From aec2a27a65e9aa110ba39a180f967c3ed7c78006 Mon Sep 17 00:00:00 2001 From: luo Date: Tue, 29 Sep 2026 16:07:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=87=AD=E8=AF=81=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../proposal.md | 4 +- .../business-user-group-management/spec.md | 27 ++ .../tasks.md | 7 + src/components/business/VoucherUpload.vue | 5 + src/router/routes/asyncRoutes.ts | 312 +++++++++--------- src/types/api/businessUserGroup.ts | 1 + src/types/components.d.ts | 1 + .../export-task-detail/index.vue | 14 +- .../task-management/task-detail/index.vue | 1 - src/views/finance/agent-recharge/index.vue | 42 ++- .../components/ApplicationFormDialog.vue | 31 +- .../business-owner-import/index.vue | 3 +- .../business-user-groups/index.vue | 63 +++- src/views/shop-management/detail/index.vue | 32 +- src/views/shop-management/list/index.vue | 49 ++- src/views/system/carrier-management/index.vue | 1 + 16 files changed, 374 insertions(+), 219 deletions(-) diff --git a/openspec/changes/update-business-user-group-members-contract/proposal.md b/openspec/changes/update-business-user-group-members-contract/proposal.md index f0adc16..954b58c 100644 --- a/openspec/changes/update-business-user-group-members-contract/proposal.md +++ b/openspec/changes/update-business-user-group-members-contract/proposal.md @@ -10,7 +10,9 @@ - 成员管理弹窗展示当前成员及成员关系信息。 - 候选账号展示 `add`、`already_member`、`move` 操作提示。 - 停用组允许查询和移除,但新增/迁移由后端拒绝并提示。 -- 用户组列表/详情使用实时成员数。 +- 用户组列表使用接口返回的实时成员数。 +- 当前成员和候选账号展示当前所属组名称、编码、启用状态,不展示内部组 ID。 +- 店铺列表和详情展示业务用户组编码、名称、启用状态和业务线,不展示内部组 ID。 ## Impact diff --git a/openspec/changes/update-business-user-group-members-contract/specs/business-user-group-management/spec.md b/openspec/changes/update-business-user-group-members-contract/specs/business-user-group-management/spec.md index b6a2264..c7e1166 100644 --- a/openspec/changes/update-business-user-group-members-contract/specs/business-user-group-management/spec.md +++ b/openspec/changes/update-business-user-group-members-contract/specs/business-user-group-management/spec.md @@ -1,5 +1,32 @@ ## ADDED Requirements +### Requirement: Business User Group Metadata Visibility + +The frontend SHALL display business user group metadata returned by shop and membership APIs while omitting internal group IDs from these views. + +#### Scenario: Show business group fields for shops + +- **WHEN** an administrator views the shop list or shop details +- **THEN** the frontend displays the business group code, name, enabled state, and business line returned by the API +- **AND** the frontend does not display the business group ID + +#### Scenario: Show current group fields for members and candidates + +- **WHEN** an administrator views current members or candidate accounts in the group drawer +- **THEN** the frontend displays each account's current group code, name, and enabled state +- **AND** displays "未分组" when the account has no current group +- **AND** the frontend does not display the current group ID + +#### Scenario: Show current member count + +- **WHEN** an administrator views the business user group list +- **THEN** the frontend displays the `member_count` returned for each group + +#### Scenario: Keep member selection and username visible + +- **WHEN** an administrator scrolls horizontally in either member or candidate table +- **THEN** the selection checkbox and username columns remain fixed on the left + ### Requirement: Incremental Business User Group Membership The frontend SHALL use the member query, candidate query, incremental POST add/move, and scoped DELETE remove contracts from the modification document. diff --git a/openspec/changes/update-business-user-group-members-contract/tasks.md b/openspec/changes/update-business-user-group-members-contract/tasks.md index a3af25b..87058f6 100644 --- a/openspec/changes/update-business-user-group-members-contract/tasks.md +++ b/openspec/changes/update-business-user-group-members-contract/tasks.md @@ -12,3 +12,10 @@ ## 3. Verification - [ ] 3.1 运行类型检查、lint、编码检查、构建和 OpenSpec 校验。 + +## 4. Metadata Display + +- [x] 4.1 在店铺列表和详情中展示业务用户组编码、名称、启用状态及业务线,不展示组 ID。 +- [x] 4.2 在成员与候选账号表中展示当前组编码、名称及启用状态,不展示组 ID。 +- [x] 4.3 在业务用户组列表中展示接口返回的成员数。 +- [x] 4.4 成员和候选账号表横向滚动时固定勾选框与用户名列在左侧。 diff --git a/src/components/business/VoucherUpload.vue b/src/components/business/VoucherUpload.vue index 4b92689..9f5a724 100644 --- a/src/components/business/VoucherUpload.vue +++ b/src/components/business/VoucherUpload.vue @@ -160,6 +160,11 @@ .filter(Boolean) : [] + const currentKeys = Array.from(voucherFileKeyMap.values()) + const isEchoOfCurrentValue = + keys.length === currentKeys.length && keys.every((key, index) => key === currentKeys[index]) + if (isEchoOfCurrentValue) return + voucherFileKeyMap.clear() keys.slice(0, getMaxCount()).forEach((key, index) => { voucherFileKeyMap.set(index + 1, key) diff --git a/src/router/routes/asyncRoutes.ts b/src/router/routes/asyncRoutes.ts index af6d78c..a654525 100644 --- a/src/router/routes/asyncRoutes.ts +++ b/src/router/routes/asyncRoutes.ts @@ -646,164 +646,166 @@ export const asyncRoutes: AppRouteRecord[] = [ permissions: [BULK_PURCHASE_PERMISSIONS.detail], keepAlive: false } - }, - // 导出管理 + } + ] + }, + + // 导出管理 + { + path: '/asset-management/export-task-management', + name: 'ExportTaskManagement', + component: RoutesAlias.Home, + meta: { + title: 'menus.assetManagement.exportTaskManagement', + icon: '', + keepAlive: true + }, + children: [ { - path: 'export-task-management', - name: 'ExportTaskManagement', - component: '', + path: 'export-device', + name: 'ExportDeviceTaskList', + component: RoutesAlias.ExportDeviceTaskList, meta: { - title: 'menus.assetManagement.exportTaskManagement', + title: 'menus.assetManagement.exportDevice', + exportTaskScene: 'device', keepAlive: true - }, - children: [ - { - path: 'export-device', - name: 'ExportDeviceTaskList', - component: RoutesAlias.ExportDeviceTaskList, - meta: { - title: 'menus.assetManagement.exportDevice', - exportTaskScene: 'device', - keepAlive: true - } - }, - { - path: 'export-iot-card', - name: 'ExportIotCardTaskList', - component: RoutesAlias.ExportIotCardTaskList, - meta: { - title: 'menus.assetManagement.exportIotCard', - exportTaskScene: 'iot_card', - keepAlive: true - } - }, - { - path: 'export-order', - name: 'ExportOrderTaskList', - component: RoutesAlias.ExportOrderTaskList, - meta: { - title: 'menus.assetManagement.exportOrder', - exportTaskScene: 'order', - keepAlive: true - } - }, - { - path: 'export-package', - name: 'ExportPackageTaskList', - component: RoutesAlias.ExportPackageTaskList, - meta: { - title: 'menus.assetManagement.exportPackage', - exportTaskScene: 'package', - keepAlive: true - } - }, - { - path: 'export-agent-wallet-transaction', - name: 'ExportAgentWalletTransactionTaskList', - component: RoutesAlias.ExportAgentWalletTransactionTaskList, - meta: { - title: 'menus.assetManagement.exportAgentWalletTransaction', - exportTaskScene: 'agent_wallet_transaction', - keepAlive: true - } - }, - { - path: 'export-refund', - name: 'ExportRefundTaskList', - component: RoutesAlias.ExportRefundTaskList, - meta: { - title: 'menus.assetManagement.exportRefund', - exportTaskScene: 'refund', - keepAlive: true - } - }, - { - path: 'export-agent-recharge', - name: 'ExportAgentRechargeTaskList', - component: RoutesAlias.ExportAgentRechargeTaskList, - meta: { - title: 'menus.assetManagement.exportAgentRecharge', - exportTaskScene: 'agent_recharge', - keepAlive: true - } - }, - { - path: 'export-exchange', - name: 'ExportExchangeTaskList', - component: RoutesAlias.ExportExchangeTaskList, - meta: { - title: 'menus.assetManagement.exportExchange', - exportTaskScene: 'exchange', - keepAlive: true - } - }, - { - path: 'export-commission-record', - name: 'ExportCommissionRecordTaskList', - component: RoutesAlias.ExportCommissionRecordTaskList, - meta: { - title: 'menus.assetManagement.exportCommissionRecord', - exportTaskScene: 'commission_record', - keepAlive: true, - permissions: [EXPORT_TASK_SCENE_CONFIG.commission_record.permissions.page] - } - }, - { - path: 'export-package-traffic-alert', - name: 'ExportPackageTrafficAlertTaskList', - component: RoutesAlias.ExportPackageTrafficAlertTaskList, - meta: { - title: 'menus.assetManagement.exportPackageTrafficAlert', - exportTaskScene: 'package_traffic_alert', - keepAlive: true, - permissions: [EXPORT_TASK_SCENE_CONFIG.package_traffic_alert.permissions.page] - } - }, - { - path: 'export-expiring-asset', - name: 'ExportExpiringAssetTaskList', - component: RoutesAlias.ExportExpiringAssetTaskList, - meta: { - title: 'menus.assetManagement.exportExpiringAsset', - exportTaskScene: 'expiring_asset', - keepAlive: true, - permissions: [EXPORT_TASK_SCENE_CONFIG.expiring_asset.permissions.page] - } - }, - { - path: 'export-operations-activation', - name: 'ExportOperationsActivationTaskList', - component: RoutesAlias.ExportOperationsActivationTaskList, - meta: { - title: 'menus.assetManagement.exportOperationsActivation', - exportTaskScene: 'operations_activation', - keepAlive: true, - permissions: [EXPORT_TASK_SCENE_CONFIG.operations_activation.permissions.page] - } - }, - { - path: 'export-operations-renewal', - name: 'ExportOperationsRenewalTaskList', - component: RoutesAlias.ExportOperationsRenewalTaskList, - meta: { - title: 'menus.assetManagement.exportOperationsRenewal', - exportTaskScene: 'operations_renewal', - keepAlive: true, - permissions: [EXPORT_TASK_SCENE_CONFIG.operations_renewal.permissions.page] - } - }, - { - path: 'export-task-detail', - name: 'ExportTaskDetail', - component: RoutesAlias.ExportTaskDetail, - meta: { - title: 'menus.assetManagement.exportTaskDetail', - isHide: true, - keepAlive: false, - permissions: [EXPORT_TASK_DETAIL_PAGE_PERMISSION] - } - } - ] + } + }, + { + path: 'export-iot-card', + name: 'ExportIotCardTaskList', + component: RoutesAlias.ExportIotCardTaskList, + meta: { + title: 'menus.assetManagement.exportIotCard', + exportTaskScene: 'iot_card', + keepAlive: true + } + }, + { + path: 'export-order', + name: 'ExportOrderTaskList', + component: RoutesAlias.ExportOrderTaskList, + meta: { + title: 'menus.assetManagement.exportOrder', + exportTaskScene: 'order', + keepAlive: true + } + }, + { + path: 'export-package', + name: 'ExportPackageTaskList', + component: RoutesAlias.ExportPackageTaskList, + meta: { + title: 'menus.assetManagement.exportPackage', + exportTaskScene: 'package', + keepAlive: true + } + }, + { + path: 'export-agent-wallet-transaction', + name: 'ExportAgentWalletTransactionTaskList', + component: RoutesAlias.ExportAgentWalletTransactionTaskList, + meta: { + title: 'menus.assetManagement.exportAgentWalletTransaction', + exportTaskScene: 'agent_wallet_transaction', + keepAlive: true + } + }, + { + path: 'export-refund', + name: 'ExportRefundTaskList', + component: RoutesAlias.ExportRefundTaskList, + meta: { + title: 'menus.assetManagement.exportRefund', + exportTaskScene: 'refund', + keepAlive: true + } + }, + { + path: 'export-agent-recharge', + name: 'ExportAgentRechargeTaskList', + component: RoutesAlias.ExportAgentRechargeTaskList, + meta: { + title: 'menus.assetManagement.exportAgentRecharge', + exportTaskScene: 'agent_recharge', + keepAlive: true + } + }, + { + path: 'export-exchange', + name: 'ExportExchangeTaskList', + component: RoutesAlias.ExportExchangeTaskList, + meta: { + title: 'menus.assetManagement.exportExchange', + exportTaskScene: 'exchange', + keepAlive: true + } + }, + { + path: 'export-commission-record', + name: 'ExportCommissionRecordTaskList', + component: RoutesAlias.ExportCommissionRecordTaskList, + meta: { + title: 'menus.assetManagement.exportCommissionRecord', + exportTaskScene: 'commission_record', + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.commission_record.permissions.page] + } + }, + { + path: 'export-package-traffic-alert', + name: 'ExportPackageTrafficAlertTaskList', + component: RoutesAlias.ExportPackageTrafficAlertTaskList, + meta: { + title: 'menus.assetManagement.exportPackageTrafficAlert', + exportTaskScene: 'package_traffic_alert', + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.package_traffic_alert.permissions.page] + } + }, + { + path: 'export-expiring-asset', + name: 'ExportExpiringAssetTaskList', + component: RoutesAlias.ExportExpiringAssetTaskList, + meta: { + title: 'menus.assetManagement.exportExpiringAsset', + exportTaskScene: 'expiring_asset', + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.expiring_asset.permissions.page] + } + }, + { + path: 'export-operations-activation', + name: 'ExportOperationsActivationTaskList', + component: RoutesAlias.ExportOperationsActivationTaskList, + meta: { + title: 'menus.assetManagement.exportOperationsActivation', + exportTaskScene: 'operations_activation', + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.operations_activation.permissions.page] + } + }, + { + path: 'export-operations-renewal', + name: 'ExportOperationsRenewalTaskList', + component: RoutesAlias.ExportOperationsRenewalTaskList, + meta: { + title: 'menus.assetManagement.exportOperationsRenewal', + exportTaskScene: 'operations_renewal', + keepAlive: true, + permissions: [EXPORT_TASK_SCENE_CONFIG.operations_renewal.permissions.page] + } + }, + { + path: 'export-task-detail', + name: 'ExportTaskDetail', + component: RoutesAlias.ExportTaskDetail, + meta: { + title: 'menus.assetManagement.exportTaskDetail', + isHide: true, + keepAlive: false, + permissions: [EXPORT_TASK_DETAIL_PAGE_PERMISSION] + } } ] }, diff --git a/src/types/api/businessUserGroup.ts b/src/types/api/businessUserGroup.ts index f422ceb..db1bf65 100644 --- a/src/types/api/businessUserGroup.ts +++ b/src/types/api/businessUserGroup.ts @@ -91,6 +91,7 @@ export interface BusinessUserGroupMember { current_group_id?: number | null current_group_code?: string | null current_group_name?: string | null + current_group_enabled?: boolean | null operation?: 'add' | 'already_member' | 'move' | string operation_name?: string | null } diff --git a/src/types/components.d.ts b/src/types/components.d.ts index 38471c6..3f99d59 100644 --- a/src/types/components.d.ts +++ b/src/types/components.d.ts @@ -123,6 +123,7 @@ declare module 'vue' { ElOption: typeof import('element-plus/es')['ElOption'] ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopover: typeof import('element-plus/es')['ElPopover'] + ElProgress: typeof import('element-plus/es')['ElProgress'] ElRadio: typeof import('element-plus/es')['ElRadio'] ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElResult: typeof import('element-plus/es')['ElResult'] diff --git a/src/views/asset-management/export-task-management/export-task-detail/index.vue b/src/views/asset-management/export-task-management/export-task-detail/index.vue index 339b33b..6c18ca5 100644 --- a/src/views/asset-management/export-task-management/export-task-detail/index.vue +++ b/src/views/asset-management/export-task-management/export-task-detail/index.vue @@ -10,11 +10,6 @@ 返回

