This commit is contained in:
@@ -19,7 +19,9 @@ import type {
|
|||||||
BaseResponse,
|
BaseResponse,
|
||||||
PaginationResponse,
|
PaginationResponse,
|
||||||
ListResponse,
|
ListResponse,
|
||||||
GatewayRealnameLinkResponse
|
GatewayRealnameLinkResponse,
|
||||||
|
ImportIotCardRequest,
|
||||||
|
ImportIotCardResponse
|
||||||
} from '@/types/api'
|
} from '@/types/api'
|
||||||
|
|
||||||
export class CardService extends BaseService {
|
export class CardService extends BaseService {
|
||||||
@@ -286,15 +288,8 @@ export class CardService extends BaseService {
|
|||||||
* 批量导入ICCID(新版:使用 JSON 格式)
|
* 批量导入ICCID(新版:使用 JSON 格式)
|
||||||
* @param data 导入请求参数
|
* @param data 导入请求参数
|
||||||
*/
|
*/
|
||||||
static importIotCards(data: {
|
static importIotCards(data: ImportIotCardRequest): Promise<BaseResponse<ImportIotCardResponse>> {
|
||||||
carrier_id: number
|
return this.post<BaseResponse<ImportIotCardResponse>>('/api/admin/iot-cards/import', data)
|
||||||
file_key: string
|
|
||||||
batch_no?: string
|
|
||||||
}): Promise<BaseResponse<{ task_id: number; task_no: string; message: string }>> {
|
|
||||||
return this.post<BaseResponse<{ task_id: number; task_no: string; message: string }>>(
|
|
||||||
'/api/admin/iot-cards/import',
|
|
||||||
data
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -93,82 +93,6 @@ export class CommissionService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== 我的佣金(已废弃,仅保留用于向后兼容) ====================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 getShopCommissionRecords 代替
|
|
||||||
* 获取我的佣金明细
|
|
||||||
* GET /api/admin/my/commission-records
|
|
||||||
*/
|
|
||||||
static getMyCommissionRecords(
|
|
||||||
params?: CommissionRecordQueryParams
|
|
||||||
): Promise<BaseResponse<MyCommissionRecordPageResult>> {
|
|
||||||
return this.get<BaseResponse<MyCommissionRecordPageResult>>(
|
|
||||||
'/api/admin/my/commission-records',
|
|
||||||
params
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 getShopFundSummary 代替
|
|
||||||
* 获取我的佣金概览
|
|
||||||
* GET /api/admin/my/commission-summary
|
|
||||||
*/
|
|
||||||
static getMyCommissionSummary(): Promise<BaseResponse<MyCommissionSummary>> {
|
|
||||||
return this.get<BaseResponse<MyCommissionSummary>>('/api/admin/my/commission-summary')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 getShopWithdrawalRequests 代替
|
|
||||||
* 获取我的提现记录
|
|
||||||
* GET /api/admin/my/withdrawal-requests
|
|
||||||
*/
|
|
||||||
static getMyWithdrawalRequests(
|
|
||||||
params?: WithdrawalRequestQueryParams
|
|
||||||
): Promise<BaseResponse<WithdrawalRequestPageResult>> {
|
|
||||||
return this.get<BaseResponse<WithdrawalRequestPageResult>>(
|
|
||||||
'/api/admin/my/withdrawal-requests',
|
|
||||||
params
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 submitShopWithdrawalRequest 代替
|
|
||||||
* 发起提现申请
|
|
||||||
* POST /api/admin/my/withdrawal-requests
|
|
||||||
*/
|
|
||||||
static submitWithdrawalRequest(params: SubmitWithdrawalParams): Promise<BaseResponse> {
|
|
||||||
return this.post<BaseResponse>('/api/admin/my/withdrawal-requests', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 getShopCommissionStats 代替
|
|
||||||
* 获取我的佣金统计
|
|
||||||
* GET /api/admin/my/commission-stats
|
|
||||||
*/
|
|
||||||
static getMyCommissionStats(
|
|
||||||
params?: ShopCommissionStatsQueryParams
|
|
||||||
): Promise<BaseResponse<CommissionStatsResponse>> {
|
|
||||||
return this.get<BaseResponse<CommissionStatsResponse>>(
|
|
||||||
'/api/admin/my/commission-stats',
|
|
||||||
params
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 getShopDailyCommissionStats 代替
|
|
||||||
* 获取我的每日佣金统计
|
|
||||||
* GET /api/admin/my/commission-daily-stats
|
|
||||||
*/
|
|
||||||
static getMyDailyCommissionStats(
|
|
||||||
params?: DailyCommissionStatsQueryParams
|
|
||||||
): Promise<BaseResponse<DailyCommissionStatsItem[]>> {
|
|
||||||
return this.get<BaseResponse<DailyCommissionStatsItem[]>>(
|
|
||||||
'/api/admin/my/commission-daily-stats',
|
|
||||||
params
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 代理商佣金管理 ====================
|
// ==================== 代理商佣金管理 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -212,17 +136,6 @@ export class CommissionService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated 使用 getShopFundSummary 代替
|
|
||||||
* 获取代理商佣金汇总列表
|
|
||||||
* GET /api/admin/shops/commission-summary
|
|
||||||
*/
|
|
||||||
static getShopCommissionSummary(
|
|
||||||
params?: ShopFundSummaryQueryParams
|
|
||||||
): Promise<BaseResponse<ShopFundSummaryPageResult>> {
|
|
||||||
return this.getShopFundSummary(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取代理商佣金统计
|
* 获取代理商佣金统计
|
||||||
* GET /api/admin/shops/{shop_id}/commission-stats
|
* GET /api/admin/shops/{shop_id}/commission-stats
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ export enum CardType {
|
|||||||
FLOW = 'flow' // 流量卡
|
FLOW = 'flow' // 流量卡
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 卡业务类型
|
||||||
|
export enum CardCategory {
|
||||||
|
NORMAL = 'normal', // 普通卡
|
||||||
|
INDUSTRY = 'industry' // 行业卡
|
||||||
|
}
|
||||||
|
|
||||||
// 号卡商品实体
|
// 号卡商品实体
|
||||||
export interface SimCardProduct {
|
export interface SimCardProduct {
|
||||||
id: string | number
|
id: string | number
|
||||||
@@ -107,6 +113,21 @@ export interface CardQueryParams extends PaginationParams {
|
|||||||
importTimeRange?: [string, string]
|
importTimeRange?: [string, string]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IoT 卡导入请求
|
||||||
|
export interface ImportIotCardRequest {
|
||||||
|
carrier_id: number // 运营商ID
|
||||||
|
file_key: string // 对象存储文件路径
|
||||||
|
batch_no?: string // 批次号
|
||||||
|
card_category?: CardCategory // 卡业务类型(新增,可选,默认 normal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IoT 卡导入响应
|
||||||
|
export interface ImportIotCardResponse {
|
||||||
|
task_id: number // 导入任务ID
|
||||||
|
task_no: string // 任务编号
|
||||||
|
message: string // 提示信息
|
||||||
|
}
|
||||||
|
|
||||||
// 网卡导入批次信息
|
// 网卡导入批次信息
|
||||||
export interface CardImportBatch extends ImportTask {
|
export interface CardImportBatch extends ImportTask {
|
||||||
importBatch: string // 导入批次号
|
importBatch: string // 导入批次号
|
||||||
@@ -118,6 +139,7 @@ export interface CardImportBatch extends ImportTask {
|
|||||||
cardCompanyName?: string
|
cardCompanyName?: string
|
||||||
operator: Operator
|
operator: Operator
|
||||||
cardType: CardType
|
cardType: CardType
|
||||||
|
cardCategory?: CardCategory // 卡业务类型(新增)
|
||||||
operatorUser?: string // 操作人
|
operatorUser?: string // 操作人
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ export interface CommissionRecordQueryParams extends PaginationParams {
|
|||||||
* 我的佣金概览
|
* 我的佣金概览
|
||||||
*/
|
*/
|
||||||
export interface MyCommissionSummary {
|
export interface MyCommissionSummary {
|
||||||
|
main_balance: number // 预充值余额(分)
|
||||||
total_commission: number // 总佣金(分)
|
total_commission: number // 总佣金(分)
|
||||||
available_commission: number // 可提现佣金(分)
|
available_commission: number // 可提现佣金(分)
|
||||||
frozen_commission: number // 冻结中佣金(分)
|
frozen_commission: number // 冻结中佣金(分)
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export interface CreateOrderRequest {
|
|||||||
iot_card_id?: number | null // IoT卡ID
|
iot_card_id?: number | null // IoT卡ID
|
||||||
device_id?: number | null // 设备ID
|
device_id?: number | null // 设备ID
|
||||||
identifier?: string // 资产标识符(ICCID 或 VirtualNo)
|
identifier?: string // 资产标识符(ICCID 或 VirtualNo)
|
||||||
package_id: number // 套餐ID(单选)
|
package_ids: number[] // 套餐ID列表(前端限制单选,后端支持1-10个)
|
||||||
payment_method: OrderPaymentMethod // 支付方式
|
payment_method: OrderPaymentMethod // 支付方式
|
||||||
payment_voucher_key?: string // 线下支付凭证(仅 offline 必填)
|
payment_voucher_key?: string // 线下支付凭证(仅 offline 必填)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1498,7 +1498,7 @@
|
|||||||
const rechargeLoading = ref(false)
|
const rechargeLoading = ref(false)
|
||||||
const rechargeFormRef = ref<FormInstance>()
|
const rechargeFormRef = ref<FormInstance>()
|
||||||
const rechargeForm = reactive({
|
const rechargeForm = reactive({
|
||||||
package_id: 0,
|
package_id: undefined as number | undefined, // 前端使用单选
|
||||||
payment_method: 'wallet' as 'wallet' | 'offline'
|
payment_method: 'wallet' as 'wallet' | 'offline'
|
||||||
})
|
})
|
||||||
const rechargeRules: FormRules = {
|
const rechargeRules: FormRules = {
|
||||||
@@ -2658,14 +2658,20 @@
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
rechargeLoading.value = true
|
rechargeLoading.value = true
|
||||||
try {
|
try {
|
||||||
|
// 验证必填字段
|
||||||
|
if (!rechargeForm.package_id) {
|
||||||
|
ElMessage.error('请选择套餐')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 获取资产标识符
|
// 获取资产标识符
|
||||||
const identifier =
|
const identifier =
|
||||||
cardInfo.value.asset_type === 'card' ? cardInfo.value.iccid : cardInfo.value.virtual_no
|
cardInfo.value.asset_type === 'card' ? cardInfo.value.iccid : cardInfo.value.virtual_no
|
||||||
|
|
||||||
// 创建订单
|
// 创建订单(后端接收数组,前端单选转为单元素数组)
|
||||||
const data: CreateOrderRequest = {
|
const data: CreateOrderRequest = {
|
||||||
identifier,
|
identifier,
|
||||||
package_id: rechargeForm.package_id,
|
package_ids: [rechargeForm.package_id],
|
||||||
payment_method: rechargeForm.payment_method
|
payment_method: rechargeForm.payment_method
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2701,7 +2707,7 @@
|
|||||||
// 关闭充值对话框
|
// 关闭充值对话框
|
||||||
const handleRechargeDialogClosed = () => {
|
const handleRechargeDialogClosed = () => {
|
||||||
rechargeFormRef.value?.resetFields()
|
rechargeFormRef.value?.resetFields()
|
||||||
rechargeForm.package_id = 0
|
rechargeForm.package_id = undefined
|
||||||
rechargeForm.payment_method = 'wallet'
|
rechargeForm.payment_method = 'wallet'
|
||||||
packageOptions.value = []
|
packageOptions.value = []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,13 +60,10 @@
|
|||||||
<p>1. 请先下载 Excel 模板文件,按照模板格式填写设备信息</p>
|
<p>1. 请先下载 Excel 模板文件,按照模板格式填写设备信息</p>
|
||||||
<p>2. 仅支持 Excel 格式(.xlsx),单次最多导入 1000 条</p>
|
<p>2. 仅支持 Excel 格式(.xlsx),单次最多导入 1000 条</p>
|
||||||
<p>3. 列格式请设置为文本格式,避免长数字被转为科学计数法</p>
|
<p>3. 列格式请设置为文本格式,避免长数字被转为科学计数法</p>
|
||||||
|
<p>4. <strong>重要:列顺序固定,不可调整。</strong>系统按位置读取,不识别列名</p>
|
||||||
|
<p>5. 必填列:虚拟号(第1列)</p>
|
||||||
<p
|
<p
|
||||||
>4.
|
>6. 可选列:设备名称、设备型号、设备类型、IMEI、制造商、最大SIM槽数(默认4,有效范围1-4)、卡1~卡4 ICCID</p
|
||||||
必填列:virtual_no(虚拟号)、device_name(设备名称)、device_model(设备型号)、device_type(设备类型)、imei(设备IMEI号)</p
|
|
||||||
>
|
|
||||||
<p
|
|
||||||
>5. 可选列:manufacturer(制造商)、max_sim_slots(最大插槽数,默认4)、iccid_1 ~
|
|
||||||
iccid_4(绑定的卡ICCID)</p
|
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -89,7 +86,7 @@
|
|||||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||||
<div class="el-upload__text">将 Excel 文件拖到此处,或<em>点击选择</em></div>
|
<div class="el-upload__text">将 Excel 文件拖到此处,或<em>点击选择</em></div>
|
||||||
<template #tip>
|
<template #tip>
|
||||||
<div class="el-upload__tip">只能上传 .xlsx 格式的 Excel 文件,且不超过 10MB</div>
|
<div class="el-upload__tip">只能上传 .xlsx 格式的 Excel 文件,且不超过 300MB</div>
|
||||||
</template>
|
</template>
|
||||||
</ElUpload>
|
</ElUpload>
|
||||||
|
|
||||||
@@ -411,33 +408,33 @@
|
|||||||
// 动态导入 xlsx 库
|
// 动态导入 xlsx 库
|
||||||
const XLSX = await import('xlsx')
|
const XLSX = await import('xlsx')
|
||||||
|
|
||||||
// 创建示例数据
|
// 创建示例数据(按固定列顺序)
|
||||||
const templateData = [
|
const templateData = [
|
||||||
{
|
{
|
||||||
virtual_no: '862639070731999',
|
虚拟号: '862639070731999',
|
||||||
device_name: '智能水表01',
|
设备名称: '智能水表01',
|
||||||
device_model: 'WM-2000',
|
设备型号: 'WM-2000',
|
||||||
device_type: '智能水表',
|
设备类型: '智能水表',
|
||||||
imei: '860123456789012',
|
IMEI: '860123456789012',
|
||||||
manufacturer: '华为',
|
制造商: '华为',
|
||||||
max_sim_slots: 4,
|
最大SIM槽数: 4,
|
||||||
iccid_1: '89860123456789012345',
|
'卡1 ICCID': '89860123456789012345',
|
||||||
iccid_2: '',
|
'卡2 ICCID': '',
|
||||||
iccid_3: '',
|
'卡3 ICCID': '',
|
||||||
iccid_4: ''
|
'卡4 ICCID': ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
virtual_no: '862639070750932',
|
虚拟号: '862639070750932',
|
||||||
device_name: 'GPS定位器01',
|
设备名称: 'GPS定位器01',
|
||||||
device_model: 'GPS-3000',
|
设备型号: 'GPS-3000',
|
||||||
device_type: '定位设备',
|
设备类型: '定位设备',
|
||||||
imei: '860123456789013',
|
IMEI: '860123456789013',
|
||||||
manufacturer: '小米',
|
制造商: '小米',
|
||||||
max_sim_slots: 2,
|
最大SIM槽数: 2,
|
||||||
iccid_1: '89860123456789012346',
|
'卡1 ICCID': '89860123456789012346',
|
||||||
iccid_2: '89860123456789012347',
|
'卡2 ICCID': '89860123456789012347',
|
||||||
iccid_3: '',
|
'卡3 ICCID': '',
|
||||||
iccid_4: ''
|
'卡4 ICCID': ''
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -447,17 +444,17 @@
|
|||||||
|
|
||||||
// 设置列宽
|
// 设置列宽
|
||||||
ws['!cols'] = [
|
ws['!cols'] = [
|
||||||
{ wch: 20 }, // virtual_no
|
{ wch: 20 }, // 虚拟号
|
||||||
{ wch: 20 }, // device_name
|
{ wch: 15 }, // 设备名称
|
||||||
{ wch: 15 }, // device_model
|
{ wch: 15 }, // 设备型号
|
||||||
{ wch: 15 }, // device_type
|
{ wch: 15 }, // 设备类型
|
||||||
{ wch: 18 }, // imei
|
{ wch: 18 }, // IMEI
|
||||||
{ wch: 15 }, // manufacturer
|
{ wch: 12 }, // 制造商
|
||||||
{ wch: 15 }, // max_sim_slots
|
{ wch: 15 }, // 最大SIM槽数
|
||||||
{ wch: 22 }, // iccid_1
|
{ wch: 25 }, // 卡1 ICCID
|
||||||
{ wch: 22 }, // iccid_2
|
{ wch: 25 }, // 卡2 ICCID
|
||||||
{ wch: 22 }, // iccid_3
|
{ wch: 25 }, // 卡3 ICCID
|
||||||
{ wch: 22 } // iccid_4
|
{ wch: 25 } // 卡4 ICCID
|
||||||
]
|
]
|
||||||
|
|
||||||
// 将所有单元格设置为文本格式
|
// 将所有单元格设置为文本格式
|
||||||
@@ -484,9 +481,9 @@
|
|||||||
|
|
||||||
// 文件选择变化
|
// 文件选择变化
|
||||||
const handleFileChange = (uploadFile: any) => {
|
const handleFileChange = (uploadFile: any) => {
|
||||||
const maxSize = 10 * 1024 * 1024
|
const maxSize = 300 * 1024 * 1024
|
||||||
if (uploadFile.raw && uploadFile.raw.size > maxSize) {
|
if (uploadFile.raw && uploadFile.raw.size > maxSize) {
|
||||||
ElMessage.error('文件大小不能超过 10MB')
|
ElMessage.error('文件大小不能超过 300MB')
|
||||||
uploadRef.value?.clearFiles()
|
uploadRef.value?.clearFiles()
|
||||||
fileList.value = []
|
fileList.value = []
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -139,6 +139,16 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
|
|
||||||
|
<ElFormItem label="卡业务类型" style="margin-bottom: 20px">
|
||||||
|
<ElSelect v-model="selectedCardCategory" placeholder="请选择卡业务类型" style="width: 100%">
|
||||||
|
<ElOption label="普通卡" value="normal" />
|
||||||
|
<ElOption label="行业卡" value="industry" />
|
||||||
|
</ElSelect>
|
||||||
|
<div style="margin-top: 4px; font-size: 12px; color: var(--el-text-color-secondary)">
|
||||||
|
默认为普通卡,可选择行业卡
|
||||||
|
</div>
|
||||||
|
</ElFormItem>
|
||||||
|
|
||||||
<ElUpload
|
<ElUpload
|
||||||
ref="uploadRef"
|
ref="uploadRef"
|
||||||
drag
|
drag
|
||||||
@@ -150,7 +160,7 @@
|
|||||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||||
<div class="el-upload__text">将 Excel 文件拖到此处,或<em>点击选择</em></div>
|
<div class="el-upload__text">将 Excel 文件拖到此处,或<em>点击选择</em></div>
|
||||||
<template #tip>
|
<template #tip>
|
||||||
<div class="el-upload__tip">只能上传 .xlsx 格式的 Excel 文件,且不超过 10MB</div>
|
<div class="el-upload__tip">只能上传 .xlsx 格式的 Excel 文件,且不超过 300MB</div>
|
||||||
</template>
|
</template>
|
||||||
</ElUpload>
|
</ElUpload>
|
||||||
|
|
||||||
@@ -207,6 +217,7 @@
|
|||||||
const uploading = ref(false)
|
const uploading = ref(false)
|
||||||
const importDialogVisible = ref(false)
|
const importDialogVisible = ref(false)
|
||||||
const selectedCarrierId = ref<number>()
|
const selectedCarrierId = ref<number>()
|
||||||
|
const selectedCardCategory = ref<'normal' | 'industry'>('normal') // 默认普通卡
|
||||||
const carrierList = ref<Carrier[]>([])
|
const carrierList = ref<Carrier[]>([])
|
||||||
const carrierLoading = ref(false)
|
const carrierLoading = ref(false)
|
||||||
const failDataDialogVisible = ref(false)
|
const failDataDialogVisible = ref(false)
|
||||||
@@ -292,6 +303,7 @@
|
|||||||
{ label: '任务编号', prop: 'task_no' },
|
{ label: '任务编号', prop: 'task_no' },
|
||||||
{ label: '任务状态', prop: 'status' },
|
{ label: '任务状态', prop: 'status' },
|
||||||
{ label: '运营商', prop: 'carrier_name' },
|
{ label: '运营商', prop: 'carrier_name' },
|
||||||
|
{ label: '卡业务类型', prop: 'card_category' },
|
||||||
{ label: '文件名', prop: 'file_name' },
|
{ label: '文件名', prop: 'file_name' },
|
||||||
{ label: '总数', prop: 'total_count' },
|
{ label: '总数', prop: 'total_count' },
|
||||||
{ label: '成功数', prop: 'success_count' },
|
{ label: '成功数', prop: 'success_count' },
|
||||||
@@ -374,6 +386,19 @@
|
|||||||
label: '运营商',
|
label: '运营商',
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: 'card_category',
|
||||||
|
label: '卡业务类型',
|
||||||
|
width: 110,
|
||||||
|
formatter: (row: IotCardImportTask) => {
|
||||||
|
if (!row.card_category) return '-'
|
||||||
|
return row.card_category === 'normal'
|
||||||
|
? '普通卡'
|
||||||
|
: row.card_category === 'industry'
|
||||||
|
? '行业卡'
|
||||||
|
: row.card_category
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prop: 'file_name',
|
prop: 'file_name',
|
||||||
label: '文件名',
|
label: '文件名',
|
||||||
@@ -577,22 +602,22 @@
|
|||||||
// 动态导入 xlsx 库
|
// 动态导入 xlsx 库
|
||||||
const XLSX = await import('xlsx')
|
const XLSX = await import('xlsx')
|
||||||
|
|
||||||
// 创建示例数据
|
// 创建示例数据(按固定列顺序:ICCID、MSISDN、虚拟号)
|
||||||
const templateData = [
|
const templateData = [
|
||||||
{
|
{
|
||||||
ICCID: '89860123456789012345',
|
ICCID: '89860123456789012345',
|
||||||
MSISDN: '13800138000',
|
'MSISDN(接入号)': '13800138000',
|
||||||
virtual_no: 'V001'
|
虚拟号: 'V001'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ICCID: '89860123456789012346',
|
ICCID: '89860123456789012346',
|
||||||
MSISDN: '13800138001',
|
'MSISDN(接入号)': '13800138001',
|
||||||
virtual_no: 'V002'
|
虚拟号: 'V002'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ICCID: '89860123456789012347',
|
ICCID: '89860123456789012347',
|
||||||
MSISDN: '13800138002',
|
'MSISDN(接入号)': '13800138002',
|
||||||
virtual_no: 'V003'
|
虚拟号: 'V003'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -603,8 +628,8 @@
|
|||||||
// 设置列宽
|
// 设置列宽
|
||||||
ws['!cols'] = [
|
ws['!cols'] = [
|
||||||
{ wch: 25 }, // ICCID
|
{ wch: 25 }, // ICCID
|
||||||
{ wch: 15 }, // MSISDN
|
{ wch: 20 }, // MSISDN(接入号)
|
||||||
{ wch: 15 } // virtual_no
|
{ wch: 15 } // 虚拟号
|
||||||
]
|
]
|
||||||
|
|
||||||
// 将所有单元格设置为文本格式,防止科学计数法
|
// 将所有单元格设置为文本格式,防止科学计数法
|
||||||
@@ -631,9 +656,9 @@
|
|||||||
|
|
||||||
// 文件选择变化
|
// 文件选择变化
|
||||||
const handleFileChange = (uploadFile: any) => {
|
const handleFileChange = (uploadFile: any) => {
|
||||||
const maxSize = 10 * 1024 * 1024
|
const maxSize = 300 * 1024 * 1024
|
||||||
if (uploadFile.raw && uploadFile.raw.size > maxSize) {
|
if (uploadFile.raw && uploadFile.raw.size > maxSize) {
|
||||||
ElMessage.error('文件大小不能超过 10MB')
|
ElMessage.error('文件大小不能超过 300MB')
|
||||||
uploadRef.value?.clearFiles()
|
uploadRef.value?.clearFiles()
|
||||||
fileList.value = []
|
fileList.value = []
|
||||||
return
|
return
|
||||||
@@ -659,6 +684,7 @@
|
|||||||
// 取消导入
|
// 取消导入
|
||||||
const handleCancelImport = () => {
|
const handleCancelImport = () => {
|
||||||
clearFiles()
|
clearFiles()
|
||||||
|
selectedCardCategory.value = 'normal' // 重置为默认值
|
||||||
importDialogVisible.value = false
|
importDialogVisible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,7 +754,8 @@
|
|||||||
const importRes = await CardService.importIotCards({
|
const importRes = await CardService.importIotCards({
|
||||||
carrier_id: selectedCarrierId.value,
|
carrier_id: selectedCarrierId.value,
|
||||||
file_key,
|
file_key,
|
||||||
batch_no: `IOT-${Date.now()}`
|
batch_no: `IOT-${Date.now()}`,
|
||||||
|
card_category: selectedCardCategory.value // 新增卡业务类型
|
||||||
})
|
})
|
||||||
|
|
||||||
if (importRes.code !== 0) {
|
if (importRes.code !== 0) {
|
||||||
|
|||||||
@@ -119,6 +119,17 @@
|
|||||||
label: '运营商',
|
label: '运营商',
|
||||||
prop: 'carrier_name',
|
prop: 'carrier_name',
|
||||||
formatter: (value: any) => value || '-'
|
formatter: (value: any) => value || '-'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '卡业务类型',
|
||||||
|
render: (data: any) => {
|
||||||
|
if (!data.card_category) return h('span', '-')
|
||||||
|
return h(
|
||||||
|
ElTag,
|
||||||
|
{ type: data.card_category === 'industry' ? 'warning' : 'success', size: 'small' },
|
||||||
|
() => (data.card_category === 'normal' ? '普通卡' : data.card_category === 'industry' ? '行业卡' : data.card_category)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
|
|||||||
@@ -10,6 +10,20 @@
|
|||||||
<!-- 正常显示 -->
|
<!-- 正常显示 -->
|
||||||
<div v-else class="commission-summary-widget">
|
<div v-else class="commission-summary-widget">
|
||||||
<div class="stats-container">
|
<div class="stats-container">
|
||||||
|
<ElCard shadow="hover" class="stat-card-wrapper">
|
||||||
|
<div class="stat-card">
|
||||||
|
<div
|
||||||
|
class="stat-icon"
|
||||||
|
style="background: linear-gradient(135deg, #ff6b6b 0%, #ff8e53 100%)"
|
||||||
|
>
|
||||||
|
<i class="iconfont-sys"></i>
|
||||||
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-label">预充值余额</div>
|
||||||
|
<div class="stat-value">{{ formatMoney(summary.main_balance) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ElCard>
|
||||||
<ElCard shadow="hover" class="stat-card-wrapper">
|
<ElCard shadow="hover" class="stat-card-wrapper">
|
||||||
<div class="stat-card">
|
<div class="stat-card">
|
||||||
<div
|
<div
|
||||||
@@ -102,6 +116,7 @@
|
|||||||
|
|
||||||
// 佣金概览
|
// 佣金概览
|
||||||
const summary = ref<MyCommissionSummary>({
|
const summary = ref<MyCommissionSummary>({
|
||||||
|
main_balance: 0,
|
||||||
total_commission: 0,
|
total_commission: 0,
|
||||||
available_commission: 0,
|
available_commission: 0,
|
||||||
frozen_commission: 0,
|
frozen_commission: 0,
|
||||||
@@ -127,6 +142,7 @@
|
|||||||
const myShopData = res.data.items.find(item => item.shop_id === currentShopId.value)
|
const myShopData = res.data.items.find(item => item.shop_id === currentShopId.value)
|
||||||
if (myShopData) {
|
if (myShopData) {
|
||||||
summary.value = {
|
summary.value = {
|
||||||
|
main_balance: myShopData.main_balance || 0,
|
||||||
total_commission: myShopData.total_commission,
|
total_commission: myShopData.total_commission,
|
||||||
available_commission: myShopData.available_commission,
|
available_commission: myShopData.available_commission,
|
||||||
frozen_commission: myShopData.frozen_commission,
|
frozen_commission: myShopData.frozen_commission,
|
||||||
|
|||||||
@@ -527,13 +527,13 @@
|
|||||||
return baseRules
|
return baseRules
|
||||||
})
|
})
|
||||||
|
|
||||||
const createForm = reactive<CreateOrderRequest>({
|
const createForm = reactive({
|
||||||
order_type: 'single_card',
|
order_type: 'single_card' as OrderType,
|
||||||
package_id: 0,
|
package_id: undefined as number | undefined, // 前端使用单选
|
||||||
iot_card_id: null,
|
iot_card_id: null as number | null,
|
||||||
device_id: null,
|
device_id: null as number | null,
|
||||||
payment_method: 'wallet', // 默认使用钱包支付
|
payment_method: 'wallet' as OrderPaymentMethod, // 默认使用钱包支付
|
||||||
payment_voucher_key: undefined // 线下支付凭证
|
payment_voucher_key: undefined as string | undefined // 线下支付凭证
|
||||||
})
|
})
|
||||||
|
|
||||||
const orderList = ref<Order[]>([])
|
const orderList = ref<Order[]>([])
|
||||||
@@ -975,7 +975,7 @@
|
|||||||
|
|
||||||
// 重置表单数据到初始值
|
// 重置表单数据到初始值
|
||||||
createForm.order_type = 'single_card'
|
createForm.order_type = 'single_card'
|
||||||
createForm.package_id = 0
|
createForm.package_id = undefined
|
||||||
createForm.iot_card_id = null
|
createForm.iot_card_id = null
|
||||||
createForm.device_id = null
|
createForm.device_id = null
|
||||||
createForm.payment_method = 'wallet'
|
createForm.payment_method = 'wallet'
|
||||||
@@ -1028,10 +1028,16 @@
|
|||||||
identifier = selectedDevice.virtual_no
|
identifier = selectedDevice.virtual_no
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建订单
|
// 验证必填字段
|
||||||
|
if (!createForm.package_id) {
|
||||||
|
ElMessage.error('请选择套餐')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建订单(后端接收数组,前端单选转为单元素数组)
|
||||||
const data: CreateOrderRequest = {
|
const data: CreateOrderRequest = {
|
||||||
identifier,
|
identifier,
|
||||||
package_id: createForm.package_id,
|
package_ids: [createForm.package_id],
|
||||||
payment_method: createForm.payment_method
|
payment_method: createForm.payment_method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -490,7 +490,7 @@
|
|||||||
page_size: 20,
|
page_size: 20,
|
||||||
carrier_name: carrierName
|
carrier_name: carrierName
|
||||||
})
|
})
|
||||||
carrierList.value = data.items || data.list || []
|
carrierList.value = data.items || []
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载运营商列表失败', error)
|
console.error('加载运营商列表失败', error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -709,7 +709,7 @@
|
|||||||
page_size: 20,
|
page_size: 20,
|
||||||
carrier_name: carrierName
|
carrier_name: carrierName
|
||||||
})
|
})
|
||||||
carrierList.value = data.items || data.list || []
|
carrierList.value = data.items || []
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载运营商列表失败', error)
|
console.error('加载运营商列表失败', error)
|
||||||
}
|
}
|
||||||
@@ -727,7 +727,7 @@
|
|||||||
const loadShops = async () => {
|
const loadShops = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await ShopService.getShops()
|
const { data } = await ShopService.getShops()
|
||||||
shopTreeData.value = data.items || data.list || []
|
shopTreeData.value = data.items || []
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载店铺列表失败', error)
|
console.error('加载店铺列表失败', error)
|
||||||
}
|
}
|
||||||
@@ -741,7 +741,7 @@
|
|||||||
page_size: 20,
|
page_size: 20,
|
||||||
iccid: iccid
|
iccid: iccid
|
||||||
})
|
})
|
||||||
cardList.value = data.items || data.list || []
|
cardList.value = data.items || []
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载卡列表失败', error)
|
console.error('加载卡列表失败', error)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user