diff --git a/openspec/changes/add-carrier-management/proposal.md b/openspec/changes/add-carrier-management/proposal.md new file mode 100644 index 0000000..e6579ed --- /dev/null +++ b/openspec/changes/add-carrier-management/proposal.md @@ -0,0 +1,38 @@ +# Change: 新增运营商管理功能 + +## Why + +当前系统缺少对运营商基础信息的统一管理能力。需要提供一个集中的运营商管理模块,用于维护运营商的基础信息(名称、编码、类型、描述等),以便后续在网卡、套餐等业务模块中关联使用。 + +运营商管理是物联网卡管理系统的基础数据模块,需要支持对运营商的 CRUD 操作以及状态管理,方便运营人员统一维护运营商信息。 + +## What Changes + +- 新增运营商管理 API 服务层(CarrierService) +- 新增运营商相关 TypeScript 类型定义 +- 新增运营商管理页面,支持以下功能: + - 运营商列表查询(支持按名称、类型、状态筛选) + - 创建运营商 + - 编辑运营商信息 + - 删除运营商 + - 状态切换(启用/禁用) + - 查看运营商详情 +- 新增运营商类型常量配置(CMCC/CUCC/CTCC/CBN) +- 在账户管理菜单下新增运营商管理入口 +- 新增路由配置 + +## Impact + +- **新增文件**: + - `src/api/modules/carrier.ts` - API 服务层 + - `src/types/api/carrier.ts` - TypeScript 类型定义 + - `src/views/finance/carrier-management/index.vue` - 运营商管理页面 + - `src/config/constants/carrierTypes.ts` - 运营商类型常量 +- **修改文件**: + - `src/api/modules/index.ts` - 导出 CarrierService + - `src/types/api/index.ts` - 导出 carrier 类型 + - `src/router/routesAlias.ts` - 新增路由别名 + - `src/router/routes/asyncRoutes.ts` - 新增路由配置 + - `src/config/constants/index.ts` - 导出运营商类型常量 +- **受影响的业务模块**: 账户管理 +- **不涉及破坏性变更** diff --git a/openspec/changes/add-carrier-management/specs/carrier-management/spec.md b/openspec/changes/add-carrier-management/specs/carrier-management/spec.md new file mode 100644 index 0000000..6551ca2 --- /dev/null +++ b/openspec/changes/add-carrier-management/specs/carrier-management/spec.md @@ -0,0 +1,200 @@ +# Carrier Management Specification + +## ADDED Requirements + +### Requirement: 运营商列表查询 + +系统 SHALL 提供运营商列表查询功能,支持分页和多条件筛选。 + +#### Scenario: 获取所有运营商列表 + +- **WHEN** 用户访问运营商管理页面 +- **THEN** 系统应显示运营商列表,包含运营商 ID、名称、编码、类型、描述、状态、创建时间、更新时间 +- **AND** 列表应支持分页展示 + +#### Scenario: 按运营商名称模糊搜索 + +- **WHEN** 用户在搜索框输入运营商名称并点击搜索 +- **THEN** 系统应返回名称匹配的运营商列表 +- **AND** 支持模糊匹配 + +#### Scenario: 按运营商类型筛选 + +- **WHEN** 用户选择运营商类型(CMCC/CUCC/CTCC/CBN)并点击搜索 +- **THEN** 系统应返回指定类型的运营商列表 + +#### Scenario: 按状态筛选 + +- **WHEN** 用户选择状态(启用/禁用)并点击搜索 +- **THEN** 系统应返回指定状态的运营商列表 + +#### Scenario: 组合条件筛选 + +- **WHEN** 用户同时指定多个筛选条件 +- **THEN** 系统应返回满足所有条件的运营商列表 + +### Requirement: 创建运营商 + +系统 SHALL 提供创建运营商的功能,允许运营人员添加新的运营商信息。 + +#### Scenario: 成功创建运营商 + +- **WHEN** 用户点击"新增运营商"按钮并填写完整的必填信息(运营商编码、运营商名称、运营商类型) +- **THEN** 系统应创建新的运营商记录 +- **AND** 显示成功消息 +- **AND** 刷新运营商列表 + +#### Scenario: 创建运营商时必填字段验证 + +- **WHEN** 用户提交创建表单但缺少必填字段 +- **THEN** 系统应显示验证错误消息 +- **AND** 阻止表单提交 + +#### Scenario: 运营商编码长度验证 + +- **WHEN** 用户输入的运营商编码长度不在 1-50 个字符之间 +- **THEN** 系统应显示验证错误消息 + +#### Scenario: 运营商名称长度验证 + +- **WHEN** 用户输入的运营商名称长度不在 1-100 个字符之间 +- **THEN** 系统应显示验证错误消息 + +#### Scenario: 运营商描述长度验证 + +- **WHEN** 用户输入的运营商描述超过 500 个字符 +- **THEN** 系统应显示验证错误消息 + +### Requirement: 编辑运营商 + +系统 SHALL 允许用户编辑现有运营商的信息。 + +#### Scenario: 成功编辑运营商 + +- **WHEN** 用户点击编辑按钮并修改运营商信息后提交 +- **THEN** 系统应更新运营商记录 +- **AND** 显示成功消息 +- **AND** 刷新运营商列表 + +#### Scenario: 编辑时只能修改名称和描述 + +- **WHEN** 用户编辑运营商时 +- **THEN** 系统应只允许修改运营商名称和描述 +- **AND** 运营商编码、运营商类型应不可修改 + +#### Scenario: 编辑时表单验证 + +- **WHEN** 用户修改运营商信息但不符合验证规则 +- **THEN** 系统应显示验证错误消息 +- **AND** 阻止表单提交 + +### Requirement: 删除运营商 + +系统 SHALL 允许用户删除运营商记录。 + +#### Scenario: 成功删除运营商 + +- **WHEN** 用户点击删除按钮并确认删除操作 +- **THEN** 系统应删除该运营商记录 +- **AND** 显示成功消息 +- **AND** 刷新运营商列表 + +#### Scenario: 删除前二次确认 + +- **WHEN** 用户点击删除按钮 +- **THEN** 系统应显示确认对话框 +- **AND** 提示用户确认删除操作 + +#### Scenario: 取消删除操作 + +- **WHEN** 用户在确认对话框中点击取消 +- **THEN** 系统应取消删除操作 +- **AND** 保留运营商记录 + +### Requirement: 运营商状态管理 + +系统 SHALL 提供运营商状态切换功能(启用/禁用)。 + +#### Scenario: 成功切换运营商状态 + +- **WHEN** 用户点击状态开关 +- **THEN** 系统应立即更新运营商状态 +- **AND** 显示成功消息 +- **AND** UI 应反映新的状态 + +#### Scenario: 状态切换失败时回滚 + +- **WHEN** 状态切换请求失败 +- **THEN** 系统应恢复原状态 +- **AND** 显示错误消息 + +### Requirement: 获取运营商详情 + +系统 SHALL 提供获取单个运营商详细信息的功能。 + +#### Scenario: 成功获取运营商详情 + +- **WHEN** 系统需要获取特定运营商的详细信息 +- **THEN** 系统应返回该运营商的完整信息 +- **AND** 包含运营商 ID、编码、名称、类型、描述、状态、创建时间、更新时间 + +### Requirement: 运营商类型定义 + +系统 SHALL 支持以下运营商类型。 + +#### Scenario: 运营商类型枚举 + +- **WHEN** 系统处理运营商类型 +- **THEN** 系统应支持以下类型: + - CMCC: 中国移动 + - CUCC: 中国联通 + - CTCC: 中国电信 + - CBN: 中国广电 + +### Requirement: 数据展示和格式化 + +系统 SHALL 正确展示和格式化运营商数据。 + +#### Scenario: 运营商类型显示 + +- **WHEN** 在列表中显示运营商类型 +- **THEN** 系统应将类型代码转换为可读的中文名称 +- **AND** 使用不同的标签颜色区分不同类型 + +#### Scenario: 状态显示 + +- **WHEN** 在列表中显示运营商状态 +- **THEN** 系统应使用开关组件展示状态 +- **AND** 启用状态显示为绿色"启用" +- **AND** 禁用状态显示为红色"禁用" + +#### Scenario: 时间格式化 + +- **WHEN** 显示创建时间和更新时间 +- **THEN** 系统应将时间格式化为 YYYY-MM-DD HH:mm:ss 格式 + +### Requirement: 权限控制 + +系统 SHALL 对运营商管理功能进行权限控制。 + +#### Scenario: 基于角色的访问控制 + +- **WHEN** 用户访问运营商管理页面 +- **THEN** 系统应验证用户是否有访问权限 +- **AND** 无权限用户应被重定向到 403 页面 + +### Requirement: 错误处理 + +系统 SHALL 正确处理各种错误情况。 + +#### Scenario: API 请求失败处理 + +- **WHEN** API 请求失败 +- **THEN** 系统应显示友好的错误消息 +- **AND** 不应中断用户操作流程 + +#### Scenario: 网络错误处理 + +- **WHEN** 发生网络错误 +- **THEN** 系统应提示用户检查网络连接 +- **AND** 允许用户重试操作 diff --git a/openspec/changes/add-carrier-management/tasks.md b/openspec/changes/add-carrier-management/tasks.md new file mode 100644 index 0000000..d627f44 --- /dev/null +++ b/openspec/changes/add-carrier-management/tasks.md @@ -0,0 +1,48 @@ +# Implementation Tasks + +## 1. 类型定义和常量配置 + +- [x] 1.1 创建运营商类型定义文件 `src/types/api/carrier.ts` +- [x] 1.2 在 `src/types/api/index.ts` 中导出 carrier 类型 +- [x] 1.3 创建运营商类型常量 `src/config/constants/carrierTypes.ts` +- [x] 1.4 在 `src/config/constants/index.ts` 中导出运营商类型常量 + +## 2. API 服务层 + +- [x] 2.1 创建 CarrierService 类 `src/api/modules/carrier.ts` +- [x] 2.2 实现获取运营商列表接口(支持分页和筛选) +- [x] 2.3 实现创建运营商接口 +- [x] 2.4 实现更新运营商接口 +- [x] 2.5 实现删除运营商接口 +- [x] 2.6 实现获取运营商详情接口 +- [x] 2.7 实现更新运营商状态接口 +- [x] 2.8 在 `src/api/modules/index.ts` 中导出 CarrierService + +## 3. 路由配置 + +- [x] 3.1 在 `src/router/routesAlias.ts` 添加运营商管理路由别名 +- [x] 3.2 在 `src/router/routes/asyncRoutes.ts` 添加运营商管理路由配置 + +## 4. 运营商管理页面 + +- [x] 4.1 创建运营商管理页面组件 `src/views/finance/carrier-management/index.vue` +- [x] 4.2 实现搜索栏(运营商名称、运营商类型、状态筛选) +- [x] 4.3 实现运营商列表表格展示 +- [x] 4.4 实现列筛选和表格头部工具栏 +- [x] 4.5 实现分页功能 +- [x] 4.6 实现新增运营商对话框 +- [x] 4.7 实现编辑运营商对话框 +- [x] 4.8 实现删除运营商确认 +- [x] 4.9 实现状态开关切换 +- [x] 4.10 实现表单验证规则 +- [x] 4.11 实现数据加载和错误处理 + +## 5. 集成测试 + +- [x] 5.1 测试运营商列表查询功能(包括筛选和分页) +- [x] 5.2 测试创建运营商功能 +- [x] 5.3 测试编辑运营商功能 +- [x] 5.4 测试删除运营商功能 +- [x] 5.5 测试状态切换功能 +- [x] 5.6 验证表单验证规则是否正确 +- [x] 5.7 验证权限控制是否正确 diff --git a/src/api/modules/card.ts b/src/api/modules/card.ts index 0016224..53431b9 100644 --- a/src/api/modules/card.ts +++ b/src/api/modules/card.ts @@ -79,13 +79,21 @@ export class CardService extends BaseService { } /** - * 根据ICCID获取单卡信息 + * 根据ICCID获取单卡信息(旧接口,用于现有功能) * @param iccid ICCID */ static getCardByIccid(iccid: string): Promise> { return this.getOne(`/api/cards/iccid/${iccid}`) } + /** + * 通过ICCID查询单卡详情(新接口,用于单卡查询页面) + * @param iccid ICCID + */ + static getIotCardDetailByIccid(iccid: string): Promise> { + return this.getOne(`/api/admin/iot-cards/by-iccid/${iccid}`) + } + /** * 网卡操作(充值、停复机、增减流量等) * @param params 操作参数 diff --git a/src/api/modules/carrier.ts b/src/api/modules/carrier.ts new file mode 100644 index 0000000..29331d6 --- /dev/null +++ b/src/api/modules/carrier.ts @@ -0,0 +1,73 @@ +/** + * 运营商管理相关 API + */ + +import { BaseService } from '../BaseService' +import type { + Carrier, + CarrierQueryParams, + CreateCarrierParams, + UpdateCarrierParams, + UpdateCarrierStatusParams, + BaseResponse, + PaginationResponse +} from '@/types/api' + +export class CarrierService extends BaseService { + /** + * 获取运营商列表 + * GET /api/admin/carriers + * @param params 查询参数 + */ + static getCarriers(params?: CarrierQueryParams): Promise> { + return this.getPage('/api/admin/carriers', params) + } + + /** + * 创建运营商 + * POST /api/admin/carriers + * @param data 运营商数据 + */ + static createCarrier(data: CreateCarrierParams): Promise> { + return this.create('/api/admin/carriers', data) + } + + /** + * 更新运营商 + * PUT /api/admin/carriers/{id} + * @param id 运营商ID + * @param data 运营商数据 + */ + static updateCarrier(id: number, data: UpdateCarrierParams): Promise> { + return this.update(`/api/admin/carriers/${id}`, data) + } + + /** + * 删除运营商 + * DELETE /api/admin/carriers/{id} + * @param id 运营商ID + */ + static deleteCarrier(id: number): Promise { + return this.remove(`/api/admin/carriers/${id}`) + } + + /** + * 获取运营商详情 + * GET /api/admin/carriers/{id} + * @param id 运营商ID + */ + static getCarrierDetail(id: number): Promise> { + return this.getOne(`/api/admin/carriers/${id}`) + } + + /** + * 更新运营商状态 + * PUT /api/admin/carriers/{id}/status + * @param id 运营商ID + * @param status 状态 (1:启用, 0:禁用) + */ + static updateCarrierStatus(id: number, status: number): Promise { + const data: UpdateCarrierStatusParams = { status } + return this.update(`/api/admin/carriers/${id}/status`, data) + } +} diff --git a/src/api/modules/device.ts b/src/api/modules/device.ts index d9ae608..10af425 100644 --- a/src/api/modules/device.ts +++ b/src/api/modules/device.ts @@ -42,6 +42,14 @@ export class DeviceService extends BaseService { return this.getOne(`/api/admin/devices/${id}`) } + /** + * 通过设备号查询设备详情 + * @param imei 设备号(IMEI) + */ + static getDeviceByImei(imei: string): Promise> { + return this.getOne(`/api/admin/devices/by-imei/${imei}`) + } + /** * 删除设备 * @param id 设备ID diff --git a/src/api/modules/index.ts b/src/api/modules/index.ts index 7533151..d97805f 100644 --- a/src/api/modules/index.ts +++ b/src/api/modules/index.ts @@ -20,6 +20,7 @@ export { CustomerAccountService } from './customerAccount' export { StorageService } from './storage' export { AuthorizationService } from './authorization' export { DeviceService } from './device' +export { CarrierService } from './carrier' // TODO: 按需添加其他业务模块 // export { PackageService } from './package' diff --git a/src/config/constants/carrierTypes.ts b/src/config/constants/carrierTypes.ts new file mode 100644 index 0000000..4460fde --- /dev/null +++ b/src/config/constants/carrierTypes.ts @@ -0,0 +1,32 @@ +/** + * 运营商类型配置 + */ + +import { CarrierType } from '@/types/api' + +// 运营商类型选项 +export const CARRIER_TYPE_OPTIONS = [ + { label: '中国移动', value: CarrierType.CMCC, color: '#4CAF50' }, + { label: '中国联通', value: CarrierType.CUCC, color: '#2196F3' }, + { label: '中国电信', value: CarrierType.CTCC, color: '#FF9800' }, + { label: '中国广电', value: CarrierType.CBN, color: '#9C27B0' } +] + +// 运营商类型映射 +export const CARRIER_TYPE_MAP = CARRIER_TYPE_OPTIONS.reduce( + (map, item) => { + map[item.value] = item + return map + }, + {} as Record +) + +// 获取运营商类型标签 +export function getCarrierTypeLabel(type: CarrierType): string { + return CARRIER_TYPE_MAP[type]?.label || type +} + +// 获取运营商类型颜色 +export function getCarrierTypeColor(type: CarrierType): string { + return CARRIER_TYPE_MAP[type]?.color || '#666' +} diff --git a/src/config/constants/index.ts b/src/config/constants/index.ts index d44caa1..5f305e2 100644 --- a/src/config/constants/index.ts +++ b/src/config/constants/index.ts @@ -19,3 +19,6 @@ export * from './status' // IoT卡相关 export * from './iotCard' + +// 运营商类型相关 +export * from './carrierTypes' diff --git a/src/router/routes/asyncRoutes.ts b/src/router/routes/asyncRoutes.ts index 479f46b..5fe650b 100644 --- a/src/router/routes/asyncRoutes.ts +++ b/src/router/routes/asyncRoutes.ts @@ -834,6 +834,26 @@ export const asyncRoutes: AppRouteRecord[] = [ } ] }, + { + path: '/my-simcard', + name: 'MySimcard', + component: RoutesAlias.Home, + meta: { + title: '我的网卡', + icon: '' + }, + children: [ + { + path: 'single-card', + name: 'SingleCard', + component: RoutesAlias.SingleCard, + meta: { + title: '单卡信息', + keepAlive: true + } + } + ] + }, { path: '/asset-management', name: 'AssetManagement', @@ -844,11 +864,20 @@ export const asyncRoutes: AppRouteRecord[] = [ }, children: [ { - path: 'single-card', - name: 'SingleCard', - component: RoutesAlias.SingleCard, + path: 'card-search', + name: 'CardSearch', + component: RoutesAlias.CardSearch, meta: { - title: 'menus.assetManagement.singleCard', + title: '单卡查询', + keepAlive: true + } + }, + { + path: 'device-search', + name: 'DeviceSearch', + component: RoutesAlias.DeviceSearch, + meta: { + title: '设备查询', keepAlive: true } }, @@ -975,6 +1004,15 @@ export const asyncRoutes: AppRouteRecord[] = [ keepAlive: true } }, + { + path: 'carrier-management', + name: 'CarrierManagement', + component: RoutesAlias.CarrierManagement, + meta: { + title: '运营商管理', + keepAlive: true + } + }, // { // path: 'my-account', // name: 'MyAccount', @@ -1102,24 +1140,24 @@ export const asyncRoutes: AppRouteRecord[] = [ keepAlive: true } }, - { - path: 'offline-batch-recharge', - name: 'OfflineBatchRecharge', - component: RoutesAlias.OfflineBatchRecharge, - meta: { - title: 'menus.batch.offlineBatchRecharge', - keepAlive: true - } - }, - { - path: 'card-change-notice', - name: 'CardChangeNotice', - component: RoutesAlias.CardChangeNotice, - meta: { - title: 'menus.batch.cardChangeNotice', - keepAlive: true - } - } + // { + // path: 'offline-batch-recharge', + // name: 'OfflineBatchRecharge', + // component: RoutesAlias.OfflineBatchRecharge, + // meta: { + // title: 'menus.batch.offlineBatchRecharge', + // keepAlive: true + // } + // }, + // { + // path: 'card-change-notice', + // name: 'CardChangeNotice', + // component: RoutesAlias.CardChangeNotice, + // meta: { + // title: 'menus.batch.cardChangeNotice', + // keepAlive: true + // } + // } ] } ] diff --git a/src/router/routesAlias.ts b/src/router/routesAlias.ts index b047146..90d4c4d 100644 --- a/src/router/routesAlias.ts +++ b/src/router/routesAlias.ts @@ -90,6 +90,8 @@ export enum RoutesAlias { SimCardAssign = '/product/sim-card-assign', // 号卡分配 // 资产管理 + CardSearch = '/asset-management/card-search', // 单卡查询 + DeviceSearch = '/asset-management/device-search', // 设备查询 StandaloneCardList = '/asset-management/card-list', // 单卡列表(未绑定设备) TaskManagement = '/asset-management/task-management', // 任务管理 TaskDetail = '/asset-management/task-detail', // 任务详情 @@ -104,6 +106,7 @@ export enum RoutesAlias { // 账户管理 CustomerAccountList = '/finance/customer-account', // 客户账号 MyAccount = '/finance/my-account', // 我的账户 + CarrierManagement = '/finance/carrier-management', // 运营商管理 // 佣金管理 WithdrawalApproval = '/finance/commission/withdrawal-approval', // 提现审批 diff --git a/src/types/api/card.ts b/src/types/api/card.ts index fddef20..0b71989 100644 --- a/src/types/api/card.ts +++ b/src/types/api/card.ts @@ -449,3 +449,32 @@ export interface AssetAllocationRecord { export interface AssetAllocationRecordDetail extends AssetAllocationRecord { related_card_ids: number[] // 关联卡ID列表 } + +// ========== 单卡详情查询相关 ========== + +// IoT卡详情响应(对应 /api/admin/iot-cards/by-iccid/{iccid} 接口) +export interface IotCardDetailResponse { + id: number // 卡ID + iccid: string // ICCID + imsi: string // IMSI + msisdn: string // 卡接入号 + carrier_id: number // 运营商ID + carrier_name: string // 运营商名称 + carrier_type: string // 运营商类型 (CMCC:中国移动, CUCC:中国联通, CTCC:中国电信, CBN:中国广电) + card_type: string // 卡类型 + card_category: string // 卡业务类型 (normal:普通卡, industry:行业卡) + status: number // 状态 (1:在库, 2:已分销, 3:已激活, 4:已停用) + activation_status: number // 激活状态 (0:未激活, 1:已激活) + network_status: number // 网络状态 (0:停机, 1:开机) + real_name_status: number // 实名状态 (0:未实名, 1:已实名) + batch_no: string // 批次号 + supplier: string // 供应商 + shop_id: number | null // 店铺ID + shop_name: string // 店铺名称 + cost_price: number // 成本价(分) + distribute_price: number // 分销价(分) + data_usage_mb: number // 累计流量使用(MB) + activated_at: string | null // 激活时间 + created_at: string // 创建时间 + updated_at: string // 更新时间 +} diff --git a/src/types/api/carrier.ts b/src/types/api/carrier.ts new file mode 100644 index 0000000..fc6470d --- /dev/null +++ b/src/types/api/carrier.ts @@ -0,0 +1,51 @@ +/** + * 运营商管理相关类型定义 + */ + +import type { PaginationParams } from './common' + +// 运营商类型枚举 +export enum CarrierType { + CMCC = 'CMCC', // 中国移动 + CUCC = 'CUCC', // 中国联通 + CTCC = 'CTCC', // 中国电信 + CBN = 'CBN' // 中国广电 +} + +// 运营商响应数据 +export interface Carrier { + id: number + carrier_code: string + carrier_name: string + carrier_type: CarrierType + description?: string + status: number + created_at: string + updated_at: string +} + +// 运营商列表查询参数 +export interface CarrierQueryParams extends PaginationParams { + carrier_name?: string + carrier_type?: CarrierType + status?: number +} + +// 创建运营商请求参数 +export interface CreateCarrierParams { + carrier_code: string + carrier_name: string + carrier_type: CarrierType + description?: string +} + +// 更新运营商请求参数 +export interface UpdateCarrierParams { + carrier_name?: string + description?: string +} + +// 更新运营商状态参数 +export interface UpdateCarrierStatusParams { + status: number +} diff --git a/src/types/api/index.ts b/src/types/api/index.ts index 3482e7f..28fc6b3 100644 --- a/src/types/api/index.ts +++ b/src/types/api/index.ts @@ -52,3 +52,6 @@ export * from './authorization' // 企业卡授权相关 export * from './enterpriseCard' + +// 运营商相关 +export * from './carrier' diff --git a/src/views/asset-management/card-search/index.vue b/src/views/asset-management/card-search/index.vue new file mode 100644 index 0000000..c1644cc --- /dev/null +++ b/src/views/asset-management/card-search/index.vue @@ -0,0 +1,208 @@ + + + + + diff --git a/src/views/asset-management/device-list/index.vue b/src/views/asset-management/device-list/index.vue index a21e5c6..d43c083 100644 --- a/src/views/asset-management/device-list/index.vue +++ b/src/views/asset-management/device-list/index.vue @@ -258,14 +258,14 @@ type: 'select', config: { clearable: true, - placeholder: '请选择状态', - options: [ - { label: '在库', value: 1 }, - { label: '已分销', value: 2 }, - { label: '已激活', value: 3 }, - { label: '已停用', value: 4 } - ] - } + placeholder: '请选择状态' + }, + options: () => [ + { label: '在库', value: 1 }, + { label: '已分销', value: 2 }, + { label: '已激活', value: 3 }, + { label: '已停用', value: 4 } + ] }, { label: '批次号', diff --git a/src/views/asset-management/device-search/index.vue b/src/views/asset-management/device-search/index.vue new file mode 100644 index 0000000..53d2988 --- /dev/null +++ b/src/views/asset-management/device-search/index.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/src/views/card-management/card-detail/index.vue b/src/views/card-management/card-detail/index.vue index 7876d6f..6dd7555 100644 --- a/src/views/card-management/card-detail/index.vue +++ b/src/views/card-management/card-detail/index.vue @@ -140,18 +140,15 @@ const contextMenuItems: MenuItemType[] = [ { key: 'cardOperation', - label: '卡务操作', - icon: '' + label: '卡务操作' }, { key: 'download', - label: '下载', - icon: '' + label: '下载' }, { key: 'delete', label: '删除', - icon: '', showLine: true } ] diff --git a/src/views/finance/carrier-management/index.vue b/src/views/finance/carrier-management/index.vue new file mode 100644 index 0000000..a9cba39 --- /dev/null +++ b/src/views/finance/carrier-management/index.vue @@ -0,0 +1,464 @@ + + + + + diff --git a/src/views/my-simcard/single-card/index.vue b/src/views/my-simcard/single-card/index.vue index 2be4ca6..692fb35 100644 --- a/src/views/my-simcard/single-card/index.vue +++ b/src/views/my-simcard/single-card/index.vue @@ -177,16 +177,32 @@

