收票登记新增所属合同带出承办部门替代手选结算组织 #13

Merged
b2894lxlx merged 6 commits from feature/20261104-bfi-project-web into master 2026-11-05 15:04:43 +08:00
10 changed files with 300 additions and 98 deletions
+1 -1
View File
@@ -118,7 +118,7 @@ export const formalSettlementOption = (settlementType = '') => ({
emptyBtnText: '重置', emptyBtnText: '重置',
searchShow: true, searchShow: true,
searchIcon: true, searchIcon: true,
searchLabelWidth: 88, searchLabelWidth: 100,
// 查询/重置紧跟首行 4 个条件(4×5 + 菜单 4 = 24),不再独占下一整行 // 查询/重置紧跟首行 4 个条件(4×5 + 菜单 4 = 24),不再独占下一整行
searchMenuSpan: 4, searchMenuSpan: 4,
searchIndex: 4, searchIndex: 4,
+33 -1
View File
@@ -129,7 +129,39 @@ export default [
name: '新增编辑结算单', name: '新增编辑结算单',
meta: { meta: {
keepAlive: false, keepAlive: false,
// 付款/收款结算单共用表单页,具体高亮菜单由页面按 settlementType 回写 // 付款结算单表单入口,高亮付款结算单菜单
activeMenu: '/settlement/payment-settlement',
},
component: loadView(() => import('@/views/settlement/formal-settlement-form.vue')),
},
],
},
{
// 收款结算单表单入口:与付款结算单共用表单组件,仅高亮菜单不同
path: '/settlement/receipt-settlement/form',
component: Layout,
children: [
{
path: '',
name: '新增编辑收款结算单',
meta: {
keepAlive: false,
activeMenu: '/settlement/receipt-settlement',
},
component: loadView(() => import('@/views/settlement/formal-settlement-form.vue')),
},
],
},
{
// 付款结算单表单入口:与 settlementListPath('payable') + '/form' 对应
path: '/settlement/payment-settlement/form',
component: Layout,
children: [
{
path: '',
name: '新增编辑付款结算单',
meta: {
keepAlive: false,
activeMenu: '/settlement/payment-settlement', activeMenu: '/settlement/payment-settlement',
}, },
component: loadView(() => import('@/views/settlement/formal-settlement-form.vue')), component: loadView(() => import('@/views/settlement/formal-settlement-form.vue')),
@@ -494,6 +494,9 @@ import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.v
import { getMkPublicDetail } from '@/api/mk-process'; import { getMkPublicDetail } from '@/api/mk-process';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval'; import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
// 提交成功后带标记返回,列表页(keep-alive)据此重新拉取
const invoiceApplicationListRefreshKey = 'invoice-application-list-refresh';
let localId = 0; let localId = 0;
const emptyLine = () => ({ const emptyLine = () => ({
localId: ++localId, localId: ++localId,
@@ -1227,6 +1230,7 @@ export default {
mkEnabled: await loadMkEnabled().catch(() => false), mkEnabled: await loadMkEnabled().catch(() => false),
}); });
this.$message.success('提交成功'); this.$message.success('提交成功');
sessionStorage.setItem(invoiceApplicationListRefreshKey, '1');
this.goBack(); this.goBack();
}, },
async syncReferenceData() { async syncReferenceData() {
+35 -3
View File
@@ -250,6 +250,11 @@ import organizationSearch from '@/mixins/organization-search';
import { getMKApprovalUrl } from '@/api/system/business-process'; import { getMKApprovalUrl } from '@/api/system/business-process';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval'; import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
import { kingdeeStatusType } from '@/utils/kingdee'; import { kingdeeStatusType } from '@/utils/kingdee';
import { settlementListPath } from '@/utils/settlement-menu';
// 表单提交成功后带标记返回,keep-alive 缓存的列表页据此重新拉取
const invoiceApplicationListRefreshKey = 'invoice-application-list-refresh';
const invoiceApplicationListRoute = '/payment/invoice-application';
const emptyQuery = () => ({ const emptyQuery = () => ({
applicationNo: '', applicationNo: '',
@@ -308,7 +313,28 @@ export default {
this.mkEnabled = false; this.mkEnabled = false;
}); });
}, },
activated() {
this.consumeListRefreshFlag();
},
watch: {
$route(to, from) {
if (
to.path === invoiceApplicationListRoute &&
from?.path?.includes('/invoice-application/form')
) {
this.consumeListRefreshFlag();
}
},
},
methods: { methods: {
/** 表单提交成功后带标记返回时,重新拉取列表 */
consumeListRefreshFlag() {
if (!sessionStorage.getItem(invoiceApplicationListRefreshKey)) {
return;
}
sessionStorage.removeItem(invoiceApplicationListRefreshKey);
this.loadTable();
},
hasPermission(code) { hasPermission(code) {
return this.permission?.[code] !== false; return this.permission?.[code] !== false;
}, },
@@ -372,12 +398,18 @@ export default {
item => String(item.formalSettlementNo || '').trim() === normalizedNo item => String(item.formalSettlementNo || '').trim() === normalizedNo
); );
if (!row?.id) { if (!row?.id) {
this.$message.warning('未找到对应的付款结算单'); this.$message.warning('未找到对应的结算单');
return; return;
} }
// 开票申请关联的多为收款结算单,按单据类型路由到对应表单入口,避免误落付款结算单
this.$router.push({ this.$router.push({
path: '/settlement/formal-settlement/form', path: settlementListPath(row.settlementType) + '/form',
query: { mode: 'view', id: row.id, name: '查看正式结算' }, query: {
mode: 'view',
id: row.id,
settlementType: row.settlementType,
name: '查看正式结算',
},
}); });
} catch (error) { } catch (error) {
this.$message.error('正式结算单详情加载失败'); this.$message.error('正式结算单详情加载失败');
+114 -69
View File
@@ -100,18 +100,28 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="6">
<el-form-item label="结算组织" prop="deptId"> <el-form-item label="所属合同" prop="contractNo">
<el-cascader <el-tooltip
v-if="!readonly" :content="form.contractName"
:model-value="deptCascaderValue" :disabled="!form.contractName"
:options="deptTreeOptions" placement="top"
:props="deptCascaderProps" :show-after="200"
placeholder="请选择结算组织(合同承办部门)" >
filterable <div class="receipt-form-page__overflow-trigger">
clearable <el-input :model-value="form.contractNo" readonly placeholder="请选择承运商合同">
@change="handleDeptChange" <template v-if="!readonly" #append>
/> <el-tooltip content="选择承运商合同" placement="top">
<el-input v-else :model-value="form.deptName" disabled /> <el-button :icon="Search" @click="openContractDialog" />
</el-tooltip>
</template>
</el-input>
</div>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="承办部门">
<el-input :model-value="form.deptName" disabled placeholder="从所属合同带出" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -214,6 +224,48 @@
:query-api="apiQueryInvoicePool" :query-api="apiQueryInvoicePool"
@confirm="handleInvoicePicked" @confirm="handleInvoicePicked"
/> />
<el-dialog v-model="contractDialog.visible" title="选择承运商合同" width="920px" append-to-body>
<el-form :model="contractDialog.query" label-position="right" label-width="auto" inline @submit.prevent>
<el-form-item label="合同编号">
<el-input
v-model="contractDialog.query.contractNo"
clearable
placeholder="请输入"
@keyup.enter="searchContracts"
/>
</el-form-item>
<el-form-item label="合同名称">
<el-input
v-model="contractDialog.query.contractName"
clearable
placeholder="请输入"
@keyup.enter="searchContracts"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Search" @click="searchContracts">查询</el-button>
<el-button @click="resetContractQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="contractDialog.loading" :data="contractDialog.rows" border>
<el-table-column prop="contractNo" label="合同编号" min-width="180" show-overflow-tooltip />
<el-table-column prop="contractName" label="合同名称" min-width="200" show-overflow-tooltip />
<el-table-column prop="organizationName" label="承办部门" min-width="160" show-overflow-tooltip />
<el-table-column label="操作" width="80" align="center">
<template #default="{ row }">
<el-button type="primary" link @click="pickContract(row)">选择</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:current-page="contractDialog.page.current"
v-model:page-size="contractDialog.page.size"
:total="contractDialog.page.total"
layout="total, prev, pager, next"
@current-change="loadContracts"
/>
</el-dialog>
</basic-container> </basic-container>
</template> </template>
@@ -221,7 +273,7 @@
import { Search } from '@element-plus/icons-vue'; import { Search } from '@element-plus/icons-vue';
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import * as api from '@/api/payment/invoiceReceipt'; import * as api from '@/api/payment/invoiceReceipt';
import { getDeptTree } from '@/api/system/dept'; import { getList as getContractList } from '@/api/business/contract-manage';
import KingdeeInvoicePoolDialog from '@/components/kingdee-invoice-pool-dialog/main.vue'; import KingdeeInvoicePoolDialog from '@/components/kingdee-invoice-pool-dialog/main.vue';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue'; import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { getMkPublicDetail } from '@/api/mk-process'; import { getMkPublicDetail } from '@/api/mk-process';
@@ -247,6 +299,8 @@ const emptyForm = () => ({
customerEmails: [], customerEmails: [],
departmentEmails: [], departmentEmails: [],
projectName: '', projectName: '',
contractNo: '',
contractName: '',
deptId: null, deptId: null,
deptName: '', deptName: '',
payerName: '', payerName: '',
@@ -269,16 +323,19 @@ export default {
customerEmailOptions: [], customerEmailOptions: [],
departmentEmailOptions: [], departmentEmailOptions: [],
invoiceItems: [], invoiceItems: [],
deptTreeOptions: [], contractDialog: {
deptMap: new Map(), visible: false,
// 结算组织=合同承办部门:部门树级联单选(取末级 id),后端沿部门树上溯平台公司取金蝶组织 loading: false,
deptCascaderProps: { checkStrictly: true, emitPath: true }, rows: [],
page: { current: 1, size: 10, total: 0 },
query: { contractNo: '', contractName: '' },
},
invoiceDialog: { invoiceDialog: {
visible: false, visible: false,
}, },
rules: { rules: {
invoiceNo: [{ required: true, validator: this.validateInvoice, trigger: 'change' }], invoiceNo: [{ required: true, validator: this.validateInvoice, trigger: 'change' }],
deptId: [{ required: true, validator: this.validateDept, trigger: 'change' }], contractNo: [{ required: true, validator: this.validateContract, trigger: 'change' }],
customerEmails: [{ validator: this.validateEmails, trigger: 'change' }], customerEmails: [{ validator: this.validateEmails, trigger: 'change' }],
departmentEmails: [{ validator: this.validateEmails, trigger: 'change' }], departmentEmails: [{ validator: this.validateEmails, trigger: 'change' }],
}, },
@@ -299,12 +356,6 @@ export default {
const code = this.recordId ? 'invoice_receipt_edit' : 'invoice_receipt_add'; const code = this.recordId ? 'invoice_receipt_edit' : 'invoice_receipt_add';
return this.hasPermission(code); return this.hasPermission(code);
}, },
deptCascaderValue() {
if (this.form.deptId === null || this.form.deptId === undefined || this.form.deptId === '') {
return [];
}
return [String(this.form.deptId)];
},
}, },
created() { created() {
this.initialize(); this.initialize();
@@ -339,7 +390,6 @@ export default {
.filter(Boolean); .filter(Boolean);
}, },
async initialize() { async initialize() {
this.loadDepartments();
if (this.isPublicViewPage) { if (this.isPublicViewPage) {
await this.loadPublicDetail(); await this.loadPublicDetail();
return; return;
@@ -380,9 +430,9 @@ export default {
} }
callback(); callback();
}, },
validateDept(rule, value, callback) { validateContract(rule, value, callback) {
if (this.form.deptId === null || this.form.deptId === undefined || this.form.deptId === '') { if (!this.form.contractNo) {
callback(new Error('请选择结算组织')); callback(new Error('请选择所属合同'));
return; return;
} }
callback(); callback();
@@ -454,47 +504,43 @@ export default {
this.invoiceItems = []; this.invoiceItems = [];
} }
}, },
loadDepartments() { // 所属合同=承运商合同:选择后带出承办部门(结算组织=承办部门对应平台公司金蝶编码,后端派生)
// 结算组织取租户部门树(过滤外部组织),选中取末级部门 id openContractDialog() {
getDeptTree(this.userInfo?.tenantId) this.contractDialog.visible = true;
.then(response => { this.searchContracts();
const rows = this.excludeExternalOrganization(this.unwrapData(response) || []);
this.deptTreeOptions = this.toDeptCascaderOptions(rows);
this.deptMap = new Map();
this.flattenDepartments(rows).forEach(item =>
this.deptMap.set(String(item.id), item.title || item.deptName || item.name)
);
})
.catch(() => {});
}, },
excludeExternalOrganization(list = []) { searchContracts() {
return list.reduce((result, item) => { this.contractDialog.page.current = 1;
const deptName = item.title || item.deptName || item.name; this.loadContracts();
if (String(deptName || '').trim() === '外部组织') return result; },
result.push({ resetContractQuery() {
...item, this.contractDialog.query = { contractNo: '', contractName: '' };
children: item.children?.length this.searchContracts();
? this.excludeExternalOrganization(item.children) },
: item.children, async loadContracts() {
this.contractDialog.loading = true;
try {
const res = await getContractList(this.contractDialog.page.current, this.contractDialog.page.size, {
...this.contractDialog.query,
contractCategory: '承运商合同',
approvalStatuses: 'approved,change_approved',
}); });
return result; const data = this.unwrapData(res) || {};
}, []); this.contractDialog.rows = data.records || [];
this.contractDialog.page.total = Number(data.total || 0);
} finally {
this.contractDialog.loading = false;
}
}, },
toDeptCascaderOptions(list = []) { pickContract(row) {
return list.map(item => ({ if (!row) return;
label: item.title || item.deptName || item.name, Object.assign(this.form, {
value: item.id == null || item.id === '' ? '' : String(item.id), contractNo: row.contractNo,
children: item.children?.length ? this.toDeptCascaderOptions(item.children) : undefined, contractName: row.contractName,
})); deptName: row.organizationName,
}, });
flattenDepartments(rows) { this.contractDialog.visible = false;
return (rows || []).flatMap(item => [item, ...this.flattenDepartments(item.children || [])]); this.$refs.formRef?.validateField('contractNo').catch(() => {});
},
handleDeptChange(value) {
const deptId = Array.isArray(value) ? value.at(-1) : value;
this.form.deptId = deptId || null;
this.form.deptName = deptId ? this.deptMap.get(String(deptId)) || '' : '';
this.$refs.formRef?.validateField('deptId').catch(() => {});
}, },
openSettlementDetail(row) { openSettlementDetail(row) {
const id = row.formalSettlementId || row.settlementId || row.id; const id = row.formalSettlementId || row.settlementId || row.id;
@@ -527,9 +573,8 @@ export default {
departmentEmails: this.form.departmentEmails.join(';'), departmentEmails: this.form.departmentEmails.join(';'),
attachmentsJson: JSON.stringify(this.form.attachments || []), attachmentsJson: JSON.stringify(this.form.attachments || []),
remark: this.form.remark, remark: this.form.remark,
// 结算组织=页面手选部门(先票后款不挂结算单,认领关系由结算单侧维护,不再传 settlements) // 所属合同仅传编号,合同名称/承办部门由后端按编号带出(结算组织=合同承办部门)
deptId: this.form.deptId, contractNo: this.form.contractNo,
deptName: this.form.deptName,
}; };
}, },
async saveDraft() { async saveDraft() {
+36 -18
View File
@@ -1296,9 +1296,11 @@ export default {
this.form = { this.form = {
...emptyForm(), ...emptyForm(),
...data, ...data,
// 后端可能返回 -1 占位预付 id,统一归一为 null,防止点击结算单号误跳预付
preSettlementId: this.isValidReferenceId(data.preSettlementId) ? data.preSettlementId : null,
preSettlementIds: data.preSettlementIds?.length preSettlementIds: data.preSettlementIds?.length
? data.preSettlementIds ? data.preSettlementIds
: data.preSettlementId : this.isValidReferenceId(data.preSettlementId)
? [data.preSettlementId] ? [data.preSettlementId]
: [], : [],
attachments: this.parse(data.attachmentsJson), attachments: this.parse(data.attachmentsJson),
@@ -1344,9 +1346,13 @@ export default {
this.form = { this.form = {
...emptyForm(), ...emptyForm(),
...data, ...data,
// 后端可能返回 -1 占位预付 id,统一归一为 null,防止点击结算单号误跳预付
preSettlementId: this.isValidReferenceId(data.preSettlementId)
? data.preSettlementId
: null,
preSettlementIds: data.preSettlementIds?.length preSettlementIds: data.preSettlementIds?.length
? data.preSettlementIds ? data.preSettlementIds
: data.preSettlementId : this.isValidReferenceId(data.preSettlementId)
? [data.preSettlementId] ? [data.preSettlementId]
: [], : [],
attachments: this.parse(data.attachmentsJson), attachments: this.parse(data.attachmentsJson),
@@ -1587,17 +1593,22 @@ export default {
}); });
}, },
clearFormalReferenceWhenPreOnly() { clearFormalReferenceWhenPreOnly() {
// 纯预付引用才收敛为预付;-1 占位 id 不得充当预付关联
const progressAdvance = this.form.paymentType === 'progress_advance'; const progressAdvance = this.form.paymentType === 'progress_advance';
const onlyPre = const onlyPre =
progressAdvance || progressAdvance ||
(this.referenceRows.length > 0 && (this.referenceRows.length > 0 &&
this.referenceRows.every(item => item.referenceType === 'pre')); this.referenceRows.every(item => item.referenceType === 'pre'));
if (!onlyPre) return; if (!onlyPre) return;
if (!this.form.preSettlementId) { if (!this.isValidReferenceId(this.form.preSettlementId)) {
const preId = const preId =
this.referenceRows.find(item => item.referenceType === 'pre')?.id || this.referenceRows.find(
(progressAdvance ? this.form.settlementId : null); item => item.referenceType === 'pre' && this.isValidReferenceId(item.id)
if (preId) { )?.id ||
(progressAdvance && this.isValidReferenceId(this.form.settlementId)
? this.form.settlementId
: null);
if (this.isValidReferenceId(preId)) {
this.form.preSettlementId = preId; this.form.preSettlementId = preId;
this.form.preSettlementIds = [preId]; this.form.preSettlementIds = [preId];
} }
@@ -1608,13 +1619,16 @@ export default {
}, },
restoreReferenceRows(data, fallbackRow) { restoreReferenceRows(data, fallbackRow) {
const relations = Array.isArray(data?.settlements) ? data.settlements : []; const relations = Array.isArray(data?.settlements) ? data.settlements : [];
// 行级预付/正式类型以过滤占位 id 后的关联为准,决定点击结算单号的跳转目标
const rows = relations const rows = relations
.map(item => { .map(item => {
const isPre = Boolean(item.preSettlementId || item.preSettlementNo); // 后端用 -1 占位空 id,必须先过滤再判预付,否则正式结算行会被误标为预付
const preId = this.isValidReferenceId(item.preSettlementId) ? item.preSettlementId : null;
const isPre = Boolean(preId || item.preSettlementNo);
const settlementNo = item.preSettlementNo || item.formalSettlementNo || ''; const settlementNo = item.preSettlementNo || item.formalSettlementNo || '';
if (!settlementNo) return null; if (!settlementNo) return null;
return { return {
id: isPre ? item.preSettlementId || item.formalSettlementId : item.formalSettlementId, id: isPre ? preId || item.formalSettlementId : item.formalSettlementId,
settlementNo, settlementNo,
referenceType: isPre ? 'pre' : 'formal', referenceType: isPre ? 'pre' : 'formal',
settlementAmount: Number(Number(item.settlementAmount || 0).toFixed(2)), settlementAmount: Number(Number(item.settlementAmount || 0).toFixed(2)),
@@ -1642,9 +1656,10 @@ export default {
}, },
createReferenceRow(row) { createReferenceRow(row) {
const settlementAmount = Number(row.settlementAmount || 0); const settlementAmount = Number(row.settlementAmount || 0);
// 后端以 -1 占位空预付 id,必须先校验否则正式结算行会被误判为预付
const isPre = Boolean( const isPre = Boolean(
row.preSettlementNo || row.preSettlementNo ||
row.preSettlementId || this.isValidReferenceId(row.preSettlementId) ||
row.referenceType === 'pre' || row.referenceType === 'pre' ||
row.paymentType === 'progress_advance' row.paymentType === 'progress_advance'
); );
@@ -2770,23 +2785,26 @@ export default {
}, },
async openSettlementDetail(row = {}) { async openSettlementDetail(row = {}) {
const settlementNo = String(row.settlementNo || '').trim(); const settlementNo = String(row.settlementNo || '').trim();
// 行上 referenceType 优先;发票行等只带单号的,按单号回查引用行;都缺省才回落表单级推断
const matchedReference = this.referenceRows.find(
item => String(item.settlementNo || '').trim() === settlementNo
);
const referenceType = row.referenceType || matchedReference?.referenceType;
const isPre = const isPre =
row.referenceType === 'pre' || referenceType === 'pre' ||
this.form.paymentType === 'progress_advance' || (!referenceType &&
Boolean(this.form.preSettlementId || this.form.preSettlementNo); (this.form.paymentType === 'progress_advance' ||
Boolean(
this.isValidReferenceId(this.form.preSettlementId) || this.form.preSettlementNo
)));
let id = let id =
row.id || row.id ||
row.preSettlementId || row.preSettlementId ||
row.settlementId || row.settlementId ||
matchedReference?.id ||
(isPre (isPre
? this.form.preSettlementId || this.form.preSettlementIds?.[0] ? this.form.preSettlementId || this.form.preSettlementIds?.[0]
: this.form.settlementId || this.form.settlementIds?.[0]); : this.form.settlementId || this.form.settlementIds?.[0]);
if (!id && settlementNo) {
const matched = this.referenceRows.find(
item => String(item.settlementNo || '').trim() === settlementNo
);
id = matched?.id;
}
if (!id && settlementNo) { if (!id && settlementNo) {
try { try {
const listApi = isPre ? preApi.getList : formalApi.getList; const listApi = isPre ? preApi.getList : formalApi.getList;
+4 -2
View File
@@ -436,8 +436,9 @@ export default {
(handlers[type] || (() => {}))(); (handlers[type] || (() => {}))();
}, },
openCreate() { openCreate() {
// 按列表锁定的结算类型路由到对应表单入口,保证菜单高亮与关闭回落列表正确
this.$router.push({ this.$router.push({
path: '/settlement/formal-settlement/form', path: settlementListPath(this.activeSettlementType) + '/form',
query: { query: {
mode: 'add', mode: 'add',
name: `新增${this.billLabel}`, name: `新增${this.billLabel}`,
@@ -448,8 +449,9 @@ export default {
}, },
openEdit(row) { openEdit(row) {
const settlementType = row.settlementType || this.activeSettlementType; const settlementType = row.settlementType || this.activeSettlementType;
// 行类型可能与列表锁定类型不同,按行类型路由
this.$router.push({ this.$router.push({
path: '/settlement/formal-settlement/form', path: settlementListPath(settlementType) + '/form',
query: { query: {
mode: 'edit', mode: 'edit',
id: row.id, id: row.id,
+31 -1
View File
@@ -1,7 +1,7 @@
<template> <template>
<basic-container class="pre-settlement-page"> <basic-container class="pre-settlement-page">
<section v-show="searchVisible" class="pre-settlement-page__search"> <section v-show="searchVisible" class="pre-settlement-page__search">
<el-form :model="query" label-position="right" label-width="88px" @submit.prevent> <el-form :model="query" label-position="right" label-width="100px" @submit.prevent>
<div class="pre-settlement-page__search-grid"> <div class="pre-settlement-page__search-grid">
<template v-for="field in visibleSearchFields" :key="field.prop"> <template v-for="field in visibleSearchFields" :key="field.prop">
<el-form-item :label="field.label"> <el-form-item :label="field.label">
@@ -108,6 +108,7 @@
:data="rows" :data="rows"
:size="tableSize" :size="tableSize"
border border
height="100%"
class="pre-settlement-page__table" class="pre-settlement-page__table"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
> >
@@ -768,8 +769,27 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// 页面固定在视口内:搜索区/工具栏/分页固定,仅表格内部滚动(与付款结算单 avue 高度自适应对齐)
// 100vh - 50(top) - 40(tags) - 24(avue-view padding)
$pre_page_height: calc(100vh - 114px);
.pre-settlement-page { .pre-settlement-page {
height: $pre_page_height;
:deep(.basic-container__card) {
height: 100%;
overflow: hidden;
}
:deep(.el-card__body) {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
&__search { &__search {
flex-shrink: 0;
padding: 12px 12px 4px; padding: 12px 12px 4px;
background: #fff; background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
@@ -801,6 +821,10 @@ export default {
} }
&__table-panel { &__table-panel {
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
margin-top: 8px; margin-top: 8px;
} }
@@ -823,8 +847,14 @@ export default {
justify-content: center; justify-content: center;
} }
&__table {
flex: 1;
min-height: 0;
}
&__pagination { &__pagination {
display: flex; display: flex;
flex-shrink: 0;
justify-content: flex-end; justify-content: flex-end;
padding: 12px; padding: 12px;
} }
@@ -507,7 +507,13 @@
</template> </template>
</el-dialog> </el-dialog>
<el-dialog v-model="transferDialog.visible" title="批量转结算" width="86%" append-to-body> <el-dialog
v-model="transferDialog.visible"
title="批量转结算"
width="72%"
append-to-body
align-center
>
<div class="settlement-detail-page__transfer-form"> <div class="settlement-detail-page__transfer-form">
<el-form :model="transferQuery" inline label-position="right" label-width="120px"> <el-form :model="transferQuery" inline label-position="right" label-width="120px">
<el-form-item label="转结算类型"> <el-form-item label="转结算类型">
@@ -548,9 +554,10 @@
:data="transferRows" :data="transferRows"
row-key="id" row-key="id"
border border
max-height="50vh"
@selection-change="transferSelectionChange" @selection-change="transferSelectionChange"
> >
<el-table-column type="selection" width="52" align="center" reserve-selection /> <el-table-column type="selection" width="52" align="center" reserve-selection fixed />
<el-table-column <el-table-column
type="index" type="index"
label="序号" label="序号"
@@ -1060,6 +1067,7 @@ import { formatContractOptionLabel } from '@/utils/contract';
import { isTierUnitPrice, isUnitPriceAdjustable } from '@/utils/settlement-adjust-rule'; import { isTierUnitPrice, isUnitPriceAdjustable } from '@/utils/settlement-adjust-rule';
import { downloadXls } from '@/utils/util'; import { downloadXls } from '@/utils/util';
import { createSettlementTransfer } from '@/utils/settlement-transfer'; import { createSettlementTransfer } from '@/utils/settlement-transfer';
import { settlementListPath } from '@/utils/settlement-menu';
import { import {
contractApprovalStatusOptions, contractApprovalStatusOptions,
contractCategoryOptions, contractCategoryOptions,
@@ -2659,10 +2667,11 @@ export default {
}); });
const isPreSettlement = settlementBillType === 'pre'; const isPreSettlement = settlementBillType === 'pre';
this.transferDialog.visible = false; this.transferDialog.visible = false;
// 按结算类型路由到对应表单入口,保证收款/付款菜单各自高亮正确
await this.$router.push({ await this.$router.push({
path: isPreSettlement path: isPreSettlement
? '/settlement/pre-settlement/form' ? '/settlement/pre-settlement/form'
: '/settlement/formal-settlement/form', : settlementListPath(this.settlementType) + '/form',
query: { query: {
mode: 'add', mode: 'add',
transferToken, transferToken,
@@ -69,6 +69,8 @@
:data="rows" :data="rows"
:size="tableSize" :size="tableSize"
border border
height="100%"
class="settlement-adjustment-page__table"
@selection-change="selection = $event" @selection-change="selection = $event"
> >
<el-table-column type="selection" width="52" fixed="left" align="center" /><el-table-column <el-table-column type="selection" width="52" fixed="left" align="center" /><el-table-column
@@ -389,8 +391,27 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
// 页面固定在视口内:搜索区/工具栏/分页固定,仅表格内部滚动(与付款结算单对齐)
// 100vh - 50(top) - 40(tags) - 24(avue-view padding)
$adjustment_page_height: calc(100vh - 114px);
.settlement-adjustment-page { .settlement-adjustment-page {
height: $adjustment_page_height;
:deep(.basic-container__card) {
height: 100%;
overflow: hidden;
}
:deep(.el-card__body) {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
&__search { &__search {
flex-shrink: 0;
padding: 12px 12px 4px; padding: 12px 12px 4px;
background: #fff; background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
@@ -417,6 +438,10 @@ export default {
margin-bottom: 8px; margin-bottom: 8px;
} }
&__table-panel { &__table-panel {
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
margin-top: 8px; margin-top: 8px;
} }
&__toolbar { &__toolbar {
@@ -431,8 +456,13 @@ export default {
justify-content: center; justify-content: center;
gap: 8px; gap: 8px;
} }
&__table {
flex: 1;
min-height: 0;
}
&__pagination { &__pagination {
display: flex; display: flex;
flex-shrink: 0;
justify-content: flex-end; justify-content: flex-end;
padding: 12px; padding: 12px;
} }