880 lines
26 KiB
Vue
880 lines
26 KiB
Vue
<template>
|
|
<ArtTableFullScreen>
|
|
<div class="refund-page" id="table-full-screen">
|
|
<!-- 搜索栏 -->
|
|
<ArtSearchBar
|
|
v-model:filter="searchForm"
|
|
:items="searchFormItems"
|
|
show-expand
|
|
@reset="handleReset"
|
|
@search="handleSearch"
|
|
></ArtSearchBar>
|
|
|
|
<ElCard shadow="never" class="art-table-card">
|
|
<!-- 表格头部 -->
|
|
<ArtTableHeader
|
|
:columnList="columnOptions"
|
|
v-model:columns="columnChecks"
|
|
@refresh="handleRefresh"
|
|
>
|
|
<template #left>
|
|
<ElButton type="primary" @click="showCreateDialog" v-if="hasAuth('refund:create')"
|
|
>创建退款申请</ElButton
|
|
>
|
|
<ElButton v-if="hasAuth('refund:export')" @click="exportDialogVisible = true">
|
|
导出
|
|
</ElButton>
|
|
</template>
|
|
</ArtTableHeader>
|
|
|
|
<!-- 表格 -->
|
|
<ArtTable
|
|
ref="tableRef"
|
|
row-key="id"
|
|
:loading="loading"
|
|
:data="refundList"
|
|
:currentPage="pagination.page"
|
|
:pageSize="pagination.page_size"
|
|
:total="pagination.total"
|
|
:marginTop="10"
|
|
:actions="getActions"
|
|
:actionsWidth="160"
|
|
:inlineActionsCount="1"
|
|
@size-change="handleSizeChange"
|
|
@current-change="handleCurrentChange"
|
|
>
|
|
<template #default>
|
|
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
|
|
</template>
|
|
</ArtTable>
|
|
|
|
<!-- 创建退款申请对话框 -->
|
|
<CreateRefundDialog v-model="createDialogVisible" @success="handleCreateSuccess" />
|
|
|
|
<!-- 导出任务对话框 -->
|
|
<ExportTaskCreateDialog
|
|
v-model="exportDialogVisible"
|
|
scene="refund"
|
|
:query="exportQuery"
|
|
confirm-permission="refund:export"
|
|
title="导出退款"
|
|
/>
|
|
|
|
<!-- 退款凭证预览 -->
|
|
<PaymentVoucherDialog
|
|
:file-keys="refundVoucherFileKeys"
|
|
@close="refundVoucherFileKeys = []"
|
|
/>
|
|
|
|
<!-- 重新提交对话框 -->
|
|
<ElDialog
|
|
v-model="resubmitDialogVisible"
|
|
title="重新申请退款"
|
|
width="500px"
|
|
@closed="handleResubmitDialogClosed"
|
|
>
|
|
<ElForm
|
|
ref="resubmitFormRef"
|
|
:model="resubmitForm"
|
|
:rules="resubmitRules"
|
|
label-width="120px"
|
|
>
|
|
<ElFormItem label="退款单号">
|
|
<span>{{ currentRefund?.refund_no }}</span>
|
|
</ElFormItem>
|
|
<ElFormItem label="申请退款金额">
|
|
<ElInputNumber
|
|
v-model="resubmitForm.requested_refund_amount"
|
|
:min="1"
|
|
:precision="2"
|
|
:step="1"
|
|
style="width: 100%"
|
|
placeholder="不填则使用原金额"
|
|
/>
|
|
</ElFormItem>
|
|
<ElFormItem label="实收金额">
|
|
<ElInputNumber
|
|
v-model="resubmitForm.actual_received_amount"
|
|
:min="1"
|
|
:precision="2"
|
|
:step="1"
|
|
style="width: 100%"
|
|
placeholder="不填则使用原金额"
|
|
/>
|
|
</ElFormItem>
|
|
<ElFormItem label="退款原因">
|
|
<ElInput
|
|
v-model="resubmitForm.refund_reason"
|
|
type="textarea"
|
|
:rows="3"
|
|
maxlength="1000"
|
|
show-word-limit
|
|
placeholder="请输入退款原因"
|
|
/>
|
|
</ElFormItem>
|
|
<ElFormItem label="退款凭证" prop="refund_voucher_key">
|
|
<VoucherUpload
|
|
ref="resubmitUploadRef"
|
|
v-model="resubmitForm.refund_voucher_key"
|
|
voucher-name="退款凭证"
|
|
@uploading-change="resubmitVoucherUploading = $event"
|
|
@change="resubmitFormRef?.validateField('refund_voucher_key')"
|
|
@files-change="resubmitForm.attachments = $event"
|
|
/>
|
|
</ElFormItem>
|
|
</ElForm>
|
|
<template #footer>
|
|
<div class="dialog-footer">
|
|
<ElButton @click="resubmitDialogVisible = false">取消</ElButton>
|
|
<ElButton
|
|
type="primary"
|
|
@click="handleResubmitRefund"
|
|
:loading="resubmitLoading || resubmitVoucherUploading"
|
|
:disabled="resubmitVoucherUploading"
|
|
>
|
|
{{ resubmitVoucherUploading ? '凭证上传中...' : '确认申请' }}
|
|
</ElButton>
|
|
</div>
|
|
</template>
|
|
</ElDialog>
|
|
</ElCard>
|
|
</div>
|
|
</ArtTableFullScreen>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, h } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { RefundService, ShopService, OrderService } from '@/api/modules'
|
|
import { ElMessage, ElMessageBox, ElTag, ElButton } from 'element-plus'
|
|
import type { FormInstance, FormRules } from 'element-plus'
|
|
import {
|
|
RefundStatus,
|
|
type Refund,
|
|
type RefundQueryParams,
|
|
type ResubmitRefundRequest,
|
|
type RefundAttachment
|
|
} from '@/types/api'
|
|
import type { SearchFormItem } from '@/types'
|
|
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
|
import { fenToYuan, formatDateTime, yuanToFen } from '@/utils/business/format'
|
|
import {
|
|
getCurrentApproverSummaryText,
|
|
getProcessingStatusText
|
|
} from '@/utils/business/approvalSummary'
|
|
import { toVoucherKeyList } from '@/utils/business'
|
|
import { RoutesAlias } from '@/router/routesAlias'
|
|
import { AUDIT_PERMISSIONS } from '@/config/constants/audit'
|
|
import {
|
|
resolveAuditResourceTarget,
|
|
resolveFinanceAuditTarget
|
|
} from '@/utils/business/auditNavigation'
|
|
import { openAuditInvestigation } from '@/components/business/audit/investigationController'
|
|
import { useUserStore } from '@/store/modules/user'
|
|
import PaymentVoucherDialog from '@/components/business/PaymentVoucherDialog.vue'
|
|
import VoucherUpload from '@/components/business/VoucherUpload.vue'
|
|
import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue'
|
|
|
|
import { useAuth } from '@/composables/useAuth'
|
|
|
|
import CreateRefundDialog from '@/components/business/CreateRefundDialog.vue'
|
|
defineOptions({ name: 'RefundList' })
|
|
|
|
const router = useRouter()
|
|
const userStore = useUserStore()
|
|
const { hasAuth } = useAuth()
|
|
const isRestrictedCustomerRole = computed(() => [3, 4].includes(Number(userStore.info.user_type)))
|
|
const hiddenInternalColumnProps = new Set([
|
|
'approval_provider',
|
|
'submitter_name',
|
|
'current_approver_summary',
|
|
'processing_status_name',
|
|
'refund_reason',
|
|
'reject_reason',
|
|
'remark'
|
|
])
|
|
const shouldShowInternalColumn = (prop?: string) =>
|
|
!isRestrictedCustomerRole.value || !hiddenInternalColumnProps.has(prop || '')
|
|
|
|
const loading = ref(false)
|
|
const resubmitLoading = ref(false)
|
|
const resubmitVoucherUploading = ref(false)
|
|
const triggerApprovalLoading = ref(false)
|
|
const tableRef = ref()
|
|
const resubmitUploadRef = ref<InstanceType<typeof VoucherUpload>>()
|
|
const createDialogVisible = ref(false)
|
|
const exportDialogVisible = ref(false)
|
|
const resubmitDialogVisible = ref(false)
|
|
const currentRefund = ref<Refund | null>(null)
|
|
const refundVoucherFileKeys = ref<string[]>([])
|
|
|
|
// 搜索表单初始值
|
|
const initialSearchState: RefundQueryParams = {
|
|
status: undefined,
|
|
order_id: undefined,
|
|
shop_id: undefined,
|
|
asset_identifier: ''
|
|
}
|
|
|
|
// 搜索表单
|
|
const searchForm = reactive<RefundQueryParams>({ ...initialSearchState })
|
|
|
|
// 店铺选项
|
|
const shopOptions = ref<any[]>([])
|
|
// 订单选项
|
|
const orderOptions = ref<any[]>([])
|
|
// 搜索表单配置
|
|
const searchFormItems: SearchFormItem[] = [
|
|
{
|
|
label: '店铺',
|
|
prop: 'shop_id',
|
|
type: 'select',
|
|
placeholder: '请选择店铺',
|
|
options: () =>
|
|
shopOptions.value.map((shop) => ({
|
|
label: shop.shop_name,
|
|
value: shop.id
|
|
})),
|
|
config: {
|
|
clearable: true,
|
|
filterable: true,
|
|
remote: true,
|
|
remoteMethod: (query: string) => searchShops(query)
|
|
}
|
|
},
|
|
{
|
|
label: '订单号',
|
|
prop: 'order_id',
|
|
type: 'select',
|
|
placeholder: '请选择订单号',
|
|
options: () =>
|
|
orderOptions.value.map((order) => ({
|
|
label: `${order.order_no}`,
|
|
value: order.id
|
|
})),
|
|
config: {
|
|
clearable: true,
|
|
filterable: true,
|
|
remote: true,
|
|
remoteMethod: (query: string) => searchOrdersForFilter(query)
|
|
}
|
|
},
|
|
{
|
|
label: '资产标识',
|
|
prop: 'asset_identifier',
|
|
type: 'input',
|
|
placeholder: '请输入ICCID或设备虚拟号',
|
|
config: {
|
|
clearable: true
|
|
}
|
|
},
|
|
{
|
|
label: '状态',
|
|
prop: 'status',
|
|
type: 'select',
|
|
placeholder: '请选择状态',
|
|
options: [
|
|
{ label: '待审批', value: 1 },
|
|
{ label: '已通过', value: 2 },
|
|
{ label: '已拒绝', value: 3 },
|
|
{ label: '已退回', value: 4 }
|
|
],
|
|
config: {
|
|
clearable: true
|
|
}
|
|
}
|
|
]
|
|
|
|
// 分页
|
|
const pagination = reactive({
|
|
page: 1,
|
|
page_size: 20,
|
|
total: 0
|
|
})
|
|
|
|
// 列配置
|
|
const columnOptions = [
|
|
{ label: '退款单号', prop: 'refund_no' },
|
|
{ label: '店铺名称', prop: 'shop_name' },
|
|
{ label: '订单号', prop: 'order_no' },
|
|
{ label: '资产标识符', prop: 'asset_identifier' },
|
|
{ label: '资产类型', prop: 'asset_type' },
|
|
{ label: '申请退款金额', prop: 'requested_refund_amount' },
|
|
{ label: '实际退款金额', prop: 'approved_refund_amount' },
|
|
{ label: '实收金额', prop: 'actual_received_amount' },
|
|
{ label: '状态', prop: 'status' },
|
|
{ label: '审批渠道', prop: 'approval_provider' },
|
|
{ label: '提交人', prop: 'submitter_name' },
|
|
{ label: '审批状态', prop: 'approval_status' },
|
|
{ label: '当前审批人摘要', prop: 'current_approver_summary' },
|
|
{ label: '业务处理状态', prop: 'processing_status_name' },
|
|
{ label: '退款原因', prop: 'refund_reason' },
|
|
{ label: '拒绝原因', prop: 'reject_reason' },
|
|
{ label: '审批备注', prop: 'remark' },
|
|
{ label: '资产重置', prop: 'asset_reset' },
|
|
{ label: '佣金扣除', prop: 'commission_deducted' },
|
|
{ label: '创建时间', prop: 'created_at' },
|
|
{ label: '审批时间', prop: 'processed_at' },
|
|
{ label: '更新时间', prop: 'updated_at' }
|
|
].filter(({ prop }) => shouldShowInternalColumn(prop))
|
|
|
|
const resubmitFormRef = ref<FormInstance>()
|
|
|
|
const resubmitRules = reactive<FormRules>({})
|
|
|
|
const resubmitForm = reactive<{
|
|
requested_refund_amount?: number
|
|
actual_received_amount?: number
|
|
refund_voucher_key: string[]
|
|
attachments: RefundAttachment[]
|
|
refund_reason?: string
|
|
}>({
|
|
requested_refund_amount: undefined,
|
|
actual_received_amount: undefined,
|
|
refund_voucher_key: [],
|
|
attachments: [],
|
|
refund_reason: ''
|
|
})
|
|
|
|
const refundList = ref<Refund[]>([])
|
|
|
|
// 格式化货币 - 将分转换为元
|
|
const formatCurrency = (amount: number | null | undefined): string => {
|
|
if (amount === undefined || amount === null || Number.isNaN(amount)) return '-'
|
|
|
|
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' // 已退回
|
|
}
|
|
return statusMap[status] || 'info'
|
|
}
|
|
|
|
// 动态列配置
|
|
const { columnChecks, columns } = useCheckedColumns(() =>
|
|
[
|
|
{
|
|
prop: 'refund_no',
|
|
label: '退款单号',
|
|
minWidth: 210,
|
|
formatter: (row: Refund) => {
|
|
return h(
|
|
'span',
|
|
{
|
|
style: 'color: var(--el-color-primary); cursor: pointer; text-decoration: underline;',
|
|
onClick: (e: MouseEvent) => {
|
|
e.stopPropagation()
|
|
handleNameClick(row)
|
|
}
|
|
},
|
|
row.refund_no
|
|
)
|
|
}
|
|
},
|
|
{
|
|
prop: 'shop_name',
|
|
label: '店铺名称',
|
|
width: 160
|
|
},
|
|
{
|
|
prop: 'order_no',
|
|
label: '订单号',
|
|
width: 180,
|
|
showOverflowTooltip: true
|
|
},
|
|
{
|
|
prop: 'asset_identifier',
|
|
label: '资产标识符',
|
|
width: 200,
|
|
showOverflowTooltip: true
|
|
},
|
|
{
|
|
prop: 'asset_type',
|
|
label: '资产类型',
|
|
width: 100,
|
|
formatter: (row: Refund) =>
|
|
row.asset_type === 'device'
|
|
? '设备'
|
|
: row.asset_type === 'card'
|
|
? '单卡'
|
|
: row.asset_type === 'iot_card'
|
|
? 'IoT卡'
|
|
: row.asset_type || '-'
|
|
},
|
|
{
|
|
prop: 'requested_refund_amount',
|
|
label: '申请退款金额',
|
|
width: 150,
|
|
formatter: (row: Refund) => formatCurrency(row.requested_refund_amount)
|
|
},
|
|
{
|
|
prop: 'approved_refund_amount',
|
|
label: '实际退款金额',
|
|
width: 150,
|
|
formatter: (row: Refund) => formatCurrency(row.approved_refund_amount)
|
|
},
|
|
{
|
|
prop: 'actual_received_amount',
|
|
label: '实收金额',
|
|
width: 120,
|
|
formatter: (row: Refund) => formatCurrency(row.actual_received_amount)
|
|
},
|
|
{
|
|
prop: 'status',
|
|
label: '状态',
|
|
width: 100,
|
|
formatter: (row: Refund) => {
|
|
return h(ElTag, { type: getStatusType(row.status) }, () => row.status_name || '-')
|
|
}
|
|
},
|
|
{
|
|
prop: 'approval_provider',
|
|
label: '审批渠道',
|
|
width: 110,
|
|
formatter: (row: Refund) => {
|
|
if (row.approval_provider === 'wecom' || row.approval_source === 'wecom') return '企微'
|
|
if (row.approval_source === 'legacy') return '历史审批'
|
|
return row.approval_provider || row.approval_source || '-'
|
|
}
|
|
},
|
|
{
|
|
prop: 'submitter_name',
|
|
label: '提交人',
|
|
width: 120,
|
|
showOverflowTooltip: true,
|
|
formatter: (row: Refund) => row.submitter_name || '-'
|
|
},
|
|
{
|
|
prop: 'approval_status',
|
|
label: '审批状态',
|
|
width: 120,
|
|
formatter: (row: Refund) => row.approval_status_name || '-'
|
|
},
|
|
{
|
|
prop: 'current_approver_summary',
|
|
label: '当前审批人摘要',
|
|
minWidth: 180,
|
|
showOverflowTooltip: true,
|
|
formatter: (row: Refund) => getCurrentApproverSummaryText(row)
|
|
},
|
|
{
|
|
prop: 'processing_status_name',
|
|
label: '业务处理状态',
|
|
width: 140,
|
|
showOverflowTooltip: true,
|
|
formatter: (row: Refund) => getProcessingStatusText(row)
|
|
},
|
|
{
|
|
prop: 'refund_reason',
|
|
label: '退款原因',
|
|
minWidth: 250,
|
|
showOverflowTooltip: true,
|
|
formatter: (row: Refund) => row.refund_reason || '-'
|
|
},
|
|
{
|
|
prop: 'reject_reason',
|
|
label: '拒绝原因',
|
|
minWidth: 200,
|
|
formatter: (row: Refund) => row.reject_reason || '-'
|
|
},
|
|
{
|
|
prop: 'remark',
|
|
label: '审批备注',
|
|
minWidth: 200,
|
|
formatter: (row: Refund) => row.remark || '-'
|
|
},
|
|
{
|
|
prop: 'asset_reset',
|
|
label: '资产重置',
|
|
width: 100,
|
|
formatter: (row: Refund) => {
|
|
return h(ElTag, { type: row.asset_reset ? 'success' : 'info' }, () =>
|
|
row.asset_reset ? '是' : '否'
|
|
)
|
|
}
|
|
},
|
|
{
|
|
prop: 'commission_deducted',
|
|
label: '佣金扣除',
|
|
width: 100,
|
|
formatter: (row: Refund) => {
|
|
return h(ElTag, { type: row.commission_deducted ? 'success' : 'info' }, () =>
|
|
row.commission_deducted ? '是' : '否'
|
|
)
|
|
}
|
|
},
|
|
{
|
|
prop: 'created_at',
|
|
label: '创建时间',
|
|
width: 180,
|
|
formatter: (row: Refund) => formatDateTime(row.created_at)
|
|
},
|
|
{
|
|
prop: 'processed_at',
|
|
label: '审批时间',
|
|
width: 180,
|
|
formatter: (row: Refund) => (row.processed_at ? formatDateTime(row.processed_at) : '-')
|
|
},
|
|
{
|
|
prop: 'updated_at',
|
|
label: '更新时间',
|
|
width: 180,
|
|
formatter: (row: Refund) => formatDateTime(row.updated_at)
|
|
}
|
|
].filter(({ prop }) => shouldShowInternalColumn(prop))
|
|
)
|
|
|
|
onMounted(() => {
|
|
getTableData()
|
|
searchShops('')
|
|
searchOrdersForFilter('')
|
|
})
|
|
|
|
let isFirstActivation = true
|
|
onActivated(() => {
|
|
if (!isFirstActivation) {
|
|
getTableData()
|
|
}
|
|
isFirstActivation = false
|
|
})
|
|
|
|
// 搜索店铺(用于搜索表单)
|
|
const searchShops = async (query: string) => {
|
|
try {
|
|
const params: any = {
|
|
page: 1,
|
|
page_size: 20
|
|
}
|
|
if (query) {
|
|
params.shop_name = query
|
|
}
|
|
const res = await ShopService.getShops(params)
|
|
if (res.code === 0) {
|
|
shopOptions.value = res.data.items || []
|
|
}
|
|
} catch (error) {
|
|
console.error('Search shops failed:', error)
|
|
}
|
|
}
|
|
|
|
// 搜索订单(用于搜索表单)
|
|
const searchOrdersForFilter = async (query: string) => {
|
|
try {
|
|
const params: any = {
|
|
page: 1,
|
|
page_size: 20
|
|
}
|
|
if (query) {
|
|
params.order_no = query
|
|
}
|
|
const res = await OrderService.getOrders(params)
|
|
if (res.code === 0) {
|
|
orderOptions.value = res.data.items || []
|
|
}
|
|
} catch (error) {
|
|
console.error('Search orders failed:', error)
|
|
}
|
|
}
|
|
|
|
// 获取退款申请列表
|
|
const getTableData = async () => {
|
|
loading.value = true
|
|
try {
|
|
const assetIdentifier = searchForm.asset_identifier?.trim()
|
|
const params: RefundQueryParams = {
|
|
page: pagination.page,
|
|
page_size: pagination.page_size,
|
|
status: searchForm.status,
|
|
order_id: searchForm.order_id,
|
|
shop_id: searchForm.shop_id,
|
|
asset_identifier: assetIdentifier || undefined
|
|
}
|
|
const res = await RefundService.getRefunds(params)
|
|
if (res.code === 0) {
|
|
refundList.value = res.data.items || []
|
|
pagination.total = res.data.total || 0
|
|
}
|
|
} catch (error: any) {
|
|
console.error(error)
|
|
ElMessage.error(error?.message || '重新提交失败')
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const exportQuery = computed(() => ({
|
|
status: searchForm.status,
|
|
order_id: searchForm.order_id,
|
|
shop_id: searchForm.shop_id,
|
|
asset_identifier: searchForm.asset_identifier?.trim() || undefined
|
|
}))
|
|
|
|
// 重置搜索
|
|
const handleReset = () => {
|
|
Object.assign(searchForm, { ...initialSearchState })
|
|
pagination.page = 1
|
|
getTableData()
|
|
}
|
|
|
|
// 搜索
|
|
const handleSearch = () => {
|
|
pagination.page = 1
|
|
getTableData()
|
|
}
|
|
|
|
// 刷新表格
|
|
const handleRefresh = () => {
|
|
getTableData()
|
|
}
|
|
|
|
// 处理表格分页变化
|
|
const handleSizeChange = (newPageSize: number) => {
|
|
pagination.page_size = newPageSize
|
|
getTableData()
|
|
}
|
|
|
|
const handleCurrentChange = (newCurrentPage: number) => {
|
|
pagination.page = newCurrentPage
|
|
getTableData()
|
|
}
|
|
|
|
// 显示创建对话框
|
|
const showCreateDialog = () => {
|
|
createDialogVisible.value = true
|
|
}
|
|
|
|
// 创建退款申请成功
|
|
const handleCreateSuccess = () => {
|
|
getTableData()
|
|
}
|
|
|
|
// 显示重新提交对话框
|
|
const handleShowResubmit = (row: Refund) => {
|
|
currentRefund.value = row
|
|
// 预填充原有数据
|
|
resubmitForm.requested_refund_amount = fenToYuan(row.requested_refund_amount) || undefined
|
|
resubmitForm.actual_received_amount = fenToYuan(row.actual_received_amount) || undefined
|
|
resubmitForm.refund_voucher_key = []
|
|
resubmitForm.attachments = []
|
|
resubmitForm.refund_reason = row.refund_reason
|
|
resubmitDialogVisible.value = true
|
|
}
|
|
|
|
// 重新提交对话框关闭后的清理
|
|
const handleResubmitDialogClosed = () => {
|
|
resubmitFormRef.value?.resetFields()
|
|
resubmitForm.requested_refund_amount = undefined
|
|
resubmitForm.actual_received_amount = undefined
|
|
resubmitForm.refund_voucher_key = []
|
|
resubmitForm.attachments = []
|
|
resubmitForm.refund_reason = ''
|
|
resubmitVoucherUploading.value = false
|
|
resubmitUploadRef.value?.clearFiles(false)
|
|
currentRefund.value = null
|
|
}
|
|
|
|
// 重新提交
|
|
const handleResubmitRefund = async () => {
|
|
if (!resubmitFormRef.value || !currentRefund.value) return
|
|
if (resubmitVoucherUploading.value) {
|
|
ElMessage.warning('退款凭证上传中,请稍候')
|
|
return
|
|
}
|
|
|
|
await resubmitFormRef.value.validate(async (valid) => {
|
|
if (valid) {
|
|
resubmitLoading.value = true
|
|
try {
|
|
const refundId = currentRefund.value?.id
|
|
if (!refundId) return
|
|
const data: ResubmitRefundRequest = {
|
|
requested_refund_amount: yuanToFen(resubmitForm.requested_refund_amount),
|
|
actual_received_amount: yuanToFen(resubmitForm.actual_received_amount),
|
|
refund_reason: resubmitForm.refund_reason || undefined,
|
|
attachments: resubmitForm.attachments
|
|
}
|
|
|
|
await RefundService.resubmitRefund(refundId, data)
|
|
ElMessage.success('重新申请成功')
|
|
resubmitDialogVisible.value = false
|
|
await getTableData()
|
|
} catch (error) {
|
|
console.error(error)
|
|
} finally {
|
|
resubmitLoading.value = false
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
// 处理名称点击
|
|
const handleNameClick = (row: Refund) => {
|
|
if (hasAuth('refund:detail')) {
|
|
handleViewDetail(row)
|
|
} else {
|
|
ElMessage.warning('您没有查看详情的权限')
|
|
}
|
|
}
|
|
|
|
// 查看详情
|
|
const handleViewDetail = (row: Refund) => {
|
|
router.push({
|
|
path: `${RoutesAlias.RefundManagement}/detail/${row.id}`
|
|
})
|
|
}
|
|
|
|
const getRefundAttachmentKeys = (row: Refund) => {
|
|
const keys = row.attachments?.map((attachment) => attachment.file_key).filter(Boolean) || []
|
|
return keys.length ? keys : toVoucherKeyList(row.refund_voucher_key)
|
|
}
|
|
|
|
const canResubmit = (row: Refund) => {
|
|
const statusText = [row.approval_status, row.approval_status_name, row.status_name]
|
|
.filter(Boolean)
|
|
.join(' ')
|
|
.toLowerCase()
|
|
|
|
return (
|
|
row.status === 3 ||
|
|
statusText.includes('reject') ||
|
|
statusText.includes('revoke') ||
|
|
statusText.includes('delete') ||
|
|
statusText.includes('驳回') ||
|
|
statusText.includes('撤销') ||
|
|
statusText.includes('删除')
|
|
)
|
|
}
|
|
|
|
const canTriggerApproval = (row: Refund) => {
|
|
const approvalStatusEmpty = row.approval_status === undefined || row.approval_status === null
|
|
return row.status === RefundStatus.PENDING && approvalStatusEmpty
|
|
}
|
|
|
|
// 补发历史退款审批
|
|
const handleTriggerApproval = (row: Refund) => {
|
|
if (triggerApprovalLoading.value) return
|
|
|
|
ElMessageBox.confirm(`确定要为退款单号 ${row.refund_no} 补发企微审批吗?`, '补发审批', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
})
|
|
.then(async () => {
|
|
triggerApprovalLoading.value = true
|
|
try {
|
|
const res = await RefundService.triggerApproval(row.id)
|
|
if (res.code !== 0) {
|
|
ElMessage.error(res.msg || '补发审批失败')
|
|
return
|
|
}
|
|
ElMessage.success('补发审批成功')
|
|
await getTableData()
|
|
} catch (error) {
|
|
console.error(error)
|
|
ElMessage.error('补发审批失败')
|
|
} finally {
|
|
triggerApprovalLoading.value = false
|
|
}
|
|
})
|
|
.catch(() => {
|
|
// 用户取消
|
|
})
|
|
}
|
|
|
|
// 获取操作按钮
|
|
const getActions = (row: Refund) => {
|
|
const actions: any[] = []
|
|
|
|
const voucherKeys = getRefundAttachmentKeys(row)
|
|
if (
|
|
[1, 2].includes(userStore.getUserInfo.user_type || 0) &&
|
|
voucherKeys.length &&
|
|
hasAuth('refund:view_voucher')
|
|
) {
|
|
actions.push({
|
|
label: '退款凭证',
|
|
handler: () => handleViewRefundVoucher(row),
|
|
type: 'primary'
|
|
})
|
|
}
|
|
|
|
if (
|
|
[1, 2].includes(userStore.getUserInfo.user_type || 0) &&
|
|
hasAuth(AUDIT_PERMISSIONS.refundEntry)
|
|
) {
|
|
const auditTarget = resolveAuditResourceTarget({
|
|
userType: userStore.getUserInfo.user_type,
|
|
resourceType: 'refund',
|
|
internalId: row.id
|
|
})
|
|
if (auditTarget)
|
|
actions.push({
|
|
label: '审计记录',
|
|
handler: () => openAuditInvestigation(auditTarget),
|
|
type: 'primary'
|
|
})
|
|
|
|
if (hasAuth(AUDIT_PERMISSIONS.refundFinanceEntry)) {
|
|
const financeTarget = resolveFinanceAuditTarget('refund_id', row.id)
|
|
if (financeTarget)
|
|
actions.push({
|
|
label: '资金链路',
|
|
handler: () => openAuditInvestigation(financeTarget),
|
|
type: 'primary'
|
|
})
|
|
}
|
|
const approvalTarget = resolveAuditResourceTarget({
|
|
userType: userStore.getUserInfo.user_type,
|
|
resourceType: 'approval_instance',
|
|
internalId: row.approval_instance_id
|
|
})
|
|
if (approvalTarget && hasAuth(AUDIT_PERMISSIONS.refundApprovalEntry))
|
|
actions.push({
|
|
label: '审批审计',
|
|
handler: () => openAuditInvestigation(approvalTarget),
|
|
type: 'primary'
|
|
})
|
|
}
|
|
|
|
if (
|
|
[1, 2].includes(userStore.getUserInfo.user_type || 0) &&
|
|
canTriggerApproval(row) &&
|
|
hasAuth('refund:trigger_approval')
|
|
) {
|
|
actions.push({
|
|
label: '补发审批',
|
|
handler: () => handleTriggerApproval(row),
|
|
type: 'primary'
|
|
})
|
|
}
|
|
|
|
if (canResubmit(row) && hasAuth('refund:resubmit')) {
|
|
actions.push({
|
|
label: '重新申请',
|
|
handler: () => handleShowResubmit(row),
|
|
type: 'primary'
|
|
})
|
|
}
|
|
|
|
return actions
|
|
}
|
|
|
|
const handleViewRefundVoucher = (row: Refund) => {
|
|
const voucherKeys = getRefundAttachmentKeys(row)
|
|
if (!voucherKeys.length) return
|
|
refundVoucherFileKeys.value = voucherKeys
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.refund-page {
|
|
height: 100%;
|
|
}
|
|
</style>
|