主要操作

- + 套餐充值 - + 激活 - + 保号停机 - + 保号复机
@@ -293,20 +309,39 @@ ElEmpty, ElSkeleton, ElDescriptions, - ElDescriptionsItem + ElDescriptionsItem, + ElMessageBox } from 'element-plus' import { useRoute } from 'vue-router' + import { EnterpriseService } from '@/api/modules/enterprise' defineOptions({ name: 'SingleCard' }) const route = useRoute() const loading = ref(true) + const operationLoading = ref(false) + + // 从 URL 获取参数 + const enterpriseId = computed(() => { + const id = route.query.enterpriseId || route.query.enterprise_id + return id ? Number(id) : null + }) + + const cardId = computed(() => { + const urlId = route.query.cardId || route.query.card_id + if (urlId) { + return Number(urlId) + } + // 如果URL中没有,从卡片数据中获取 + return cardInfo.value?.id ? Number(cardInfo.value.id) : null + }) // 卡片信息 const cardInfo = ref(null) // 模拟卡片数据 const mockCardData = { + id: 1, // 卡片ID iccid: '8986062357007989203', accessNumber: '1440012345678', imei: '860123456789012', @@ -411,7 +446,7 @@ } // 处理操作按钮点击 - const handleOperation = (operation: string) => { + const handleOperation = async (operation: string) => { if (!cardInfo.value) { ElMessage.warning('请先查询卡片信息') return @@ -439,6 +474,75 @@ deviceOperation: '设备操作' } + // 保号停机 + if (operation === 'suspend') { + // 检查必需的参数 + if (!enterpriseId.value || !cardId.value) { + ElMessage.error('缺少必需的参数:企业ID或卡片ID') + return + } + + try { + await ElMessageBox.confirm( + `确认要对卡片 ${cardInfo.value.iccid} 进行保号停机操作吗?`, + '保号停机确认', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + } + ) + + operationLoading.value = true + await EnterpriseService.suspendCard(enterpriseId.value, cardId.value) + ElMessage.success('保号停机操作成功') + // 刷新卡片信息 + await fetchCardDetail() + } catch (error: any) { + if (error !== 'cancel') { + ElMessage.error(error?.message || '保号停机操作失败') + } + } finally { + operationLoading.value = false + } + return + } + + // 保号复机 + if (operation === 'resume') { + // 检查必需的参数 + if (!enterpriseId.value || !cardId.value) { + ElMessage.error('缺少必需的参数:企业ID或卡片ID') + return + } + + try { + await ElMessageBox.confirm( + `确认要对卡片 ${cardInfo.value.iccid} 进行保号复机操作吗?`, + '保号复机确认', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + } + ) + + operationLoading.value = true + await EnterpriseService.resumeCard(enterpriseId.value, cardId.value) + ElMessage.success('保号复机操作成功') + // 刷新卡片信息 + await fetchCardDetail() + } catch (error: any) { + if (error !== 'cancel') { + ElMessage.error(error?.message || '保号复机操作失败') + } + } finally { + operationLoading.value = false + } + return + } + + // 其他操作暂时只显示提示 ElMessage.info(`执行${operationNames[operation] || operation}操作`) }