fix:订单列表详情实付金额代理/企业不可见
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 6m22s

This commit is contained in:
sexygoat
2026-06-01 14:10:09 +08:00
parent e563b81b6e
commit 3e6b3981f4
6 changed files with 397 additions and 338 deletions

View File

@@ -233,6 +233,7 @@ export interface AssetPackageUsageRecord {
reduction_pct?: number // 展示增幅比例(小数,如 0.428571 reduction_pct?: number // 展示增幅比例(小数,如 0.428571
enable_virtual_data?: boolean // 是否启用虚流量 enable_virtual_data?: boolean // 是否启用虚流量
paid_amount?: number // 实际支付金额(分) paid_amount?: number // 实际支付金额(分)
retail_amount?: number // 零售价(分)
package_price?: number // 套餐价格(分) package_price?: number // 套餐价格(分)
start_time?: string // 开始时间(兼容前端现有映射字段) start_time?: string // 开始时间(兼容前端现有映射字段)
expire_time?: string // 到期时间(兼容前端现有映射字段) expire_time?: string // 到期时间(兼容前端现有映射字段)

View File

@@ -193,8 +193,11 @@
<ElDescriptionsItem label="套餐名称"> <ElDescriptionsItem label="套餐名称">
{{ currentPackage.package_name || '-' }} {{ currentPackage.package_name || '-' }}
</ElDescriptionsItem> </ElDescriptionsItem>
<ElDescriptionsItem label="套餐价格"> <ElDescriptionsItem label="套餐成本价格" v-if="isAdminOrPlatform">
{{ formatAmount(currentPackage.paid_amount || currentPackage.package_price || 0) }} {{ formatAmount(currentPackage.paid_amount || 0) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="套餐零售价">
{{ formatAmount(currentPackage.retail_amount || 0) }}
</ElDescriptionsItem> </ElDescriptionsItem>
<ElDescriptionsItem label="套餐类型"> <ElDescriptionsItem label="套餐类型">
{{ getPackageTypeName(currentPackage.package_type) }} {{ getPackageTypeName(currentPackage.package_type) }}

View File

@@ -48,9 +48,14 @@
<span class="package-name-text">{{ scope.row.package_name }}</span> <span class="package-name-text">{{ scope.row.package_name }}</span>
</template> </template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn label="套餐价格" width="120"> <ElTableColumn v-if="isAdminOrPlatform" label="套餐成本价格" width="120">
<template #default="scope"> <template #default="scope">
{{ formatAmount(scope.row.paid_amount || scope.row.package_price || 0) }} {{ formatAmount(scope.row.paid_amount || 0) }}
</template>
</ElTableColumn>
<ElTableColumn label="套餐零售价" width="120">
<template #default="scope">
{{ formatAmount(scope.row.retail_amount || 0) }}
</template> </template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn prop="status_name" label="套餐状态" width="100"> <ElTableColumn prop="status_name" label="套餐状态" width="100">

View File

@@ -245,6 +245,7 @@ export function useAssetInfo() {
order_no: pkg.order_no || '', order_no: pkg.order_no || '',
package_name: pkg.package_name || '', package_name: pkg.package_name || '',
paid_amount: pkg.paid_amount || 0, paid_amount: pkg.paid_amount || 0,
retail_amount : pkg.retail_amount || 0,
real_total_mb: pkg.real_total_mb || 0, real_total_mb: pkg.real_total_mb || 0,
real_used_mb: pkg.real_used_mb || 0, real_used_mb: pkg.real_used_mb || 0,
real_remaining_mb: (pkg.real_total_mb || 0) - (pkg.real_used_mb || 0), real_remaining_mb: (pkg.real_total_mb || 0) - (pkg.real_used_mb || 0),

View File

@@ -60,7 +60,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { h, onMounted, ref } from 'vue' import { h, onMounted, ref, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { ElButton, ElCard, ElIcon, ElImage, ElMessage, ElTable, ElTableColumn } from 'element-plus' import { ElButton, ElCard, ElIcon, ElImage, ElMessage, ElTable, ElTableColumn } from 'element-plus'
import { ArrowLeft, Loading } from '@element-plus/icons-vue' import { ArrowLeft, Loading } from '@element-plus/icons-vue'
@@ -75,6 +75,7 @@
OrderPaymentMethod OrderPaymentMethod
} from '@/types/api' } from '@/types/api'
import { useAuth } from '@/composables/useAuth' import { useAuth } from '@/composables/useAuth'
import { useUserStore } from '@/store/modules/user'
import { formatDateTime } from '@/utils/business/format' import { formatDateTime } from '@/utils/business/format'
defineOptions({ name: 'OrderDetail' }) defineOptions({ name: 'OrderDetail' })
@@ -82,6 +83,7 @@
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const { hasAuth } = useAuth() const { hasAuth } = useAuth()
const userStore = useUserStore()
const loading = ref(false) const loading = ref(false)
const detailData = ref<Order | null>(null) const detailData = ref<Order | null>(null)
@@ -174,163 +176,181 @@
} }
} }
// 检查当前用户是否可以查看实付金额(代理账号和企业账号不能看到)
const canViewActualPaidAmount = computed(() => {
const userType = userStore.info.user_type
// 只有代理账号(3)和企业账号(4)不能看到实付金额
return userType !== 3 && userType !== 4
})
// 详情页配置 // 详情页配置
const detailSections: DetailSection[] = [ const detailSections = computed<DetailSection[]>(() => {
{ const baseFields = [
title: '基本信息', { label: '订单号', prop: 'order_no' },
fields: [ {
{ label: '订单号', prop: 'order_no' }, label: '订单类型',
{ formatter: (_, data) => getOrderTypeText(data.order_type)
label: '订单类型', },
formatter: (_, data) => getOrderTypeText(data.order_type) {
}, label: '支付状态',
{ formatter: (_, data) => data.payment_status_text || '-'
label: '支付状态', },
formatter: (_, data) => data.payment_status_text || '-' {
}, label: '订单金额',
{ prop: 'total_amount',
label: '订单金额', formatter: (value) => formatCurrency(value)
prop: 'total_amount', }
formatter: (value) => formatCurrency(value) ]
},
{
label: '实付金额',
prop: 'actual_paid_amount',
formatter: (value) =>
value !== undefined && value !== null ? formatCurrency(value) : '-'
},
{
label: '支付凭证',
fullWidth: true,
render: (data) => {
if (!data.payment_voucher_key || !hasAuth('orders:view_payment_voucher')) {
return h('span', '-')
}
if (!paymentVoucherUrl.value) { // 只有非代理账号和非企业账号才能看到实付金额字段
return h('span', '加载中...') if (canViewActualPaidAmount.value) {
} baseFields.push({
label: '实付金额',
return h(ElImage, { prop: 'actual_paid_amount',
src: paymentVoucherUrl.value, formatter: (value) =>
previewSrcList: [paymentVoucherUrl.value], value !== undefined && value !== null ? formatCurrency(value) : '-'
fit: 'cover', })
style: {
width: '120px',
height: '120px',
borderRadius: '8px',
border: '1px solid var(--el-border-color-light)'
}
})
}
},
{
label: '买家类型',
formatter: (_, data) => (data.buyer_type ? getBuyerTypeText(data.buyer_type) : '-')
},
{
label: '买家手机号',
prop: 'buyer_phone',
formatter: (value) => value || '-'
},
{
label: '买家昵称',
prop: 'buyer_nickname',
formatter: (value) => value || '-'
},
{
label: '订单渠道',
formatter: (_, data) =>
data.purchase_role ? getPurchaseRoleText(data.purchase_role) : '-'
},
{
label: '购买备注',
prop: 'purchase_remark',
formatter: (value) => value || '-'
},
{
label: '支付时间',
prop: 'paid_at',
formatter: (value) => (value ? formatDateTime(value) : '-')
},
{
label: '是否上级代购',
formatter: (_, data) => (data.is_purchased_by_parent ? '是' : '否')
},
{
label: 'ICCID/VirtualNo',
prop: 'asset_identifier',
formatter: (value) => value || '-'
},
{
label: '是否超时',
formatter: (_, data) => {
if (data.is_expired === undefined || data.is_expired === null) return '-'
return data.is_expired ? '是' : '否'
}
},
{
label: '超时时间',
prop: 'expires_at',
formatter: (value) => (value ? formatDateTime(value) : '-')
},
{
label: '创建时间',
prop: 'created_at',
formatter: (value) => formatDateTime(value)
},
{
label: '更新时间',
prop: 'updated_at',
formatter: (value) => formatDateTime(value)
}
]
},
{
title: '操作者信息',
fields: [
{
label: '操作者类型',
prop: 'operator_type',
formatter: (value) => getOperatorTypeText(value)
},
{
label: '操作者名称',
prop: 'operator_name',
formatter: (value) => value || '-'
}
]
},
{
title: '业务归属信息',
fields: [
{
label: '销售店铺名称',
prop: 'seller_shop_name',
formatter: (value) => value || '-'
}
]
},
{
title: '佣金信息',
fields: [
{
label: '流程状态',
formatter: (_, data) =>
getCommissionStatusText(data.commission_status, data.commission_status_name)
},
{
label: '业务结果',
formatter: (_, data) =>
getCommissionResultText(data.commission_result, data.commission_result_name)
},
{
label: '佣金配置版本',
prop: 'commission_config_version'
}
]
} }
]
baseFields.push(
{
label: '支付凭证',
fullWidth: true,
render: (data) => {
if (!data.payment_voucher_key || !hasAuth('orders:view_payment_voucher')) {
return h('span', '-')
}
if (!paymentVoucherUrl.value) {
return h('span', '加载中...')
}
return h(ElImage, {
src: paymentVoucherUrl.value,
previewSrcList: [paymentVoucherUrl.value],
fit: 'cover',
style: {
width: '120px',
height: '120px',
borderRadius: '8px',
border: '1px solid var(--el-border-color-light)'
}
})
}
},
{
label: '买家类型',
formatter: (_, data) => (data.buyer_type ? getBuyerTypeText(data.buyer_type) : '-')
},
{
label: '买家手机号',
prop: 'buyer_phone',
formatter: (value) => value || '-'
},
{
label: '买家昵称',
prop: 'buyer_nickname',
formatter: (value) => value || '-'
},
{
label: '订单渠道',
formatter: (_, data) =>
data.purchase_role ? getPurchaseRoleText(data.purchase_role) : '-'
},
{
label: '购买备注',
prop: 'purchase_remark',
formatter: (value) => value || '-'
},
{
label: '支付时间',
prop: 'paid_at',
formatter: (value) => (value ? formatDateTime(value) : '-')
},
{
label: '是否上级代购',
formatter: (_, data) => (data.is_purchased_by_parent ? '是' : '否')
},
{
label: 'ICCID/VirtualNo',
prop: 'asset_identifier',
formatter: (value) => value || '-'
},
{
label: '是否超时',
formatter: (_, data) => {
if (data.is_expired === undefined || data.is_expired === null) return '-'
return data.is_expired ? '是' : '否'
}
},
{
label: '超时时间',
prop: 'expires_at',
formatter: (value) => (value ? formatDateTime(value) : '-')
},
{
label: '创建时间',
prop: 'created_at',
formatter: (value) => formatDateTime(value)
},
{
label: '更新时间',
prop: 'updated_at',
formatter: (value) => formatDateTime(value)
}
)
return [
{
title: '基本信息',
fields: baseFields
},
{
title: '操作者信息',
fields: [
{
label: '操作者类型',
prop: 'operator_type',
formatter: (value) => getOperatorTypeText(value)
},
{
label: '操作者名称',
prop: 'operator_name',
formatter: (value) => value || '-'
}
]
},
{
title: '业务归属信息',
fields: [
{
label: '销售店铺名称',
prop: 'seller_shop_name',
formatter: (value) => value || '-'
}
]
},
{
title: '佣金信息',
fields: [
{
label: '流程状态',
formatter: (_, data) =>
getCommissionStatusText(data.commission_status, data.commission_status_name)
},
{
label: '业务结果',
formatter: (_, data) =>
getCommissionResultText(data.commission_result, data.commission_result_name)
},
{
label: '佣金配置版本',
prop: 'commission_config_version'
}
]
}
]
})
// 返回上一页 // 返回上一页
const handleBack = () => { const handleBack = () => {

View File

@@ -489,26 +489,37 @@
}) })
// 列配置 // 列配置
const columnOptions = [ const columnOptions = computed(() => {
{ label: '订单编号', prop: 'order_no' }, const options = [
{ label: '买家手机号', prop: 'buyer_phone' }, { label: '订单编号', prop: 'order_no' },
{ label: '买家昵称', prop: 'buyer_nickname' }, { label: '买家手机号', prop: 'buyer_phone' },
{ label: '订单类型', prop: 'order_type' }, { label: '买家昵称', prop: 'buyer_nickname' },
{ label: '买家类型', prop: 'buyer_type' }, { label: '订单类型', prop: 'order_type' },
{ label: '资产标识符', prop: 'asset_identifier' }, { label: '买家类型', prop: 'buyer_type' },
{ label: '订单渠道', prop: 'purchase_role' }, { label: '资产标识符', prop: 'asset_identifier' },
{ label: '购买备注', prop: 'purchase_remark' }, { label: '订单渠道', prop: 'purchase_role' },
{ label: '下单时间', prop: 'created_at' }, { label: '购买备注', prop: 'purchase_remark' },
{ label: '操作者', prop: 'operator_name' }, { label: '下单时间', prop: 'created_at' },
{ label: '销售店铺', prop: 'seller_shop_name' }, { label: '操作者', prop: 'operator_name' },
{ label: '支付状态', prop: 'payment_status' }, { label: '销售店铺', prop: 'seller_shop_name' },
{ label: '佣金流程状态', prop: 'commission_status_name' }, { label: '支付状态', prop: 'payment_status' },
{ label: '佣金业务结果', prop: 'commission_result_name' }, { label: '佣金流程状态', prop: 'commission_status_name' },
{ label: '订单金额', prop: 'total_amount' }, { label: '佣金业务结果', prop: 'commission_result_name' },
{ label: '实付金额', prop: 'actual_paid_amount' }, { label: '订单金额', prop: 'total_amount' }
{ label: '支付方式', prop: 'payment_method' }, ]
{ label: '支付时间', prop: 'paid_at' }
] // 只有非代理账号和非企业账号才能看到实付金额选项
if (canViewActualPaidAmount.value) {
options.push({ label: '实付金额', prop: 'actual_paid_amount' })
}
options.push(
{ label: '支付方式', prop: 'payment_method' },
{ label: '支付时间', prop: 'paid_at' }
)
return options
})
const createFormRef = ref<FormInstance>() const createFormRef = ref<FormInstance>()
const uploadRef = ref<UploadInstance>() const uploadRef = ref<UploadInstance>()
@@ -858,169 +869,187 @@
} }
} }
// 检查当前用户是否可以查看实付金额(代理账号和企业账号不能看到)
const canViewActualPaidAmount = computed(() => {
const userType = userStore.info.user_type
// 只有代理账号(3)和企业账号(4)不能看到实付金额
return userType !== 3 && userType !== 4
})
// 动态列配置 // 动态列配置
const { columnChecks, columns } = useCheckedColumns(() => [ const { columnChecks, columns } = useCheckedColumns(() => {
{ const baseColumns = [
prop: 'order_no', {
label: '订单编号', prop: 'order_no',
minWidth: 220, label: '订单编号',
showOverflowTooltip: true, minWidth: 220,
formatter: (row: Order) => { showOverflowTooltip: true,
return h( formatter: (row: Order) => {
'span', return h(
{ 'span',
style: 'color: var(--el-color-primary); cursor: pointer; text-decoration: underline;', {
onClick: (e: MouseEvent) => { style: 'color: var(--el-color-primary); cursor: pointer; text-decoration: underline;',
e.stopPropagation() onClick: (e: MouseEvent) => {
handleNameClick(row) e.stopPropagation()
} handleNameClick(row)
}, }
row.order_no },
) row.order_no
} )
},
{
prop: 'buyer_phone',
label: '买家手机号',
width: 130,
formatter: (row: Order) => row.buyer_phone || '-'
},
{
prop: 'buyer_nickname',
label: '买家昵称',
width: 130,
formatter: (row: Order) => row.buyer_nickname || '-'
},
{
prop: 'order_type',
label: '订单类型',
width: 120,
formatter: (row: Order) => {
return h(ElTag, { type: row.order_type === 'single_card' ? 'primary' : 'success' }, () =>
getOrderTypeText(row.order_type)
)
}
},
{
prop: 'buyer_type',
label: '买家类型',
width: 120,
formatter: (row: Order) => {
return h(ElTag, { type: row.buyer_type === 'personal' ? 'info' : 'warning' }, () =>
getBuyerTypeText(row.buyer_type)
)
}
},
{
prop: 'payment_status',
label: '支付状态',
width: 120,
formatter: (row: Order) => {
return h(
ElTag,
{ type: getPaymentStatusType(row.payment_status) },
() => row.payment_status_text
)
}
},
{
prop: 'asset_identifier',
label: '资产标识符',
width: 180,
showOverflowTooltip: true,
formatter: (row: Order) => row.asset_identifier || '-'
},
{
prop: 'purchase_role',
label: '订单渠道',
width: 140,
formatter: (row: Order) => {
if (!row.purchase_role) return '-'
const roleTypeMap: Record<string, 'success' | 'info' | 'warning' | 'danger'> = {
self_purchase: 'success',
purchased_by_parent: 'warning',
purchased_by_platform: 'danger',
purchase_for_subordinate: 'info'
} }
return h( },
ElTag, {
{ type: roleTypeMap[row.purchase_role || ''] || 'info', size: 'small' }, prop: 'buyer_phone',
() => getPurchaseRoleText(row.purchase_role || '') label: '买家手机号',
) width: 130,
formatter: (row: Order) => row.buyer_phone || '-'
},
{
prop: 'buyer_nickname',
label: '买家昵称',
width: 130,
formatter: (row: Order) => row.buyer_nickname || '-'
},
{
prop: 'order_type',
label: '订单类型',
width: 120,
formatter: (row: Order) => {
return h(ElTag, { type: row.order_type === 'single_card' ? 'primary' : 'success' }, () =>
getOrderTypeText(row.order_type)
)
}
},
{
prop: 'buyer_type',
label: '买家类型',
width: 120,
formatter: (row: Order) => {
return h(ElTag, { type: row.buyer_type === 'personal' ? 'info' : 'warning' }, () =>
getBuyerTypeText(row.buyer_type)
)
}
},
{
prop: 'payment_status',
label: '支付状态',
width: 120,
formatter: (row: Order) => {
return h(
ElTag,
{ type: getPaymentStatusType(row.payment_status) },
() => row.payment_status_text
)
}
},
{
prop: 'asset_identifier',
label: '资产标识符',
width: 180,
showOverflowTooltip: true,
formatter: (row: Order) => row.asset_identifier || '-'
},
{
prop: 'purchase_role',
label: '订单渠道',
width: 140,
formatter: (row: Order) => {
if (!row.purchase_role) return '-'
const roleTypeMap: Record<string, 'success' | 'info' | 'warning' | 'danger'> = {
self_purchase: 'success',
purchased_by_parent: 'warning',
purchased_by_platform: 'danger',
purchase_for_subordinate: 'info'
}
return h(
ElTag,
{ type: roleTypeMap[row.purchase_role || ''] || 'info', size: 'small' },
() => getPurchaseRoleText(row.purchase_role || '')
)
}
},
{
prop: 'purchase_remark',
label: '购买备注',
minWidth: 180,
showOverflowTooltip: true,
formatter: (row: Order) => row.purchase_remark || '-'
},
{
prop: 'created_at',
label: '下单时间',
width: 180,
formatter: (row: Order) => formatDateTime(row.created_at)
},
{
prop: 'operator_name',
label: '操作者',
width: 140,
formatter: (row: Order) => row.operator_name || '-'
},
{
prop: 'seller_shop_name',
label: '销售店铺',
width: 160,
showOverflowTooltip: true,
formatter: (row: Order) => row.seller_shop_name || '-'
},
{
prop: 'commission_status_name',
label: '佣金流程状态',
width: 140,
formatter: (row: Order) =>
h(ElTag, { type: getCommissionStatusType(row.commission_status), size: 'small' }, () =>
getCommissionStatusText(row.commission_status, row.commission_status_name)
)
},
{
prop: 'commission_result_name',
label: '佣金业务结果',
width: 140,
formatter: (row: Order) =>
h(ElTag, { type: getCommissionResultType(row.commission_result), size: 'small' }, () =>
getCommissionResultText(row.commission_result, row.commission_result_name)
)
},
{
prop: 'total_amount',
label: '订单金额',
width: 120,
formatter: (row: Order) => formatCurrency(row.total_amount)
} }
}, ]
{
prop: 'purchase_remark', // 只有非代理账号和非企业账号才能看到实付金额列
label: '购买备注', if (canViewActualPaidAmount.value) {
minWidth: 180, baseColumns.push({
showOverflowTooltip: true, prop: 'actual_paid_amount',
formatter: (row: Order) => row.purchase_remark || '-' label: '实付金额',
}, width: 120,
{ formatter: (row: Order) => {
prop: 'created_at', if (row.actual_paid_amount === undefined || row.actual_paid_amount === null) return '-'
label: '下单时间', return formatCurrency(row.actual_paid_amount)
width: 180, }
formatter: (row: Order) => formatDateTime(row.created_at) })
},
{
prop: 'operator_name',
label: '操作者',
width: 140,
formatter: (row: Order) => row.operator_name || '-'
},
{
prop: 'seller_shop_name',
label: '销售店铺',
width: 160,
showOverflowTooltip: true,
formatter: (row: Order) => row.seller_shop_name || '-'
},
{
prop: 'commission_status_name',
label: '佣金流程状态',
width: 140,
formatter: (row: Order) =>
h(ElTag, { type: getCommissionStatusType(row.commission_status), size: 'small' }, () =>
getCommissionStatusText(row.commission_status, row.commission_status_name)
)
},
{
prop: 'commission_result_name',
label: '佣金业务结果',
width: 140,
formatter: (row: Order) =>
h(ElTag, { type: getCommissionResultType(row.commission_result), size: 'small' }, () =>
getCommissionResultText(row.commission_result, row.commission_result_name)
)
},
{
prop: 'total_amount',
label: '订单金额',
width: 120,
formatter: (row: Order) => formatCurrency(row.total_amount)
},
{
prop: 'actual_paid_amount',
label: '实付金额',
width: 120,
formatter: (row: Order) => {
if (row.actual_paid_amount === undefined || row.actual_paid_amount === null) return '-'
return formatCurrency(row.actual_paid_amount)
}
},
{
prop: 'payment_method',
label: '支付方式',
width: 120,
formatter: (row: Order) => getPaymentMethodText(row.payment_method)
},
{
prop: 'paid_at',
label: '支付时间',
width: 180,
formatter: (row: Order) => (row.paid_at ? formatDateTime(row.paid_at) : '-')
} }
])
baseColumns.push(
{
prop: 'payment_method',
label: '支付方式',
width: 120,
formatter: (row: Order) => getPaymentMethodText(row.payment_method)
},
{
prop: 'paid_at',
label: '支付时间',
width: 180,
formatter: (row: Order) => (row.paid_at ? formatDateTime(row.paid_at) : '-')
}
)
return baseColumns
})
// 当订单类型切换时,清空已选择的套餐 // 当订单类型切换时,清空已选择的套餐
watch( watch(