270 lines
9.6 KiB
Vue
270 lines
9.6 KiB
Vue
<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>
|