From ce1032c7f9bd3651f9ea67d3e0bdc722feaac42b Mon Sep 17 00:00:00 2001 From: sexygoat <1538832180@qq.com> Date: Sat, 28 Feb 2026 11:04:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=8C=89=E9=92=AE=E5=92=8C?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../changes/add-button-permissions/tasks.md | 2 +- src/locales/langs/en.json | 3 +- src/locales/langs/zh.json | 10 +- src/router/routes/asyncRoutes.ts | 42 ++- src/router/routesAlias.ts | 6 +- .../account-management/account/index.vue | 1 + .../enterprise-customer/index.vue | 1 + .../asset-management/asset-assign/detail.vue | 135 ++++++++ .../asset-management/asset-assign/index.vue | 87 ++--- .../authorization-records/detail.vue | 140 ++++++++ .../authorization-records/index.vue | 56 +--- .../asset-management/device-list/index.vue | 46 ++- .../asset-management/device-task/index.vue | 312 +++--------------- .../iot-card-management/index.vue | 84 +++-- .../asset-management/iot-card-task/index.vue | 265 ++++----------- src/views/common/account-list.vue | 31 +- .../order-management/order-list/detail.vue | 245 ++++++++++++++ .../order-management/order-list/index.vue | 28 +- .../package-assign/index.vue | 16 +- .../package-management/package-list/index.vue | 10 +- .../series-assign/index.vue | 10 +- src/views/product/shop/index.vue | 213 ++++++------ src/views/system/permission/index.vue | 1 + 23 files changed, 984 insertions(+), 760 deletions(-) create mode 100644 src/views/asset-management/asset-assign/detail.vue create mode 100644 src/views/asset-management/authorization-records/detail.vue create mode 100644 src/views/order-management/order-list/detail.vue diff --git a/openspec/changes/add-button-permissions/tasks.md b/openspec/changes/add-button-permissions/tasks.md index c6ad50d..81996da 100644 --- a/openspec/changes/add-button-permissions/tasks.md +++ b/openspec/changes/add-button-permissions/tasks.md @@ -90,7 +90,7 @@ - [x] **IoT卡任务页面** (`/asset-management/iot-card-task`) - ✅ 引入 `useAuth` composable - - ✅ 为"批量导入IoT卡"按钮添加 `v-permission="'lot_task:bulk_import'"` + - ✅ 为"批量导入IoT卡"按钮添加 `v-permission="''"` - ✅ 验证权限控制正确工作 - [x] **设备任务页面** (`/asset-management/device-task`) diff --git a/src/locales/langs/en.json b/src/locales/langs/en.json index 15fd372..e7f0e42 100644 --- a/src/locales/langs/en.json +++ b/src/locales/langs/en.json @@ -421,7 +421,8 @@ "withdrawalSettings": "Withdrawal Settings", "myAccount": "My Account", "carrierManagement": "Carrier Management", - "orders": "Order Management" + "orders": "Order Management", + "orderDetail": "Order Details" }, "deviceManagement": { "title": "Device Management", diff --git a/src/locales/langs/zh.json b/src/locales/langs/zh.json index 79856e5..236b334 100644 --- a/src/locales/langs/zh.json +++ b/src/locales/langs/zh.json @@ -448,13 +448,16 @@ "standaloneCardList": "IoT卡管理", "iotCardTask": "IoT卡任务", "deviceTask": "设备任务", + "taskDetail": "任务详情", "devices": "设备管理", "deviceDetail": "设备详情", "assetAssign": "分配记录", + "assetAssignDetail": "资产分配详情", "allocationRecordDetail": "分配记录详情", "cardReplacementRequest": "换卡申请", "authorizationRecords": "授权记录", "authorizationDetail": "授权记录详情", + "authorizationRecordDetail": "授权记录详情", "enterpriseDevices": "企业设备列表" }, "account": { @@ -462,7 +465,8 @@ "customerAccount": "客户账号", "myAccount": "我的账户", "carrierManagement": "运营商管理", - "orders": "订单管理" + "orders": "订单管理", + "orderDetail": "订单详情" }, "commission": { "menu": { @@ -470,7 +474,7 @@ "withdrawal": "提现审批", "withdrawalSettings": "提现配置", "myCommission": "我的佣金", - "agentCommission": "代理商佣金管理" + "agentCommission": "代理商佣金" } }, "settings": { @@ -605,7 +609,7 @@ "withdrawal": "提现审批", "withdrawalSettings": "提现配置", "myCommission": "我的佣金", - "agentCommission": "代理商佣金管理" + "agentCommission": "代理商佣金" }, "table": { "withdrawalNo": "提现单号", diff --git a/src/router/routes/asyncRoutes.ts b/src/router/routes/asyncRoutes.ts index bddc38e..701bf3d 100644 --- a/src/router/routes/asyncRoutes.ts +++ b/src/router/routes/asyncRoutes.ts @@ -1014,6 +1014,16 @@ export const asyncRoutes: AppRouteRecord[] = [ keepAlive: true } }, + { + path: 'task-detail', + name: 'TaskDetail', + component: RoutesAlias.TaskDetail, + meta: { + title: 'menus.assetManagement.taskDetail', + isHide: true, + keepAlive: false + } + }, { path: 'devices', name: 'DeviceList', @@ -1042,6 +1052,16 @@ export const asyncRoutes: AppRouteRecord[] = [ keepAlive: true } }, + { + path: 'asset-assign/detail/:id', + name: 'AssetAssignDetail', + component: RoutesAlias.AssetAssignDetail, + meta: { + title: 'menus.assetManagement.assetAssignDetail', + isHide: true, + keepAlive: false + } + }, // { // path: 'card-replacement-request', // name: 'CardReplacementRequest', @@ -1060,6 +1080,16 @@ export const asyncRoutes: AppRouteRecord[] = [ keepAlive: true } }, + { + path: 'authorization-records/detail/:id', + name: 'AuthorizationRecordDetail', + component: RoutesAlias.AuthorizationRecordDetail, + meta: { + title: 'menus.assetManagement.authorizationRecordDetail', + isHide: true, + keepAlive: false + } + }, { path: 'enterprise-devices', name: 'EnterpriseDevices', @@ -1093,11 +1123,21 @@ export const asyncRoutes: AppRouteRecord[] = [ { path: 'orders', name: 'OrderManagement', - component: RoutesAlias.OrderList, + component: '/order-management/order-list', meta: { title: 'menus.account.orders', keepAlive: true } + }, + { + path: 'orders/detail/:id', + name: 'OrderDetail', + component: '/order-management/order-list/detail', + meta: { + title: 'menus.account.orderDetail', + isHide: true, + keepAlive: false + } } // { // path: 'my-account', diff --git a/src/router/routesAlias.ts b/src/router/routesAlias.ts index 6c70969..fec9310 100644 --- a/src/router/routesAlias.ts +++ b/src/router/routesAlias.ts @@ -99,18 +99,22 @@ export enum RoutesAlias { StandaloneCardList = '/asset-management/iot-card-management', // IoT卡管理 IotCardTask = '/asset-management/iot-card-task', // IoT卡任务 DeviceTask = '/asset-management/device-task', // 设备任务 + TaskDetail = '/asset-management/task-detail', // 任务详情(IoT卡/设备任务详情) DeviceList = '/asset-management/device-list', // 设备列表 DeviceDetail = '/asset-management/device-detail', // 设备详情 AssetAssign = '/asset-management/asset-assign', // 资产分配(分配记录) + AssetAssignDetail = '/asset-management/asset-assign/detail', // 资产分配详情 CardReplacementRequest = '/asset-management/card-replacement-request', // 换卡申请 AuthorizationRecords = '/asset-management/authorization-records', // 授权记录 + AuthorizationRecordDetail = '/asset-management/authorization-records/detail', // 授权记录详情 EnterpriseDevices = '/asset-management/enterprise-devices', // 企业设备列表 // 账户管理 CustomerAccountList = '/finance/customer-account', // 客户账号 MyAccount = '/finance/my-account', // 我的账户 CarrierManagement = '/finance/carrier-management', // 运营商管理 - OrderList = '/order-management/order-list', // 订单管理 + OrderList = '/account/orders', // 订单管理 + OrderDetail = '/account/orders/detail', // 订单详情 // 佣金管理 WithdrawalApproval = '/finance/commission/withdrawal-approval', // 提现审批 diff --git a/src/views/account-management/account/index.vue b/src/views/account-management/account/index.vue index 0a94818..f663a56 100644 --- a/src/views/account-management/account/index.vue +++ b/src/views/account-management/account/index.vue @@ -475,6 +475,7 @@ activeText: getStatusText(CommonStatus.ENABLED), inactiveText: getStatusText(CommonStatus.DISABLED), inlinePrompt: true, + disabled: !hasAuth('account:modify_status'), 'onUpdate:modelValue': (val: string | number | boolean) => handleStatusChange(row, val as number) }) diff --git a/src/views/account-management/enterprise-customer/index.vue b/src/views/account-management/enterprise-customer/index.vue index 1c2b880..1d1a964 100644 --- a/src/views/account-management/enterprise-customer/index.vue +++ b/src/views/account-management/enterprise-customer/index.vue @@ -450,6 +450,7 @@ activeText: '启用', inactiveText: '禁用', inlinePrompt: true, + disabled: !hasAuth('enterprise_customer:status'), 'onUpdate:modelValue': (val: string | number | boolean) => handleStatusChange(row, val as number) }) diff --git a/src/views/asset-management/asset-assign/detail.vue b/src/views/asset-management/asset-assign/detail.vue new file mode 100644 index 0000000..f40bdb7 --- /dev/null +++ b/src/views/asset-management/asset-assign/detail.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/src/views/asset-management/asset-assign/index.vue b/src/views/asset-management/asset-assign/index.vue index 0f453ee..548640a 100644 --- a/src/views/asset-management/asset-assign/index.vue +++ b/src/views/asset-management/asset-assign/index.vue @@ -30,45 +30,20 @@ :marginTop="10" @size-change="handleSizeChange" @current-change="handleCurrentChange" + @row-contextmenu="handleRowContextMenu" > - - - - {{ currentRecord.allocation_no }} - - - {{ currentRecord.allocation_name }} - - - - - {{ currentRecord.asset_type_name }} - - - {{ currentRecord.asset_identifier }} - {{ currentRecord.from_owner_name }} - {{ currentRecord.to_owner_name }} - {{ currentRecord.operator_name }} - {{ currentRecord.related_card_count }} - {{ formatDateTime(currentRecord.created_at) }} - {{ currentRecord.remark || '--' }} - - - + + @@ -81,16 +56,21 @@ import { ElMessage, ElTag } from 'element-plus' import type { SearchFormItem } from '@/types' import { useCheckedColumns } from '@/composables/useCheckedColumns' + import { useAuth } from '@/composables/useAuth' import { formatDateTime } from '@/utils/business/format' import type { AssetAllocationRecord, AllocationTypeEnum, AssetTypeEnum } from '@/types/api/card' + import { RoutesAlias } from '@/router/routesAlias' + import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue' + import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue' defineOptions({ name: 'AssetAllocationRecords' }) + const { hasAuth } = useAuth() const router = useRouter() const loading = ref(false) - const detailDialogVisible = ref(false) const tableRef = ref() - const currentRecord = ref(null) + const contextMenuRef = ref>() + const currentRow = ref(null) // 搜索表单初始值 const initialSearchState = { @@ -205,7 +185,7 @@ { prop: 'allocation_no', label: '分配单号', - minWidth: 180 + minWidth: 200 }, { prop: 'allocation_name', @@ -338,8 +318,39 @@ // 查看详情 const viewDetail = (row: AssetAllocationRecord) => { - currentRecord.value = row - detailDialogVisible.value = true + router.push({ + path: `${RoutesAlias.AssetAssign}/detail/${row.id}` + }) + } + + // 右键菜单项配置 + const contextMenuItems = computed((): MenuItemType[] => { + const items: MenuItemType[] = [] + + if (hasAuth('asset_assign:view_detail')) { + items.push({ key: 'detail', label: '详情' }) + } + + return items + }) + + // 处理表格行右键菜单 + const handleRowContextMenu = (row: AssetAllocationRecord, column: any, event: MouseEvent) => { + event.preventDefault() + event.stopPropagation() + currentRow.value = row + contextMenuRef.value?.show(event) + } + + // 处理右键菜单选择 + const handleContextMenuSelect = (item: MenuItemType) => { + if (!currentRow.value) return + + switch (item.key) { + case 'detail': + viewDetail(currentRow.value) + break + } } diff --git a/src/views/asset-management/authorization-records/detail.vue b/src/views/asset-management/authorization-records/detail.vue new file mode 100644 index 0000000..93d5e62 --- /dev/null +++ b/src/views/asset-management/authorization-records/detail.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/src/views/asset-management/authorization-records/index.vue b/src/views/asset-management/authorization-records/index.vue index 95ce03a..fda893f 100644 --- a/src/views/asset-management/authorization-records/index.vue +++ b/src/views/asset-management/authorization-records/index.vue @@ -45,50 +45,6 @@ @select="handleContextMenuSelect" /> - - - - {{ - currentRecord.enterprise_id - }} - {{ - currentRecord.enterprise_name - }} - {{ currentRecord.card_id }} - {{ currentRecord.iccid }} - {{ - currentRecord.msisdn || '--' - }} - {{ - currentRecord.authorized_by - }} - {{ - currentRecord.authorizer_name - }} - - - {{ getAuthorizerTypeText(currentRecord.authorizer_type) }} - - - {{ - formatDateTime(currentRecord.authorized_at) - }} - - - {{ getStatusText(currentRecord.status) }} - - - {{ - currentRecord.remark || '--' - }} - - - - @@ -136,19 +92,18 @@ AuthorizerType } from '@/types/api/authorization' import { CommonStatus } from '@/config/constants' + import { RoutesAlias } from '@/router/routesAlias' defineOptions({ name: 'AuthorizationRecords' }) const { hasAuth } = useAuth() const router = useRouter() const loading = ref(false) - const detailDialogVisible = ref(false) const remarkDialogVisible = ref(false) const remarkLoading = ref(false) const tableRef = ref() const remarkFormRef = ref() const currentRecordId = ref(0) - const currentRecord = ref(null) const contextMenuRef = ref>() const currentRow = ref(null) @@ -394,8 +349,9 @@ // 查看详情 const viewDetail = (row: AuthorizationItem) => { - currentRecord.value = row - detailDialogVisible.value = true + router.push({ + path: `${RoutesAlias.AuthorizationRecords}/detail/${row.id}` + }) } // 显示修改备注对话框 @@ -433,7 +389,9 @@ const contextMenuItems = computed((): MenuItemType[] => { const items: MenuItemType[] = [] - items.push({ key: 'detail', label: '详情' }) + if (hasAuth('authorization_records:view_detail')) { + items.push({ key: 'detail', label: '详情' }) + } if (hasAuth('authorization_records:update_remark')) { items.push({ key: 'edit', label: '编辑' }) diff --git a/src/views/asset-management/device-list/index.vue b/src/views/asset-management/device-list/index.vue index cc947db..1dd7753 100644 --- a/src/views/asset-management/device-list/index.vue +++ b/src/views/asset-management/device-list/index.vue @@ -21,14 +21,14 @@ type="primary" @click="handleBatchAllocate" :disabled="!selectedDevices.length" - v-permission="'devices:batch_allocation'" + v-permission="'device:batch_allocate'" > 批量分配 批量回收 @@ -36,7 +36,7 @@ type="info" @click="handleBatchSetSeries" :disabled="!selectedDevices.length" - v-permission="'devices:batch_setting'" + v-permission="'device:batch_set_series'" > 批量设置套餐系列 @@ -1625,37 +1625,49 @@ const items: MenuItemType[] = [] // 添加查看卡片到菜单最前面 - if (hasAuth('devices:look_binding')) { + if (hasAuth('device:view_cards')) { items.push({ key: 'view-cards', label: '查看卡片' }) } - items.push( - { + if (hasAuth('device:reboot')) { + items.push({ key: 'reboot', label: '重启设备' - }, - { + }) + } + + if (hasAuth('device:factory_reset')) { + items.push({ key: 'reset', label: '恢复出厂' - }, - { + }) + } + + if (hasAuth('device:set_speed_limit')) { + items.push({ key: 'speed-limit', label: '设置限速' - }, - { + }) + } + + if (hasAuth('device:switch_sim')) { + items.push({ key: 'switch-card', label: '切换SIM卡' - }, - { + }) + } + + if (hasAuth('device:set_wifi')) { + items.push({ key: 'set-wifi', label: '设置WiFi' - } - ) + }) + } - if (hasAuth('devices:delete')) { + if (hasAuth('device:delete')) { items.push({ key: 'delete', label: '删除设备' diff --git a/src/views/asset-management/device-task/index.vue b/src/views/asset-management/device-task/index.vue index ed348d6..e0bce65 100644 --- a/src/views/asset-management/device-task/index.vue +++ b/src/views/asset-management/device-task/index.vue @@ -107,122 +107,12 @@ - - - - {{ - currentDetail.task_no - }} - - {{ currentDetail.status_text }} - - {{ currentDetail.batch_no }} - {{ - currentDetail.file_name - }} - {{ currentDetail.total_count }} - - {{ currentDetail.success_count }} - - {{ currentDetail.skip_count }} - - {{ currentDetail.fail_count }} - - - {{ currentDetail.warning_count }} - - {{ currentDetail.started_at }} - {{ currentDetail.completed_at }} - {{ currentDetail.created_at }} - {{ - currentDetail.error_message - }} - - - 跳过明细 -
- - - - - - - -
- - - 警告明细 -
- - - - - - - -
- - - 失败明细 -
- - - - - - - -
- - - -
+ + diff --git a/src/views/order-management/order-list/index.vue b/src/views/order-management/order-list/index.vue index 72a52f0..b86f811 100644 --- a/src/views/order-management/order-list/index.vue +++ b/src/views/order-management/order-list/index.vue @@ -273,6 +273,7 @@ diff --git a/src/views/system/permission/index.vue b/src/views/system/permission/index.vue index 3fbf8b9..1a69cc1 100644 --- a/src/views/system/permission/index.vue +++ b/src/views/system/permission/index.vue @@ -5,6 +5,7 @@