fix: bug
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 2m9s

This commit is contained in:
sexygoat
2026-04-23 14:59:05 +08:00
parent a9467e8a0c
commit a5e76313cb
28 changed files with 1284 additions and 702 deletions

View File

@@ -1,77 +1,24 @@
<template>
<div class="refund-detail-page">
<ElCard shadow="never" v-loading="loading">
<template #header>
<div class="card-header">
<span>退款详情</span>
<ElButton @click="handleGoBack">返回</ElButton>
</div>
</template>
<ElCard shadow="never">
<!-- 页面头部 -->
<div class="detail-header">
<ElButton @click="handleBack">
<template #icon>
<ElIcon><ArrowLeft /></ElIcon>
</template>
返回
</ElButton>
<h2 class="detail-title">{{ pageTitle }}</h2>
</div>
<ElDescriptions :column="2" border v-if="refund">
<ElDescriptionsItem label="退款单号">{{ refund.refund_no }}</ElDescriptionsItem>
<ElDescriptionsItem label="状态">
<ElTag :type="getStatusType(refund.status)">{{ getStatusText(refund.status) }}</ElTag>
</ElDescriptionsItem>
<!-- 详情内容 -->
<DetailPage v-if="refund" :sections="detailSections" :data="refund" />
<ElDescriptionsItem label="申请退款金额">
{{ formatCurrency(refund.requested_refund_amount) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="实际退款金额">
{{ refund.approved_refund_amount ? formatCurrency(refund.approved_refund_amount) : '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="实收金额">
{{ formatCurrency(refund.actual_received_amount) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="资产重置">
<ElTag :type="refund.asset_reset ? 'success' : 'info'">
{{ refund.asset_reset ? '是' : '否' }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="佣金扣除">
<ElTag :type="refund.commission_deducted ? 'success' : 'info'">
{{ refund.commission_deducted ? '是' : '否' }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="退款原因">
{{ refund.refund_reason || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="拒绝原因">
{{ refund.reject_reason || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="审批时间">
{{ refund.processed_at ? formatDateTime(refund.processed_at) : '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="审批备注">
{{ refund.remark || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="创建时间">
{{ formatDateTime(refund.created_at) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="更新时间">
{{ formatDateTime(refund.updated_at) }}
</ElDescriptionsItem>
</ElDescriptions>
<div class="action-buttons" v-if="refund">
<!-- 待审批状态显示审批操作 -->
<template v-if="refund.status === 1">
<ElButton type="primary" @click="handleShowApprove">审批通过</ElButton>
<ElButton type="danger" @click="handleShowReject">审批拒绝</ElButton>
<ElButton type="warning" @click="handleShowReturn">退回</ElButton>
</template>
<!-- 已拒绝或已退回状态显示重新提交 -->
<template v-if="refund.status === 3 || refund.status === 4">
<ElButton type="primary" @click="handleShowResubmit">重新提交</ElButton>
</template>
<!-- 加载中 -->
<div v-if="loading" class="loading-container">
<ElIcon class="is-loading"><Loading /></ElIcon>
<span>加载中...</span>
</div>
</ElCard>
@@ -247,11 +194,13 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ref, onMounted, computed, h } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElCard, ElButton, ElIcon, ElMessage, ElTag } from 'element-plus'
import { ArrowLeft, Loading } from '@element-plus/icons-vue'
import DetailPage from '@/components/common/DetailPage.vue'
import type { DetailSection } from '@/components/common/DetailPage.vue'
import { RefundService } from '@/api/modules'
import { ElMessage, ElTag } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import type {
Refund,
RefundStatus,
@@ -261,38 +210,39 @@
ResubmitRefundRequest
} from '@/types/api'
import { formatDateTime } from '@/utils/business/format'
import { RoutesAlias } from '@/router/routesAlias'
defineOptions({ name: 'RefundDetail' })
const router = useRouter()
const route = useRoute()
const router = useRouter()
const loading = ref(false)
const approveLoading = ref(false)
const rejectLoading = ref(false)
const returnLoading = ref(false)
const resubmitLoading = ref(false)
const refund = ref<Refund | null>(null)
const pageTitle = computed(() => `退款详情`)
const approveDialogVisible = ref(false)
const rejectDialogVisible = ref(false)
const returnDialogVisible = ref(false)
const resubmitDialogVisible = ref(false)
const approveFormRef = ref<FormInstance>()
const rejectFormRef = ref<FormInstance>()
const returnFormRef = ref<FormInstance>()
const resubmitFormRef = ref<FormInstance>()
const approveLoading = ref(false)
const rejectLoading = ref(false)
const returnLoading = ref(false)
const resubmitLoading = ref(false)
const approveRules = reactive<FormRules>({})
const approveFormRef = ref()
const rejectFormRef = ref()
const returnFormRef = ref()
const resubmitFormRef = ref()
const rejectRules = reactive<FormRules>({
const approveRules = ref()
const rejectRules = ref({
reject_reason: [{ required: true, message: '请输入拒绝原因', trigger: 'blur' }]
})
const returnRules = reactive<FormRules>({})
const resubmitRules = reactive<FormRules>({})
const returnRules = ref()
const resubmitRules = ref()
const approveForm = reactive<ApproveRefundRequest>({
approved_refund_amount: undefined,
@@ -317,23 +267,20 @@
refund_reason: ''
})
// 格式化货币 - 将分转换为元
const formatCurrency = (amount: number): string => {
return `¥${(amount / 100).toFixed(2)}`
}
// 获取状态标签类型
const getStatusType = (status: RefundStatus): 'warning' | 'success' | 'danger' | 'info' => {
const statusMap: Record<RefundStatus, 'warning' | 'success' | 'danger' | 'info'> = {
1: 'warning', // 待审批
2: 'success', // 已通过
3: 'danger', // 已拒绝
4: 'info' // 已退回
1: 'warning',
2: 'success',
3: 'danger',
4: 'info'
}
return statusMap[status] || 'info'
}
// 获取状态文本
const getStatusText = (status: RefundStatus): string => {
const statusMap: Record<RefundStatus, string> = {
1: '待审批',
@@ -344,14 +291,94 @@
return statusMap[status] || '-'
}
onMounted(() => {
const id = route.params.id as string
if (id) {
fetchRefundDetail(Number(id))
const detailSections = computed((): DetailSection[] => [
{
title: '退款信息',
fields: [
{ label: '退款单号', prop: 'refund_no' },
{ label: '店铺名称', prop: 'shop_name' },
{ label: '订单号', prop: 'order_no' },
{ label: '资产标识符', prop: 'asset_identifier' },
{ label: '资产类型', prop: 'asset_type' },
{
label: '申请退款金额',
formatter: (_, data) => formatCurrency(data.requested_refund_amount)
},
{
label: '实际退款金额',
formatter: (_, data) =>
data.approved_refund_amount ? formatCurrency(data.approved_refund_amount) : '-'
},
{
label: '实收金额',
formatter: (_, data) => formatCurrency(data.actual_received_amount)
},
{
label: '状态',
render: (data) =>
h(ElTag, { type: getStatusType(data.status) }, () => getStatusText(data.status))
},
{
label: '资产重置',
render: (data) =>
h(ElTag, { type: data.asset_reset ? 'success' : 'info' }, () =>
data.asset_reset ? '是' : '否'
)
},
{
label: '佣金扣除',
render: (data) =>
h(ElTag, { type: data.commission_deducted ? 'success' : 'info' }, () =>
data.commission_deducted ? '是' : '否'
)
}
]
},
{
title: '退款原因',
fields: [
{
label: '退款原因',
prop: 'refund_reason',
formatter: (value) => value || '-',
fullWidth: true
},
{
label: '拒绝原因',
prop: 'reject_reason',
formatter: (value) => value || '-',
fullWidth: true
},
{
label: '审批备注',
prop: 'remark',
formatter: (value) => value || '-',
fullWidth: true
}
]
},
{
title: '时间信息',
fields: [
{
label: '创建时间',
prop: 'created_at',
formatter: (value) => formatDateTime(value)
},
{
label: '审批时间',
prop: 'processed_at',
formatter: (value) => (value ? formatDateTime(value) : '-')
},
{
label: '更新时间',
prop: 'updated_at',
formatter: (value) => formatDateTime(value)
}
]
}
})
])
// 获取退款详情
const fetchRefundDetail = async (id: number) => {
loading.value = true
try {
@@ -366,24 +393,40 @@
}
}
// 返回
const handleGoBack = () => {
router.back()
const handleBack = () => {
router.push(RoutesAlias.RefundManagement)
}
// 显示审批通过对话框
const handleShowApprove = () => {
approveDialogVisible.value = true
}
onMounted(() => {
const id = route.params.id as string
if (id) {
fetchRefundDetail(Number(id))
}
})
// 审批通过对话框关闭后的清理
const handleApproveDialogClosed = () => {
approveFormRef.value?.resetFields()
approveForm.approved_refund_amount = undefined
approveForm.remark = ''
}
// 审批通过
const handleRejectDialogClosed = () => {
rejectFormRef.value?.resetFields()
rejectForm.reject_reason = ''
}
const handleReturnDialogClosed = () => {
returnFormRef.value?.resetFields()
returnForm.remark = ''
}
const handleResubmitDialogClosed = () => {
resubmitFormRef.value?.resetFields()
resubmitForm.requested_refund_amount = undefined
resubmitForm.actual_received_amount = undefined
resubmitForm.refund_reason = ''
}
const handleApproveRefund = async () => {
if (!approveFormRef.value || !refund.value) return
@@ -411,18 +454,6 @@
})
}
// 显示审批拒绝对话框
const handleShowReject = () => {
rejectDialogVisible.value = true
}
// 审批拒绝对话框关闭后的清理
const handleRejectDialogClosed = () => {
rejectFormRef.value?.resetFields()
rejectForm.reject_reason = ''
}
// 审批拒绝
const handleRejectRefund = async () => {
if (!rejectFormRef.value || !refund.value) return
@@ -443,18 +474,6 @@
})
}
// 显示退回对话框
const handleShowReturn = () => {
returnDialogVisible.value = true
}
// 退回对话框关闭后的清理
const handleReturnDialogClosed = () => {
returnFormRef.value?.resetFields()
returnForm.remark = ''
}
// 退回
const handleReturnRefund = async () => {
if (!returnFormRef.value || !refund.value) return
@@ -475,25 +494,6 @@
})
}
// 显示重新提交对话框
const handleShowResubmit = () => {
if (!refund.value) return
// 预填充原有数据
resubmitForm.requested_refund_amount = refund.value.requested_refund_amount / 100
resubmitForm.actual_received_amount = refund.value.actual_received_amount / 100
resubmitForm.refund_reason = refund.value.refund_reason
resubmitDialogVisible.value = true
}
// 重新提交对话框关闭后的清理
const handleResubmitDialogClosed = () => {
resubmitFormRef.value?.resetFields()
resubmitForm.requested_refund_amount = undefined
resubmitForm.actual_received_amount = undefined
resubmitForm.refund_reason = ''
}
// 重新提交
const handleResubmitRefund = async () => {
if (!resubmitFormRef.value || !refund.value) return
@@ -529,17 +529,32 @@
.refund-detail-page {
padding: 20px;
.card-header {
.detail-header {
display: flex;
gap: 16px;
align-items: center;
justify-content: space-between;
margin-bottom: 24px;
.detail-title {
margin: 0;
font-size: 20px;
font-weight: 600;
color: var(--el-text-color-primary);
}
}
.action-buttons {
.loading-container {
display: flex;
gap: 10px;
justify-content: flex-end;
margin-top: 20px;
flex-direction: column;
gap: 12px;
align-items: center;
justify-content: center;
padding: 60px 0;
color: var(--el-text-color-secondary);
.el-icon {
font-size: 32px;
}
}
}
</style>