feat: 新增发票冲销明细公共组件与独立页面路由
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div class="invoice-write-off-table">
|
||||
<el-table v-loading="loading" :data="rows" border>
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column prop="arrivalAddress" label="到货地址" min-width="150" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : displayValue(row.arrivalAddress) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="actualDepartureTime" label="实际发货时间" width="150" align="center">
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : formatDateTime(row.actualDepartureTime) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="completionTime" label="实际完成时间" width="150" align="center">
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : formatDateTime(row.completionTime) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="transportType" label="运输类型" width="100" align="center">
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : displayValue(row.transportType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="cargoName" label="货物名称" min-width="110" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : displayValue(row.cargoName) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="cargoType" label="货物类型" min-width="110" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : displayValue(row.cargoType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="transportQuantity" label="运输总量" width="110" align="center">
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : displayValue(row.transportQuantity) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="mileage" label="里程 (KM)" width="100" align="center">
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : displayValue(row.mileage) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="batchNo" label="批次号" width="100" align="center" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.manualFlag === 1 ? '—' : displayValue(row.batchNo) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="invoiceNo" label="发票号" min-width="160" align="center" show-overflow-tooltip />
|
||||
<!-- 按费用项目动态分组列头,每组三列:结算金额/未开票费用/本次开票金额 -->
|
||||
<el-table-column v-for="group in feeItemGroups" :key="group.name" :label="group.name" align="center">
|
||||
<el-table-column :label="'结算金额'" width="110" align="center">
|
||||
<template #default="{ row }">{{ formatMoney(row.settlementAmounts[group.name]) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="'未开票费用'" width="110" align="center">
|
||||
<template #default="{ row }">{{ formatMoney(row.beforeRemainAmounts[group.name]) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="'本次开票金额'" width="120" align="center">
|
||||
<template #default="{ row }">{{ formatMoney(row.writeOffAmounts[group.name]) }}</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div v-if="!loading && !rows.length" class="invoice-write-off-table__empty">暂无冲销明细</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import request from '@/axios';
|
||||
|
||||
/**
|
||||
* 发票冲销明细公共表格(开票申请/收票登记/付款申请通用)
|
||||
* 数据源:/blade-transport/invoice-write-off/list?bizType=&bizId=
|
||||
* 行按运单完成时间升序(先完成的运单先冲销),手动添加费用无运输信息显示"—"
|
||||
*/
|
||||
export default {
|
||||
name: 'InvoiceWriteOffTable',
|
||||
props: {
|
||||
// invoice_apply-开票申请 receipt-收票登记 payment_receipt-付款申请生成的收票单
|
||||
bizType: { type: String, required: true },
|
||||
bizId: { type: [String, Number], default: null },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
rows: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
feeItemGroups() {
|
||||
const names = [];
|
||||
this.rows.forEach(row => {
|
||||
if (row.feeItemName && !names.includes(row.feeItemName)) names.push(row.feeItemName);
|
||||
});
|
||||
return names.map(name => ({ name }));
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
bizId: {
|
||||
immediate: true,
|
||||
handler(value) {
|
||||
if (value) this.load();
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
load() {
|
||||
this.loading = true;
|
||||
request({
|
||||
url: '/blade-transport/invoice-write-off/list',
|
||||
method: 'get',
|
||||
params: { bizType: this.bizType, bizId: this.bizId },
|
||||
})
|
||||
.then(res => {
|
||||
const list = res.data.data || [];
|
||||
// 同一运单同一费用项目可能被多张发票分段冲抵(跨发票拆分),按运单+费用项目归并展示
|
||||
const merged = new Map();
|
||||
list.forEach(row => {
|
||||
const key = `${row.waybillId || row.summaryFeeId || ''}|${row.feeItemName}`;
|
||||
if (!merged.has(key)) {
|
||||
merged.set(key, {
|
||||
...row,
|
||||
settlementAmounts: { [row.feeItemName]: row.settlementAmount },
|
||||
beforeRemainAmounts: { [row.feeItemName]: row.beforeRemainAmount },
|
||||
writeOffAmounts: { [row.feeItemName]: row.writeOffAmount },
|
||||
});
|
||||
return;
|
||||
}
|
||||
const target = merged.get(key);
|
||||
target.writeOffAmounts[row.feeItemName] = Number(target.writeOffAmounts[row.feeItemName] || 0) + Number(row.writeOffAmount || 0);
|
||||
// 未开票费用取首段冲抵前余额,发票号追加展示
|
||||
if (!String(target.invoiceNo).includes(row.invoiceNo)) {
|
||||
target.invoiceNo = `${target.invoiceNo},${row.invoiceNo}`;
|
||||
}
|
||||
});
|
||||
this.rows = [...merged.values()];
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
displayValue(value) {
|
||||
return value === null || value === undefined || value === '' ? '-' : value;
|
||||
},
|
||||
formatDateTime(value) {
|
||||
if (!value) return '-';
|
||||
return this.$dayjs(value).format('YYYY-MM-DD HH:mm:ss');
|
||||
},
|
||||
formatMoney(value) {
|
||||
return Number(value || 0).toFixed(2);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.invoice-write-off-table__empty {
|
||||
padding: 24px 0;
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
@@ -77,6 +77,19 @@ export default [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// 发票冲销明细独立页(不挂菜单,供开票申请/收票登记/付款申请页面跳转引用)
|
||||
path: '/payment/invoice-write-off',
|
||||
component: Layout,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: '发票冲销明细',
|
||||
meta: { keepAlive: false, activeMenu: '/payment/invoice-application' },
|
||||
component: loadView(() => import('@/views/payment/invoice-write-off.vue')),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/payment/payment-application/form',
|
||||
component: Layout,
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<basic-container>
|
||||
<section-card title="发票冲销明细">
|
||||
<invoice-write-off-table :biz-type="bizType" :biz-id="bizId" />
|
||||
</section-card>
|
||||
</basic-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import InvoiceWriteOffTable from '@/components/invoice-write-off-table/main.vue';
|
||||
|
||||
/**
|
||||
* 发票冲销明细独立页(不挂菜单,供其他页面 $router 跳转引用)
|
||||
* 用法:$router.push({ path: '/payment/invoice-write-off', query: { bizType: 'invoice_apply', bizId: id } })
|
||||
*/
|
||||
export default {
|
||||
name: 'InvoiceWriteOff',
|
||||
components: { InvoiceWriteOffTable },
|
||||
computed: {
|
||||
bizType() {
|
||||
return String(this.$route.query.bizType || 'invoice_apply');
|
||||
},
|
||||
bizId() {
|
||||
return this.$route.query.bizId || null;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user