diff --git a/src/api/modules/account.ts b/src/api/modules/account.ts index 9f6a573..454e013 100644 --- a/src/api/modules/account.ts +++ b/src/api/modules/account.ts @@ -34,7 +34,7 @@ export class AccountService extends BaseService { */ static createAccount( data: CreatePlatformAccountParams - ): Promise> { + ): Promise> { return this.create('/api/admin/accounts', data) } diff --git a/src/components/business/CustomerAccountDialog.vue b/src/components/business/CustomerAccountDialog.vue index ff06e99..fcc6828 100644 --- a/src/components/business/CustomerAccountDialog.vue +++ b/src/components/business/CustomerAccountDialog.vue @@ -12,7 +12,7 @@
diff --git a/src/locales/langs/en.json b/src/locales/langs/en.json index f8c7355..690335a 100644 --- a/src/locales/langs/en.json +++ b/src/locales/langs/en.json @@ -432,7 +432,7 @@ "standaloneCardList": "IoT Card Management", "iotCardTask": "IoT Card Tasks", "deviceTask": "Device Tasks", - "deviceBatchAllocation": "Device Batch Allocation", + "deviceBatchAllocation": "Device Batch Tasks", "bulkPurchase": "Bulk Package Purchase", "bulkPurchaseDetail": "Bulk Purchase Task Detail", "orderPackageInvalidateTask": "Order Package Void Tasks", diff --git a/src/locales/langs/zh.json b/src/locales/langs/zh.json index a7c2e59..027e619 100644 --- a/src/locales/langs/zh.json +++ b/src/locales/langs/zh.json @@ -370,7 +370,7 @@ "standaloneCardList": "IoT卡管理", "iotCardTask": "IoT卡任务", "deviceTask": "设备任务", - "deviceBatchAllocation": "设备批量分配", + "deviceBatchAllocation": "设备批量任务", "bulkPurchase": "批量订购套餐", "bulkPurchaseDetail": "批量订购任务详情", "orderPackageInvalidateTask": "订单套餐批量作废", diff --git a/src/router/routes/asyncRoutes.ts b/src/router/routes/asyncRoutes.ts index f697f5c..4234a07 100644 --- a/src/router/routes/asyncRoutes.ts +++ b/src/router/routes/asyncRoutes.ts @@ -441,7 +441,7 @@ export const asyncRoutes: AppRouteRecord[] = [ keepAlive: true } }, - // 设备批量分配任务 + // 设备批量任务 { path: 'device-batch-allocation', name: 'DeviceBatchAllocation', diff --git a/src/router/routesAlias.ts b/src/router/routesAlias.ts index 35df4fb..c0bc861 100644 --- a/src/router/routesAlias.ts +++ b/src/router/routesAlias.ts @@ -59,7 +59,7 @@ export enum RoutesAlias { // 任务管理 IotCardTask = '/asset-management/task-management/iot-card-task', // IoT卡任务 DeviceTask = '/asset-management/task-management/device-task', // 设备任务 - DeviceBatchAllocation = '/asset-management/task-management/device-batch-allocation', // 设备批量分配 + DeviceBatchAllocation = '/asset-management/task-management/device-batch-allocation', // 设备批量任务 BulkPurchase = '/asset-management/task-management/bulk-purchase', // 批量订购套餐 BulkPurchaseDetail = '/asset-management/task-management/bulk-purchase/detail', // 批量订购套餐详情 OrderPackageInvalidateTask = '/asset-management/task-management/order-package-invalidate-task', // 订单套餐批量作废任务 diff --git a/src/types/api/account.ts b/src/types/api/account.ts index 108e1a7..4a0b34a 100644 --- a/src/types/api/account.ts +++ b/src/types/api/account.ts @@ -12,7 +12,8 @@ export enum AccountStatus { // 账号实体(统一账号模型,匹配后端 ModelAccountResponse) export interface PlatformAccount { - ID: number + id?: number + ID?: number CreatedAt?: string UpdatedAt?: string DeletedAt?: string | null diff --git a/src/types/api/permission.ts b/src/types/api/permission.ts index abc01e0..0d046ba 100644 --- a/src/types/api/permission.ts +++ b/src/types/api/permission.ts @@ -18,7 +18,8 @@ export enum PermissionStatus { // 权限实体(匹配后端 ModelPermission) export interface Permission { - ID: number + id?: number + ID?: number CreatedAt?: string UpdatedAt?: string DeletedAt?: string | null diff --git a/src/types/api/role.ts b/src/types/api/role.ts index 9e91b39..7cbfbab 100644 --- a/src/types/api/role.ts +++ b/src/types/api/role.ts @@ -19,7 +19,7 @@ export enum RoleStatus { // 角色实体(匹配后端 ModelRole) export interface PlatformRole { id?: number - ID: number + ID?: number CreatedAt?: string UpdatedAt?: string DeletedAt?: string | null diff --git a/src/utils/business/id.ts b/src/utils/business/id.ts new file mode 100644 index 0000000..d33bdd4 --- /dev/null +++ b/src/utils/business/id.ts @@ -0,0 +1,58 @@ +/** + * 兼容后端实体 ID 字段的大小写差异。 + * 后端历史接口可能返回 `ID`,新接口返回 `id`,前端统一优先使用小写 id。 + */ +export type CompatibleId = number | string + +export interface CompatibleIdFields { + id?: CompatibleId | null + ID?: CompatibleId | null +} + +/** 从实体中读取兼容的 ID 字段。0 也是有效 ID,不能使用 ||。 */ +export const getCompatibleId = (value: CompatibleIdFields | null | undefined) => { + const id = value?.id ?? value?.ID + return id === null || id === undefined || id === '' ? undefined : id +} + +/** 读取并转换为数字 ID,供只接受 number 的接口参数使用。 */ +export const getCompatibleNumericId = ( + value: CompatibleIdFields | null | undefined +): number | undefined => { + const id = getCompatibleId(value) + if (id === undefined) return undefined + + const numericId = Number(id) + return Number.isFinite(numericId) ? numericId : undefined +} + +const isPlainObject = (value: unknown): value is Record => { + if (value === null || typeof value !== 'object') return false + const prototype = Object.getPrototypeOf(value) + return prototype === Object.prototype || prototype === null +} + +/** 递归补齐响应中的 id/ID 别名,不影响 Blob、FormData、Date 等特殊数据。 */ +export const syncCompatibleIdFields = (value: T): T => { + if (Array.isArray(value)) { + value.forEach((item) => syncCompatibleIdFields(item)) + return value + } + + if (!isPlainObject(value)) return value + + const record = value as Record + const hasId = Object.prototype.hasOwnProperty.call(record, 'id') + const hasUpperId = Object.prototype.hasOwnProperty.call(record, 'ID') + + if (hasId || hasUpperId) { + const id = record.id ?? record.ID + if (id !== null && id !== undefined && id !== '') { + if (!hasId) record.id = id + if (!hasUpperId) record.ID = id + } + } + + Object.values(record).forEach((item) => syncCompatibleIdFields(item)) + return value +} diff --git a/src/utils/business/index.ts b/src/utils/business/index.ts index a97c33b..def9e04 100644 --- a/src/utils/business/index.ts +++ b/src/utils/business/index.ts @@ -9,3 +9,4 @@ export * from './voucher' export * from './apiRateLimit' export * from './approvalSummary' export * from './expiryEstimate' +export * from './id' diff --git a/src/utils/http/index.ts b/src/utils/http/index.ts index 8f021cd..daf4bf8 100644 --- a/src/utils/http/index.ts +++ b/src/utils/http/index.ts @@ -4,6 +4,7 @@ import { useUserStore } from '@/store/modules/user' import { ApiStatus } from './status' import type { RequestOptions, ErrorMessageMode } from '@/types/api' import { normalizeApiError } from '@/utils/business/apiError' +import { syncCompatibleIdFields } from '@/utils/business/id' const axiosInstance = axios.create({ timeout: 15000, // 请求超时时间(毫秒) @@ -90,6 +91,9 @@ const processQueue = (error: any, token: string | null = null) => { // 响应拦截器 axiosInstance.interceptors.response.use( (response: AxiosResponse) => { + // 兼容历史接口返回的 ID 与新接口返回的 id。 + syncCompatibleIdFields(response.data) + // 401 未授权 - 尝试刷新 token if (response.data.code === ApiStatus.unauthorized) { const userStore = useUserStore() diff --git a/src/views/account-management/account/index.vue b/src/views/account-management/account/index.vue index 3b693f8..a4c8669 100644 --- a/src/views/account-management/account/index.vue +++ b/src/views/account-management/account/index.vue @@ -82,9 +82,9 @@ >
{{ role.role_name }} @@ -133,8 +133,15 @@