feat: order-export,generation,status
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m45s

This commit is contained in:
luo
2026-06-17 17:46:04 +08:00
parent 2a8f4e40d6
commit 85d158dfec
15 changed files with 300 additions and 8 deletions

View File

@@ -76,7 +76,8 @@
const sceneName = computed(() => {
const sceneMap: Record<ExportTaskScene, string> = {
device: '设备管理',
iot_card: 'IoT卡管理'
iot_card: 'IoT卡管理',
order: '订单管理'
}
return sceneMap[props.scene]

View File

@@ -63,6 +63,14 @@ export interface SimCardProduct {
updateTime?: string
}
// 网卡业务状态枚举
export enum AssetStatus {
IN_STOCK = 1, // 在库
SOLD = 2, // 已销售
REPLACED = 3, // 已换货
DISABLED = 4 // 已停用
}
// 网卡实体
export interface Card {
id: string | number
@@ -73,6 +81,9 @@ export interface Card {
networkType: NetworkType
cardType: CardType
status: CardStatus
generation?: number // 资产世代编号初始值1每次换货转新后+1
asset_status?: AssetStatus // 业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用)
asset_status_name?: string // 业务状态名称(中文)
// 关联信息
productId?: string | number // 关联商品ID
productName?: string
@@ -369,6 +380,9 @@ export interface StandaloneIotCard {
activation_status: number // 激活状态 (0:未激活, 1:已激活)
network_status: number // 网络状态 (0:停机, 1:开机)
real_name_status: number // 实名状态 (0:未实名, 1:已实名)
generation?: number // 资产世代编号初始值1每次换货转新后+1
asset_status?: AssetStatus // 业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用)
asset_status_name?: string // 业务状态名称(中文)
batch_no?: string // 批次号 (可选)
supplier?: string // 供应商 (可选)
shop_id?: number | null // 店铺ID (可选)
@@ -515,6 +529,9 @@ export interface IotCardDetailResponse {
activation_status: number // 激活状态 (0:未激活, 1:已激活)
network_status: number // 网络状态 (0:停机, 1:开机)
real_name_status: number // 实名状态 (0:未实名, 1:已实名)
generation?: number // 资产世代编号初始值1每次换货转新后+1
asset_status?: AssetStatus // 业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用)
asset_status_name?: string // 业务状态名称(中文)
batch_no: string // 批次号
supplier: string // 供应商
shop_id: number | null // 店铺ID

View File

@@ -14,6 +14,14 @@ export enum DeviceStatus {
DEACTIVATED = 4 // 已停用
}
// 设备业务状态枚举
export enum DeviceAssetStatus {
IN_STOCK = 1, // 在库
SOLD = 2, // 已销售
REPLACED = 3, // 已换货
DISABLED = 4 // 已停用
}
// 设备在线状态枚举
export enum DeviceOnlineStatus {
UNKNOWN = 0, // 未知
@@ -38,6 +46,9 @@ export interface Device {
bound_card_count: number // 已绑定卡数量
status: DeviceStatus // 状态 (1:在库, 2:已分销, 3:已激活, 4:已停用)
status_name: string // 状态名称
generation?: number // 资产世代编号初始值1每次换货转新后+1
asset_status?: DeviceAssetStatus // 业务状态 (1:在库, 2:已销售, 3:已换货, 4:已停用)
asset_status_name?: string // 业务状态名称(中文)
shop_id: number | null // 店铺ID
shop_name: string // 店铺名称
batch_no: string // 批次号

View File

@@ -1,6 +1,6 @@
import type { BaseResponse, PaginationParams } from './common'
export type ExportTaskScene = 'device' | 'iot_card'
export type ExportTaskScene = 'device' | 'iot_card' | 'order'
export type ExportTaskFormat = 'xlsx' | 'csv'

View File

@@ -1219,6 +1219,8 @@
{ label: '设备类型', prop: 'device_type' },
{ label: '状态', prop: 'status' },
{ label: '状态名称', prop: 'status_name' },
{ label: '资产世代', prop: 'generation' },
{ label: '业务状态', prop: 'asset_status' },
{ label: '激活状态', prop: 'activation_status_name' },
{ label: '在线状态', prop: 'online_status' },
{ label: '实名策略', prop: 'realname_policy' },
@@ -1527,6 +1529,28 @@
width: 100,
formatter: (row: Device) => row.status_name || '-'
},
{
prop: 'generation',
label: '资产世代',
width: 100,
formatter: (row: Device) => row.generation ?? '-'
},
{
prop: 'asset_status',
label: '业务状态',
width: 100,
formatter: (row: Device) => {
const assetStatusMap: Record<number, { text: string; type: any }> = {
1: { text: '在库', type: 'info' },
2: { text: '已销售', type: 'success' },
3: { text: '已换货', type: 'warning' },
4: { text: '已停用', type: 'danger' }
}
if (row.asset_status == null) return '-'
const status = assetStatusMap[row.asset_status] || { text: '未知', type: 'info' }
return h(ElTag, { type: status.type }, () => status.text)
}
},
{
prop: 'activation_status_name',
label: '激活状态',

View File

@@ -67,7 +67,8 @@
const getSceneName = (scene?: ExportTaskScene) => {
const sceneMap: Record<ExportTaskScene, string> = {
device: '设备管理',
iot_card: 'IoT卡管理'
iot_card: 'IoT卡管理',
order: '订单管理'
}
return scene ? sceneMap[scene] : '-'

View File

@@ -74,7 +74,8 @@
const sceneOptions = [
{ label: '设备管理', value: 'device' },
{ label: 'IoT卡管理', value: 'iot_card' }
{ label: 'IoT卡管理', value: 'iot_card' },
{ label: '订单管理', value: 'order' }
]
const statusOptions = [

View File

@@ -1363,6 +1363,8 @@
{ label: '运营商', prop: 'carrier_name' },
{ label: '卡业务类型', prop: 'card_category' },
{ label: '状态', prop: 'status' },
{ label: '资产世代', prop: 'generation' },
{ label: '业务状态', prop: 'asset_status' },
{ label: '激活状态', prop: 'activation_status' },
{ label: '激活时间', prop: 'activated_at' },
{ label: '网络状态', prop: 'network_status' },
@@ -1550,6 +1552,28 @@
return h(ElTag, { type: getStatusType(row.status) }, () => getStatusText(row.status))
}
},
{
prop: 'generation',
label: '资产世代',
width: 100,
formatter: (row: StandaloneIotCard) => row.generation ?? '-'
},
{
prop: 'asset_status',
label: '业务状态',
width: 100,
formatter: (row: StandaloneIotCard) => {
const assetStatusMap: Record<number, { text: string; type: any }> = {
1: { text: '在库', type: 'info' },
2: { text: '已销售', type: 'success' },
3: { text: '已换货', type: 'warning' },
4: { text: '已停用', type: 'danger' }
}
if (row.asset_status == null) return '-'
const status = assetStatusMap[row.asset_status] || { text: '未知', type: 'info' }
return h(ElTag, { type: status.type }, () => status.text)
}
},
{
prop: 'activation_status',
label: '激活状态',

View File

@@ -22,6 +22,9 @@
<ElButton @click="showCreateDialog" v-permission="'orders:add'">{{
'创建订单'
}}</ElButton>
<ElButton v-if="hasAuth('orders:export')" @click="exportDialogVisible = true">{{
'导出'
}}</ElButton>
</template>
</ArtTableHeader>
@@ -152,17 +155,17 @@
</ElOption>
</ElSelect>
<template v-if="noSeriesId">
<div style=" margin-top: 4px; font-size: 12px;color: var(--el-text-color-warning)">
<div style="margin-top: 4px; font-size: 12px; color: var(--el-text-color-warning)">
该设备未关联套餐系列无法购买套餐
</div>
</template>
<template v-else-if="packagesEmptyWithSeriesId">
<div style=" margin-top: 4px; font-size: 12px;color: var(--el-text-color-info)">
<div style="margin-top: 4px; font-size: 12px; color: var(--el-text-color-info)">
该系列暂无可用套餐
</div>
</template>
<template v-else-if="selectedPackageIsGift">
<div style=" margin-top: 4px; font-size: 12px;color: var(--el-color-warning)">
<div style="margin-top: 4px; font-size: 12px; color: var(--el-color-warning)">
提示: 赠送套餐只能使用线下支付方式且必须上传支付凭证
</div>
</template>
@@ -237,13 +240,22 @@
:file-key="paymentVoucherFileKey"
@close="paymentVoucherFileKey = ''"
/>
<!-- 导出任务对话框 -->
<ExportTaskCreateDialog
v-model="exportDialogVisible"
scene="order"
:query="exportQuery"
confirm-permission="orders:export"
title="导出订单"
/>
</ElCard>
</div>
</ArtTableFullScreen>
</template>
<script setup lang="ts">
import { h, nextTick } from 'vue'
import { computed, h, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import {
OrderService,
@@ -277,6 +289,7 @@
import { formatDateTime } from '@/utils/business/format'
import { RoutesAlias } from '@/router/routesAlias'
import PaymentVoucherDialog from '@/components/business/PaymentVoucherDialog.vue'
import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue'
defineOptions({ name: 'OrderList' })
@@ -293,6 +306,7 @@
const voucherUploading = ref(false)
const tableRef = ref()
const createDialogVisible = ref(false)
const exportDialogVisible = ref(false)
const paymentVoucherFileKey = ref('')
let activeVoucherUploadId = 0
@@ -1130,6 +1144,31 @@
getTableData()
}
// 导出查询参数
const exportQuery = computed(() => {
const query: Record<string, unknown> = {
order_no: searchForm.order_no || undefined,
buyer_phone: searchForm.buyer_phone || undefined,
payment_status: searchForm.payment_status,
payment_method: searchForm.payment_method,
order_type: searchForm.order_type,
purchase_role: searchForm.purchase_role,
identifier: searchForm.identifier || undefined,
is_expired: searchForm.is_expired === undefined ? undefined : Boolean(searchForm.is_expired),
seller_shop_id: searchForm.seller_shop_id,
start_time: searchForm.start_time || undefined,
end_time: searchForm.end_time || undefined
}
Object.keys(query).forEach((key) => {
if (query[key] === undefined || query[key] === null || query[key] === '') {
delete query[key]
}
})
return query
})
// 刷新表格
const handleRefresh = () => {
getTableData()