应收账单模块,调整枚举代码优化

This commit is contained in:
caojia
2026-09-17 11:00:59 +08:00
parent 5207c00574
commit a17f09683b
26 changed files with 397 additions and 140 deletions
+6 -23
View File
@@ -1,23 +1,6 @@
export const AR_BILL_STATUS = Object.freeze({
DRAFT: 'DRAFT',
CONFIRMED: 'CONFIRMED',
PARTIAL_WRITTEN_OFF: 'PARTIAL_WRITTEN_OFF',
WRITTEN_OFF: 'WRITTEN_OFF',
VOID: 'VOID'
})
export const AR_BILL_STATUS_OPTIONS = Object.freeze([
{ label: '草稿', value: AR_BILL_STATUS.DRAFT },
{ label: '已确认', value: AR_BILL_STATUS.CONFIRMED },
{ label: '部分核销', value: AR_BILL_STATUS.PARTIAL_WRITTEN_OFF },
{ label: '已核销', value: AR_BILL_STATUS.WRITTEN_OFF },
{ label: '已作废', value: AR_BILL_STATUS.VOID }
])
export const AR_BILL_STATUS_TYPES = Object.freeze({
[AR_BILL_STATUS.DRAFT]: 'info',
[AR_BILL_STATUS.CONFIRMED]: 'primary',
[AR_BILL_STATUS.PARTIAL_WRITTEN_OFF]: 'warning',
[AR_BILL_STATUS.WRITTEN_OFF]: 'success',
[AR_BILL_STATUS.VOID]: 'danger'
})
// 保留旧的导入路径,统一从应收枚举文件导出,避免页面各自维护状态编码。
export {
AR_BILL_STATUS,
AR_BILL_STATUS_OPTIONS,
AR_BILL_STATUS_TYPES
} from './enums'
@@ -43,10 +43,10 @@
<el-table :data="detail.exports || []" border size="small">
<el-table-column prop="fileName" label="文件名" min-width="250" show-overflow-tooltip />
<el-table-column prop="templateVersion" label="模板版本" width="100" />
<el-table-column prop="exportStatus" label="状态" width="100"><template #default="{ row }"><el-tag :type="row.exportStatus === 'SUCCESS' ? 'success' : 'danger'">{{ row.exportStatus }}</el-tag></template></el-table-column>
<el-table-column prop="exportStatus" label="状态" width="100"><template #default="{ row }"><el-tag :type="exportStatusType(row.exportStatus)">{{ exportStatusText(row.exportStatus) }}</el-tag></template></el-table-column>
<el-table-column prop="exportBy" label="导出人" width="100" />
<el-table-column prop="exportTime" label="导出时间" width="170" />
<el-table-column label="操作" width="90"><template #default="{ row }"><el-button v-if="row.exportStatus === 'SUCCESS'" link type="primary" @click="$emit('download', row)">下载</el-button></template></el-table-column>
<el-table-column label="操作" width="90"><template #default="{ row }"><el-button v-if="row.exportStatus === AR_EXPORT_STATUS.SUCCESS" link type="primary" @click="$emit('download', row)">下载</el-button></template></el-table-column>
</el-table>
</template>
</div>
@@ -54,13 +54,16 @@
</template>
<script setup>
import { AR_BILL_STATUS_OPTIONS, AR_BILL_STATUS_TYPES, AR_EXPORT_STATUS, AR_EXPORT_STATUS_OPTIONS, AR_EXPORT_STATUS_TYPES, arEnumLabel } from '@/constants/ar/enums'
defineProps({ modelValue: Boolean, detail: { type: Object, default: null }, loading: Boolean })
defineEmits(['update:modelValue', 'download', 'export'])
const statusOptions = [{ label: '草稿', value: 'DRAFT' }, { label: '已确认', value: 'CONFIRMED' }, { label: '部分核销', value: 'PARTIAL_WRITTEN_OFF' }, { label: '已核销', value: 'WRITTEN_OFF' }, { label: '已作废', value: 'VOID' }]
function date(value) { return value ? String(value).slice(0, 10) : '-' }
function money(value) { const num = Number(value); return Number.isNaN(num) ? '-' : num.toFixed(2) }
function statusText(value) { return statusOptions.find(item => item.value === value)?.label || value || '-' }
function statusType(value) { return { DRAFT: 'info', CONFIRMED: 'primary', PARTIAL_WRITTEN_OFF: 'warning', WRITTEN_OFF: 'success', VOID: 'danger' }[value] || 'info' }
function statusText(value) { return arEnumLabel(AR_BILL_STATUS_OPTIONS, value) }
function statusType(value) { return AR_BILL_STATUS_TYPES[value] || 'info' }
function exportStatusText(value) { return arEnumLabel(AR_EXPORT_STATUS_OPTIONS, value) }
function exportStatusType(value) { return AR_EXPORT_STATUS_TYPES[value] || 'info' }
function dimensions(row) { return [row.pkgLength, row.pkgWidth, row.pkgHeight].map(v => v == null ? '-' : v).join(' × ') }
function mask(value) { if (!value) return '-'; return value.length <= 4 ? '****' : '****' + value.slice(-4) }
</script>
+21 -10
View File
@@ -1,30 +1,41 @@
<template>
<div class="app-container">
<basic-table ref="tableRef" :columns="columns" :search-columns="searchColumns" :query="listArBillLogs" row-key="logId" :selection="false">
<template #col-result="{ row }"><el-tag :type="row.result === 'SUCCESS' ? 'success' : 'danger'">{{ resultText(row.result) }}</el-tag></template>
<template #col-result="{ row }"><el-tag :type="AR_LOG_RESULT_TYPES[row.result] || 'info'">{{ resultText(row.result) }}</el-tag></template>
</basic-table>
</div>
</template>
<script setup name="ArBillLog">
import { listArBillLogs } from '@/api/ar/bill'
import {
AR_LOG_OBJECT_TYPE_OPTIONS,
AR_LOG_OPERATION_SOURCE_OPTIONS,
AR_LOG_OPERATION_TYPE_OPTIONS,
AR_LOG_RESULT_OPTIONS,
AR_LOG_RESULT_TYPES,
AR_LOG_STATUS_OPTIONS,
arEnumLabel
} from '@/constants/ar/enums'
const tableRef = ref()
const searchColumns = [
{ label: '对象类型', prop: 'objectType', component: 'select', options: [{ label: '应收账单', value: 'BILL' }, { label: '账单导出', value: 'EXPORT' }, { label: '余额核销', value: 'BALANCE_WRITEOFF' }], width: '130px' },
{ label: '操作类型', prop: 'operationType', component: 'input', width: '140px' }, { label: '结果', prop: 'result', component: 'select', options: [{ label: '成功', value: 'SUCCESS' }, { label: '失败', value: 'FAILED' }], width: '120px' }
{ label: '对象类型', prop: 'objectType', component: 'select', options: AR_LOG_OBJECT_TYPE_OPTIONS, width: '130px' },
{ label: '操作类型', prop: 'operationType', component: 'select', options: AR_LOG_OPERATION_TYPE_OPTIONS, width: '150px' },
{ label: '操作来源', prop: 'operationSource', component: 'select', options: AR_LOG_OPERATION_SOURCE_OPTIONS, width: '130px' },
{ label: '结果', prop: 'result', component: 'select', options: AR_LOG_RESULT_OPTIONS, width: '120px' }
]
const columns = [
{ label: '对象类型', prop: 'objectType', width: 110, formatter: row => objectTypeText(row.objectType) }, { label: '对象', prop: 'objectDisplay', minWidth: 220, showOverflowTooltip: true, formatter: row => row.objectDisplay || '-' },
{ label: '操作', prop: 'operationType', width: 150, formatter: row => operationText(row.operationType) }, { label: '说明', prop: 'operationDesc', minWidth: 220, showOverflowTooltip: true },
{ label: '状态变化', prop: 'status', width: 160, formatter: row => `${statusText(row.fromStatus)} → ${statusText(row.toStatus)}` }, { label: '操作人', prop: 'operatorName', width: 110 },
{ label: '来源', prop: 'operationSource', width: 100, formatter: row => sourceText(row.operationSource) },
{ label: '结果', prop: 'result', width: 90, slot: 'result' }, { label: '时间', prop: 'createTime', width: 170, parseTime: true }
]
const objectTypeLabels = { BILL: '应收账单', EXPORT: '账单导出', BALANCE_WRITEOFF: '余额核销' }
const operationLabels = { CONFIRM: '确认账单', VOID: '作废账单', EXPORT: '导出账单', BALANCE_WRITEOFF: '余额核销', CANCEL_BALANCE_WRITEOFF: '取消余额核销' }
const statusLabels = { DRAFT: '草稿', CONFIRMED: '已确认', PARTIAL_WRITTEN_OFF: '部分核销', WRITTEN_OFF: '已核销', VOID: '已作废', REGISTERED: '已登记', CANCELLED: '已取消', EFFECTIVE: '有效' }
function objectTypeText(value) { return objectTypeLabels[value] || value || '-' }
function operationText(value) { return operationLabels[value] || value || '-' }
function statusText(value) { return statusLabels[value] || value || '-' }
function resultText(value) { return value === 'SUCCESS' ? '成功' : value === 'FAILED' ? '失败' : value || '-' }
function objectTypeText(value) { return arEnumLabel(AR_LOG_OBJECT_TYPE_OPTIONS, value) }
function operationText(value) { return arEnumLabel(AR_LOG_OPERATION_TYPE_OPTIONS, value) }
function sourceText(value) { return arEnumLabel(AR_LOG_OPERATION_SOURCE_OPTIONS, value) }
function statusText(value) { return arEnumLabel(AR_LOG_STATUS_OPTIONS, value) }
function resultText(value) { return arEnumLabel(AR_LOG_RESULT_OPTIONS, value) }
</script>
@@ -485,8 +485,7 @@
<el-form :inline="true" class="search-form">
<el-form-item label="状态">
<el-select v-model="woQuery.status" placeholder="全部" clearable style="width: 130px;">
<el-option label="有效" value="EFFECTIVE" />
<el-option label="已反核销" value="CANCELLED" />
<el-option v-for="item in AR_BALANCE_WRITEOFF_STATUS_OPTIONS" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
@@ -506,8 +505,8 @@
</el-table-column>
<el-table-column label="状态" align="center" width="90">
<template #default="scope">
<el-tag :type="scope.row.status === 'EFFECTIVE' ? 'success' : 'info'" size="small">
{{ scope.row.status === 'EFFECTIVE' ? '有效' : '已反核销' }}
<el-tag :type="AR_BALANCE_WRITEOFF_STATUS_TYPES[scope.row.status] || 'info'" size="small">
{{ formatOption(AR_BALANCE_WRITEOFF_STATUS_OPTIONS, scope.row.status) }}
</el-tag>
</template>
</el-table-column>
@@ -519,7 +518,7 @@
<el-table-column label="反核销原因" align="center" prop="cancelRemark" min-width="130" show-overflow-tooltip />
<el-table-column label="操作" align="center" width="90" fixed="right">
<template #default="scope">
<el-button v-if="scope.row.status === 'EFFECTIVE'" link type="warning" size="small"
<el-button v-if="scope.row.status === AR_BALANCE_WRITEOFF_STATUS.EFFECTIVE" link type="warning" size="small"
@click="openCancelWriteoffDialog(scope.row)"
v-hasPermi="['customer:bill:writeoff:cancel']">反核销</el-button>
<span v-else>-</span>
@@ -899,6 +898,7 @@ import { listAccount, listReceipt, getReceipt, addReceipt, confirmReceipt, cance
import { listUnsettledBill, listBalanceWriteoff, balanceWriteoff, cancelBalanceWriteoff } from "@/api/customersuppliermanagement/customermoney/customerbill.js"
import { convertToBase } from "@/api/data/exchangeRate"
import { getToken } from "@/utils/auth"
import { AR_BALANCE_WRITEOFF_STATUS, AR_BALANCE_WRITEOFF_STATUS_OPTIONS, AR_BALANCE_WRITEOFF_STATUS_TYPES, AR_BILL_STATUS_OPTIONS, AR_BILL_STATUS_TYPES, arEnumLabel } from '@/constants/ar/enums'
import { useRoute } from 'vue-router'
import { nextTick } from 'vue'
@@ -1522,18 +1522,11 @@ function handleCancelApply(row) {
}
/* ================= 账单核销 ================= */
const billStatusMap = {
DRAFT: { label: '草稿', type: 'info' },
CONFIRMED: { label: '已确认', type: 'warning' },
PARTIAL_WRITTEN_OFF: { label: '部分核销', type: 'primary' },
WRITTEN_OFF: { label: '已核销', type: 'success' },
VOID: { label: '已作废', type: 'danger' }
}
function billStatusLabel(v) {
return billStatusMap[v]?.label || v || '-'
return arEnumLabel(AR_BILL_STATUS_OPTIONS, v)
}
function billStatusTag(v) {
return billStatusMap[v]?.type || 'info'
return AR_BILL_STATUS_TYPES[v] || 'info'
}
function formatDate(val) {
if (!val) return '-'