导出任务详情

-
- - 下载文件 - -
@@ -203,8 +198,7 @@ label: '下载地址', fullWidth: true, render: (data: ExportTaskDetail) => { - if (!data.download_url) return h('span', '-') - if (!canDownloadTask.value) return h('span', '-') + if (!data.download_url || !canDownloadTask.value) return h('span', '-') return h( ElButton, { @@ -276,12 +270,6 @@ font-weight: 600; color: var(--el-text-color-primary); } - - .detail-actions { - display: flex; - gap: 10px; - margin-left: auto; - } } .detail-loading { diff --git a/src/views/asset-management/task-management/task-detail/index.vue b/src/views/asset-management/task-management/task-detail/index.vue index 6deb027..3e4191f 100644 --- a/src/views/asset-management/task-management/task-detail/index.vue +++ b/src/views/asset-management/task-management/task-detail/index.vue @@ -96,7 +96,6 @@ const taskDetail = ref(null) const taskType = ref('card') const loading = ref(false) - const getOperationLabel = (operationType?: DeviceImportTaskOperationType) => { switch (operationType) { case 'assign_shop': diff --git a/src/views/finance/agent-recharge/index.vue b/src/views/finance/agent-recharge/index.vue index 6bd8d9b..34e0b3c 100644 --- a/src/views/finance/agent-recharge/index.vue +++ b/src/views/finance/agent-recharge/index.vue @@ -129,7 +129,7 @@ 识别凭证 @@ -359,7 +359,7 @@