Files
one-pipe-system/src/components/business/CommissionRecordDetailDialog.vue
2026-09-17 12:16:20 +08:00

270 lines
9.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<ElDialog
:model-value="modelValue"
title="佣金明细详情"
width="780px"
@update:model-value="handleVisibleChange"
@closed="handleDialogClosed"
>
<div v-loading="loading" class="commission-record-detail">
<template v-if="record">
<ElDescriptions :column="2" border size="small">
<ElDescriptionsItem label="记录类型">
<ElTag :type="isClawback ? 'danger' : 'primary'" size="small">
{{ recordSourceName }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="状态">
<ElTag :type="statusTagType" size="small">
{{ record.status_name || statusName }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="佣金金额">
<span :class="{ 'amount-negative': isNegative(record.amount) }">
{{ formatMoney(record.amount) }}
</span>
</ElDescriptionsItem>
<ElDescriptionsItem label="入账后佣金余额">
<span :class="{ 'amount-negative': isNegative(record.balance_after) }">
{{ formatMoney(record.balance_after) }}
</span>
</ElDescriptionsItem>
<ElDescriptionsItem label="佣金来源">
<ElTag :type="sourceTagType" size="small">{{ sourceName }}</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="是否可提现">
<ElTag v-if="isClawback" type="danger" size="small">不可提现</ElTag>
<span v-else>可提现</span>
</ElDescriptionsItem>
<ElDescriptionsItem label="订单号">{{ record.order_no || '-' }}</ElDescriptionsItem>
<ElDescriptionsItem label="卖家店铺">
{{ record.seller_shop_name || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="ICCID">{{ record.iccid || '-' }}</ElDescriptionsItem>
<ElDescriptionsItem label="设备虚拟号">
{{ record.virtual_no || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="记录生成时间">
{{ record.created_at ? formatDateTime(record.created_at) : '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="佣金入账时间">
{{ record.released_at ? formatDateTime(record.released_at) : '-' }}
</ElDescriptionsItem>
<template v-if="isClawback">
<ElDescriptionsItem label="被回溯原佣金ID">
{{ record.original_commission_id ?? '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="来源退款单号">
{{ record.refund_no || '-' }}
</ElDescriptionsItem>
</template>
</ElDescriptions>
<template v-if="!isClawback">
<div class="detail-section-title">
回溯明细
<span class="detail-section-summary">
累计回溯金额{{ formatMoney(clawbackTotalAmount) }}
</span>
</div>
<ElTable :data="clawbackRecords" size="small" border :max-height="260">
<ElTableColumn label="回溯金额" prop="amount" width="120">
<template #default="{ row }">
<span class="amount-negative">{{ formatMoney(row.amount) }}</span>
</template>
</ElTableColumn>
<ElTableColumn label="回溯后余额" prop="balance_after" width="130">
<template #default="{ row }">
<span :class="{ 'amount-negative': isNegative(row.balance_after) }">
{{ formatMoney(row.balance_after) }}
</span>
</template>
</ElTableColumn>
<ElTableColumn
label="来源退款单号"
prop="refund_no"
min-width="180"
show-overflow-tooltip
>
<template #default="{ row }">{{ row.refund_no || '-' }}</template>
</ElTableColumn>
<ElTableColumn label="状态" prop="status_name" width="100">
<template #default="{ row }">
<ElTag type="danger" size="small">{{ row.status_name || '回溯' }}</ElTag>
</template>
</ElTableColumn>
<ElTableColumn label="生成时间" prop="created_at" width="180">
<template #default="{ row }">
{{ row.created_at ? formatDateTime(row.created_at) : '-' }}
</template>
</ElTableColumn>
</ElTable>
</template>
<template v-else-if="originalCommission">
<div class="detail-section-title">来源原佣金</div>
<ElDescriptions :column="2" border size="small">
<ElDescriptionsItem label="原佣金记录ID">
{{ originalCommission.id }}
</ElDescriptionsItem>
<ElDescriptionsItem label="原佣金金额">
{{ formatMoney(originalCommission.amount) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="原佣金余额">
{{ formatMoney(originalCommission.balance_after) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="原佣金状态">
{{ originalCommission.status_name || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="订单号">
{{ originalCommission.order_no || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="佣金入账时间">
{{
originalCommission.released_at
? formatDateTime(originalCommission.released_at)
: '-'
}}
</ElDescriptionsItem>
</ElDescriptions>
</template>
</template>
<ElEmpty v-else-if="!loading" description="佣金明细不存在" />
</div>
</ElDialog>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { CommissionService } from '@/api/modules'
import type { ShopCommissionRecordDetail, ShopCommissionRecordSource } from '@/types/api'
import {
COMMISSION_RECORD_SOURCE_MAP,
CommissionSourceMap,
CommissionStatusMap,
isCommissionClawbackRecord
} from '@/config/constants/commission'
import { formatDateTime, formatMoney } from '@/utils/business/format'
import { getErrorMessage } from '@/utils/business'
defineOptions({ name: 'CommissionRecordDetailDialog' })
const props = withDefaults(
defineProps<{
modelValue: boolean
shopId?: number | null
recordId?: number | null
source?: ShopCommissionRecordSource
}>(),
{
shopId: null,
recordId: null,
source: 'original'
}
)
const emit = defineEmits<{
'update:modelValue': [value: boolean]
}>()
const loading = ref(false)
const detail = ref<ShopCommissionRecordDetail | null>(null)
const record = computed(() => detail.value?.record || null)
const isClawback = computed(() =>
isCommissionClawbackRecord({
source: detail.value?.source || props.source,
status: detail.value?.record?.status
})
)
const commissionStatusMeta = computed(
() =>
CommissionStatusMap[Number(record.value?.status) as keyof typeof CommissionStatusMap] || null
)
const commissionSourceMeta = computed(
() =>
CommissionSourceMap[
(record.value?.commission_source || '') as keyof typeof CommissionSourceMap
] || null
)
const recordSourceMeta = computed(
() => COMMISSION_RECORD_SOURCE_MAP[isClawback.value ? 'clawback' : 'original']
)
const recordSourceName = computed(() => recordSourceMeta.value.label)
const statusName = computed(() => commissionStatusMeta.value?.label || '-')
const statusTagType = computed(() => commissionStatusMeta.value?.type || 'info')
const sourceName = computed(
() => commissionSourceMeta.value?.label || record.value?.commission_source || '-'
)
const sourceTagType = computed(() => commissionSourceMeta.value?.type || 'info')
const clawbackRecords = computed(() => detail.value?.clawback_records ?? [])
const clawbackTotalAmount = computed(() => record.value?.clawback_total_amount ?? 0)
const originalCommission = computed(() => detail.value?.original_commission || null)
const isNegative = (value?: number | null) => typeof value === 'number' && value < 0
const loadDetail = async () => {
if (!props.shopId || !props.recordId) return
loading.value = true
detail.value = null
try {
const res = await CommissionService.getShopCommissionRecordDetail(
props.shopId,
props.recordId,
props.source
)
if (res.code === 0) {
detail.value = res.data
} else {
ElMessage.error(res.msg || '佣金明细不存在')
}
} catch (error) {
ElMessage.error(getErrorMessage(error, '佣金明细不存在'))
} finally {
loading.value = false
}
}
const handleVisibleChange = (value: boolean) => {
emit('update:modelValue', value)
}
const handleDialogClosed = () => {
detail.value = null
}
watch(
() => [props.modelValue, props.shopId, props.recordId, props.source] as const,
([visible]) => {
if (visible) loadDetail()
}
)
</script>
<style scoped lang="scss">
.commission-record-detail {
min-height: 120px;
}
.amount-negative {
color: var(--el-color-danger);
}
.detail-section-title {
display: flex;
align-items: center;
justify-content: space-between;
margin: 16px 0 8px;
font-size: 14px;
font-weight: 600;
}
.detail-section-summary {
font-size: 12px;
font-weight: 400;
color: var(--el-text-color-secondary);
}
</style>