Merge pull request '修复付款申请 + 收款/付款结算单搜索栏' (#16) from fix/20261110-修复结算单页面-web into master
Reviewed-on: #16
This commit was merged in pull request #16.
This commit is contained in:
@@ -1,14 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* 付款申请列表(avue-crud)配置
|
* 付款申请列表(avue-crud)配置
|
||||||
* ------------------------------------------------------------------
|
* ------------------------------------------------------------------
|
||||||
* 列表页与其它模块统一使用 avue-crud,头部 4 个按钮(刷新 / 列显隐 / 搜索显隐 /
|
* 列表页与其它模块统一使用 avue-crud,头部按钮(刷新 / 列显隐 / 表格卡片切换)
|
||||||
* 表格卡片切换)由 avue-crud 自带,不做二次封装。
|
* 由 avue-crud 自带,不做二次封装。
|
||||||
*
|
*
|
||||||
* 搜索项与表格列 label 不一致的(如表格列「收款方」/ 搜索项「客户名称」),
|
* 搜索栏与应收/应付明细等页面统一为页面级手写搜索区(见 payment-application.vue),
|
||||||
* 单独定义一个 hide 的搜索列,并用 searchProp 映射到后端字段。
|
* 此处只保留表格列配置。
|
||||||
*
|
|
||||||
* ⚠️ avue 的 searchOrder 为降序排序,值越大越靠前(见 header-search2.js:
|
|
||||||
* `list.sort((a, b) => (b.searchOrder || 0) - (a.searchOrder || 0))`)。
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const textFormatter = (row, value) =>
|
const textFormatter = (row, value) =>
|
||||||
@@ -16,46 +13,10 @@ const textFormatter = (row, value) =>
|
|||||||
|
|
||||||
const moneyFormatter = (row, value) => Number(value || 0).toFixed(2);
|
const moneyFormatter = (row, value) => Number(value || 0).toFixed(2);
|
||||||
|
|
||||||
// 仅用于搜索、不在表格中出现的列
|
export const paymentApplicationOption = () => ({
|
||||||
const searchOnlyColumn = ({ label, prop, searchOrder, searchProp, dicData }) => {
|
|
||||||
const column = {
|
|
||||||
label,
|
|
||||||
prop,
|
|
||||||
search: true,
|
|
||||||
searchOrder,
|
|
||||||
searchPlaceholder: '请输入',
|
|
||||||
hide: true,
|
|
||||||
showColumn: false,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
};
|
|
||||||
if (searchProp) column.searchProp = searchProp;
|
|
||||||
if (dicData) {
|
|
||||||
column.type = 'select';
|
|
||||||
column.searchPlaceholder = '请选择';
|
|
||||||
column.dicData = dicData;
|
|
||||||
}
|
|
||||||
return column;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const paymentApplicationOption = ({
|
|
||||||
paymentTypeOptions = [],
|
|
||||||
approvalStatusOptions = [],
|
|
||||||
kingdeeStatusOptions = [],
|
|
||||||
} = {}) => ({
|
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchBtnText: '查询',
|
|
||||||
emptyBtnText: '重置',
|
|
||||||
searchShow: true,
|
|
||||||
searchIcon: true,
|
|
||||||
searchLabelWidth: 88,
|
|
||||||
// 查询/重置紧跟首行 4 个条件(4×5 + 菜单 4 = 24),不再独占下一整行
|
|
||||||
searchMenuSpan: 4,
|
|
||||||
searchIndex: 4,
|
|
||||||
searchMenuPosition: 'right',
|
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
@@ -73,84 +34,11 @@ export const paymentApplicationOption = ({
|
|||||||
menuFixed: 'right',
|
menuFixed: 'right',
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
// ---------- 搜索项(前 4 项默认展示,其余折叠;searchOrder 越大越靠前) ----------
|
|
||||||
{
|
|
||||||
label: '单据号',
|
|
||||||
prop: 'paymentNo',
|
|
||||||
slot: true,
|
|
||||||
search: true,
|
|
||||||
searchSpan: 5,
|
|
||||||
searchOrder: 9,
|
|
||||||
searchPlaceholder: '请输入',
|
|
||||||
minWidth: 150,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '日期',
|
|
||||||
prop: 'applyDateRange',
|
|
||||||
type: 'daterange',
|
|
||||||
searchType: 'daterange',
|
|
||||||
search: true,
|
|
||||||
searchSpan: 5,
|
|
||||||
searchOrder: 8,
|
|
||||||
hide: true,
|
|
||||||
showColumn: false,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...searchOnlyColumn({
|
|
||||||
label: '客户名称',
|
|
||||||
prop: 'payeeNameSearch',
|
|
||||||
searchOrder: 7,
|
|
||||||
searchProp: 'payeeName',
|
|
||||||
}),
|
|
||||||
searchSpan: 5,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
...searchOnlyColumn({
|
|
||||||
label: '项目名称',
|
|
||||||
prop: 'projectNameSearch',
|
|
||||||
searchOrder: 6,
|
|
||||||
searchProp: 'projectName',
|
|
||||||
}),
|
|
||||||
searchSpan: 5,
|
|
||||||
},
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '关联结算单',
|
|
||||||
prop: 'settlementNo',
|
|
||||||
searchOrder: 4,
|
|
||||||
}),
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '付款类型',
|
|
||||||
prop: 'paymentType',
|
|
||||||
searchOrder: 3,
|
|
||||||
dicData: paymentTypeOptions,
|
|
||||||
}),
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '审核状态',
|
|
||||||
prop: 'approvalStatus',
|
|
||||||
searchOrder: 2,
|
|
||||||
dicData: approvalStatusOptions,
|
|
||||||
}),
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '金蝶单据状态',
|
|
||||||
prop: 'kingdeeStatus',
|
|
||||||
searchOrder: 1,
|
|
||||||
dicData: kingdeeStatusOptions,
|
|
||||||
}),
|
|
||||||
// ---------- 表格列 ----------
|
// ---------- 表格列 ----------
|
||||||
|
{ label: '单据号', prop: 'paymentNo', slot: true, minWidth: 150 },
|
||||||
{ label: '付款类型', prop: 'paymentTypeName', minWidth: 110, formatter: textFormatter },
|
{ label: '付款类型', prop: 'paymentTypeName', minWidth: 110, formatter: textFormatter },
|
||||||
{ label: '所属项目', prop: 'projectName', minWidth: 140, formatter: textFormatter },
|
{ label: '所属项目', prop: 'projectName', minWidth: 140, formatter: textFormatter },
|
||||||
{
|
{ label: '所属组织', prop: 'deptName', minWidth: 120, formatter: textFormatter },
|
||||||
label: '所属组织',
|
|
||||||
prop: 'deptName',
|
|
||||||
search: true,
|
|
||||||
searchOrder: 5,
|
|
||||||
searchslot: true,
|
|
||||||
minWidth: 120,
|
|
||||||
formatter: textFormatter,
|
|
||||||
},
|
|
||||||
{ label: '合同编号', prop: 'contractNo', minWidth: 130, formatter: textFormatter },
|
{ label: '合同编号', prop: 'contractNo', minWidth: 130, formatter: textFormatter },
|
||||||
{ label: '合同名称', prop: 'contractName', minWidth: 140, formatter: textFormatter },
|
{ label: '合同名称', prop: 'contractName', minWidth: 140, formatter: textFormatter },
|
||||||
{ label: '付款方', prop: 'payerName', minWidth: 130, formatter: textFormatter },
|
{ label: '付款方', prop: 'payerName', minWidth: 130, formatter: textFormatter },
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
/**
|
/**
|
||||||
* 正式结算单列表(avue-crud)配置
|
* 正式结算单列表(avue-crud)配置
|
||||||
* ------------------------------------------------------------------
|
* ------------------------------------------------------------------
|
||||||
* 列表页与其它模块统一使用 avue-crud,头部 4 个按钮(刷新 / 列显隐 / 搜索显隐 /
|
* 列表页与其它模块统一使用 avue-crud,头部按钮(刷新 / 列显隐 / 显示方式)
|
||||||
* 显示方式)由 avue-crud 自带,不做二次封装。
|
* 由 avue-crud 自带,不做二次封装。
|
||||||
|
*
|
||||||
|
* 搜索栏与应收/应付明细页统一为页面级手写搜索区(见 formal-settlement.vue),
|
||||||
|
* 此处只保留表格列配置。
|
||||||
*
|
*
|
||||||
* 表格列复用 formalSettlementTable.js 的 formalSettlementTableColumns(与弹窗内
|
* 表格列复用 formalSettlementTable.js 的 formalSettlementTableColumns(与弹窗内
|
||||||
* 明细表共用同一份列定义),此处只补充 avue 需要的展示/搜索属性,避免两处维护。
|
* 明细表共用同一份列定义),此处只补充 avue 需要的展示属性,避免两处维护。
|
||||||
*
|
|
||||||
* ⚠️ searchOrder 为降序排序,值越大越靠前。
|
|
||||||
* ⚠️ 仅用于搜索的列必须 hide + showColumn: false,否则会混进「列显隐」抽屉。
|
|
||||||
* ⚠️ column 数组顺序 = 表格列顺序,搜索专用列统一放在数组最前面。
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { formatSealTypes } from '@/utils/settlement-seal';
|
import { formatSealTypes } from '@/utils/settlement-seal';
|
||||||
import {
|
import {
|
||||||
approvalStatusOptions,
|
|
||||||
invoiceStatusOptions,
|
|
||||||
kingdeeSyncStatusOptions,
|
kingdeeSyncStatusOptions,
|
||||||
kingdeeWriteOffStatusOptions,
|
kingdeeWriteOffStatusOptions,
|
||||||
paymentStatusOptions,
|
paymentStatusOptions,
|
||||||
@@ -34,47 +31,9 @@ const moneyFormatter = (row, value) =>
|
|||||||
const pickLabel = (options, value) =>
|
const pickLabel = (options, value) =>
|
||||||
options.find(item => item.value === value)?.label || value || '-';
|
options.find(item => item.value === value)?.label || value || '-';
|
||||||
|
|
||||||
const searchOnlyColumn = ({ label, prop, searchOrder, type = 'input', dicData }) => {
|
/** 表格列的 avue 增量配置:插槽、覆盖宽度等 */
|
||||||
const column = {
|
|
||||||
label,
|
|
||||||
prop,
|
|
||||||
search: true,
|
|
||||||
searchOrder,
|
|
||||||
searchSpan: 5,
|
|
||||||
hide: true,
|
|
||||||
showColumn: false,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
};
|
|
||||||
if (type === 'select') {
|
|
||||||
column.type = 'select';
|
|
||||||
column.searchPlaceholder = '请选择';
|
|
||||||
column.dicData = dicData || [];
|
|
||||||
} else if (type === 'daterange') {
|
|
||||||
column.type = 'daterange';
|
|
||||||
column.searchType = 'daterange';
|
|
||||||
column.searchPlaceholder = '请选择';
|
|
||||||
} else {
|
|
||||||
column.searchPlaceholder = '请输入';
|
|
||||||
}
|
|
||||||
return column;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 表格列的 avue 增量配置:搜索项、插槽、覆盖宽度等 */
|
|
||||||
const COLUMN_EXTRA = {
|
const COLUMN_EXTRA = {
|
||||||
formalSettlementNo: {
|
formalSettlementNo: { slot: true },
|
||||||
slot: true,
|
|
||||||
search: true,
|
|
||||||
searchSpan: 5,
|
|
||||||
searchOrder: 12,
|
|
||||||
searchPlaceholder: '请输入',
|
|
||||||
},
|
|
||||||
payerName: { search: true, searchSpan: 5, searchOrder: 7, searchPlaceholder: '请输入' },
|
|
||||||
payeeName: { search: true, searchSpan: 5, searchOrder: 6, searchPlaceholder: '请输入' },
|
|
||||||
projectName: { search: true, searchSpan: 5, searchOrder: 11, searchPlaceholder: '请输入' },
|
|
||||||
deptName: { search: true, searchslot: true, searchSpan: 5, searchOrder: 10 },
|
|
||||||
contractNo: { search: true, searchSpan: 5, searchOrder: 9, searchPlaceholder: '请输入' },
|
|
||||||
sealTypes: { formatter: sealTypesFormatter },
|
sealTypes: { formatter: sealTypesFormatter },
|
||||||
invoiceStatusName: { slot: true },
|
invoiceStatusName: { slot: true },
|
||||||
paymentStatusName: { slot: true },
|
paymentStatusName: { slot: true },
|
||||||
@@ -82,27 +41,27 @@ const COLUMN_EXTRA = {
|
|||||||
adjustFlag: {
|
adjustFlag: {
|
||||||
formatter: row => row.adjustStatusName || (row.originFormalSettlementNo ? '调整后单' : '-'),
|
formatter: row => row.adjustStatusName || (row.originFormalSettlementNo ? '调整后单' : '-'),
|
||||||
},
|
},
|
||||||
kingdeeSyncStatus: {
|
kingdeeSyncStatus: { slot: true },
|
||||||
slot: true,
|
|
||||||
search: true,
|
|
||||||
type: 'select',
|
|
||||||
dicData: kingdeeSyncStatusOptions,
|
|
||||||
searchSpan: 5,
|
|
||||||
searchOrder: 2,
|
|
||||||
searchPlaceholder: '请选择',
|
|
||||||
},
|
|
||||||
kingdeeLockStatus: { slot: true },
|
kingdeeLockStatus: { slot: true },
|
||||||
kingdeeWriteOffStatus: { slot: true },
|
kingdeeWriteOffStatus: { slot: true },
|
||||||
kingdeeAssignStatus: { slot: true },
|
kingdeeAssignStatus: { slot: true },
|
||||||
createTime: { width: 180 },
|
createTime: { width: 180 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 收款/付款结算单按结算类型展示各自标签 */
|
||||||
|
const PAYMENT_FIELD_LABELS = {
|
||||||
|
paidAmount: { payable: '已付合计(含预付)', receivable: '已收合计(含预付)' },
|
||||||
|
paymentStatusName: { payable: '付款状态', receivable: '收款状态' },
|
||||||
|
};
|
||||||
|
|
||||||
// 已指定应付仅付款结算单(先票后款 A302-6)有,收款结算单不展示
|
// 已指定应付仅付款结算单(先票后款 A302-6)有,收款结算单不展示
|
||||||
const buildTableColumns = settlementType =>
|
const buildTableColumns = settlementType =>
|
||||||
formalSettlementTableColumns
|
formalSettlementTableColumns
|
||||||
.filter(column => !(settlementType === 'receivable' && column.prop === 'kingdeeAssignStatus'))
|
.filter(column => !(settlementType === 'receivable' && column.prop === 'kingdeeAssignStatus'))
|
||||||
.map(column => {
|
.map(column => {
|
||||||
const extra = { ...(COLUMN_EXTRA[column.prop] || {}) };
|
const extra = { ...(COLUMN_EXTRA[column.prop] || {}) };
|
||||||
|
const label = PAYMENT_FIELD_LABELS[column.prop]?.[settlementType];
|
||||||
|
if (label) extra.label = label;
|
||||||
if (column.money) {
|
if (column.money) {
|
||||||
extra.formatter = moneyFormatter;
|
extra.formatter = moneyFormatter;
|
||||||
extra.align = 'right';
|
extra.align = 'right';
|
||||||
@@ -118,15 +77,6 @@ export const formalSettlementOption = (settlementType = '') => ({
|
|||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchBtnText: '查询',
|
|
||||||
emptyBtnText: '重置',
|
|
||||||
searchShow: true,
|
|
||||||
searchIcon: true,
|
|
||||||
searchLabelWidth: 100,
|
|
||||||
// 查询/重置紧跟首行 4 个条件(4×5 + 菜单 4 = 24),不再独占下一整行
|
|
||||||
searchMenuSpan: 4,
|
|
||||||
searchIndex: 4,
|
|
||||||
searchMenuPosition: 'right',
|
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
@@ -141,45 +91,10 @@ export const formalSettlementOption = (settlementType = '') => ({
|
|||||||
editBtn: false,
|
editBtn: false,
|
||||||
menuWidth: 320,
|
menuWidth: 320,
|
||||||
menuFixed: 'right',
|
menuFixed: 'right',
|
||||||
column: [
|
column: [...buildTableColumns(settlementType)],
|
||||||
// ---------- 仅搜索列 ----------
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '预付结算单号',
|
|
||||||
prop: 'preSettlementNo',
|
|
||||||
searchOrder: 8,
|
|
||||||
}),
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '发票状态',
|
|
||||||
prop: 'invoiceStatus',
|
|
||||||
searchOrder: 5,
|
|
||||||
type: 'select',
|
|
||||||
dicData: invoiceStatusOptions,
|
|
||||||
}),
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '收付款状态',
|
|
||||||
prop: 'paymentStatus',
|
|
||||||
searchOrder: 4,
|
|
||||||
type: 'select',
|
|
||||||
dicData: paymentStatusOptions,
|
|
||||||
}),
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '审核状态',
|
|
||||||
prop: 'approvalStatus',
|
|
||||||
searchOrder: 3,
|
|
||||||
type: 'select',
|
|
||||||
dicData: approvalStatusOptions,
|
|
||||||
}),
|
|
||||||
searchOnlyColumn({
|
|
||||||
label: '生成日期',
|
|
||||||
prop: 'createDateRange',
|
|
||||||
searchOrder: 1,
|
|
||||||
type: 'daterange',
|
|
||||||
}),
|
|
||||||
// ---------- 表格列(部分兼搜索项) ----------
|
|
||||||
...buildTableColumns(settlementType),
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const kingdeeSyncName = value => pickLabel(kingdeeSyncStatusOptions, value);
|
export const kingdeeSyncName = value => pickLabel(kingdeeSyncStatusOptions, value);
|
||||||
export const kingdeeWriteOffName = value => pickLabel(kingdeeWriteOffStatusOptions, value);
|
export const kingdeeWriteOffName = value => pickLabel(kingdeeWriteOffStatusOptions, value);
|
||||||
export const paymentStatusName = value => pickLabel(paymentStatusOptions, value);
|
export const paymentStatusName = (value, settlementType) =>
|
||||||
|
pickLabel(paymentStatusOptions(settlementType), value);
|
||||||
|
|||||||
@@ -6,27 +6,28 @@ export const approvalStatusOptions = [
|
|||||||
{ label: '已作废', value: 'voided' },
|
{ label: '已作废', value: 'voided' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const invoiceStatusOptions = [
|
/** 发票状态选项按结算类型区分:付款结算单=收票方向,收款结算单=开票方向 */
|
||||||
{ label: '未开/收票', value: 'unreceived' },
|
export const invoiceStatusOptions = (settlementType = '') => {
|
||||||
{ label: '部分开/收票', value: 'partial' },
|
const received = settlementType === 'payable';
|
||||||
{ label: '已开/收票', value: 'completed' },
|
return [
|
||||||
|
{ label: received ? '未收票' : '未开票', value: 'unreceived' },
|
||||||
|
{ label: received ? '部分收票' : '部分开票', value: 'partial' },
|
||||||
|
{ label: received ? '已收票' : '已开票', value: 'completed' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const invoiceStatusName = (value, settlementType) => {
|
|
||||||
const payable = settlementType === 'payable';
|
|
||||||
const labels = {
|
|
||||||
unreceived: payable ? '未收票' : '未开票',
|
|
||||||
partial: payable ? '部分收票' : '部分开票',
|
|
||||||
completed: payable ? '已收票' : '已开票',
|
|
||||||
};
|
|
||||||
return labels[value] || value || '-';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const paymentStatusOptions = [
|
export const invoiceStatusName = (value, settlementType) =>
|
||||||
{ label: '未收/付款', value: 'unpaid' },
|
invoiceStatusOptions(settlementType).find(item => item.value === value)?.label || value || '-';
|
||||||
{ label: '部分收/付款', value: 'partial' },
|
|
||||||
{ label: '已收/付款', value: 'paid' },
|
/** 收付款状态选项按结算类型区分:付款结算单=付款方向,收款结算单=收款方向 */
|
||||||
|
export const paymentStatusOptions = (settlementType = '') => {
|
||||||
|
const suffix = settlementType === 'payable' ? '付款' : '收款';
|
||||||
|
return [
|
||||||
|
{ label: `未${suffix}`, value: 'unpaid' },
|
||||||
|
{ label: `部分${suffix}`, value: 'partial' },
|
||||||
|
{ label: `已${suffix}`, value: 'paid' },
|
||||||
];
|
];
|
||||||
|
};
|
||||||
|
|
||||||
export const kingdeeSyncStatusOptions = [
|
export const kingdeeSyncStatusOptions = [
|
||||||
{ label: '未同步', value: 'unsynced' },
|
{ label: '未同步', value: 'unsynced' },
|
||||||
@@ -38,23 +39,3 @@ export const kingdeeWriteOffStatusOptions = [
|
|||||||
{ label: '未冲销', value: 'unwrittenoff' },
|
{ label: '未冲销', value: 'unwrittenoff' },
|
||||||
{ label: '已冲销', value: 'writtenoff' },
|
{ label: '已冲销', value: 'writtenoff' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const formalSettlementSearchFields = [
|
|
||||||
{ label: '结算单号', prop: 'formalSettlementNo', type: 'input' },
|
|
||||||
{ label: '预付结算单号', prop: 'preSettlementNo', type: 'input' },
|
|
||||||
{ label: '项目', prop: 'projectName', type: 'input' },
|
|
||||||
{ label: '所属组织', prop: 'deptName', type: 'cascader' },
|
|
||||||
{ label: '合同编号', prop: 'contractNo', type: 'input' },
|
|
||||||
{ label: '付款方', prop: 'payerName', type: 'input' },
|
|
||||||
{ label: '收款方', prop: 'payeeName', type: 'input' },
|
|
||||||
{ label: '发票状态', prop: 'invoiceStatus', type: 'select', options: invoiceStatusOptions },
|
|
||||||
{ label: '收付款状态', prop: 'paymentStatus', type: 'select', options: paymentStatusOptions },
|
|
||||||
{ label: '审核状态', prop: 'approvalStatus', type: 'select', options: approvalStatusOptions },
|
|
||||||
{
|
|
||||||
label: '金蝶单据状态',
|
|
||||||
prop: 'kingdeeSyncStatus',
|
|
||||||
type: 'select',
|
|
||||||
options: kingdeeSyncStatusOptions,
|
|
||||||
},
|
|
||||||
{ label: '生成日期', prop: 'createDateRange', type: 'daterange' },
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -1115,6 +1115,8 @@ export default {
|
|||||||
);
|
);
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.amountSyncing = false;
|
this.amountSyncing = false;
|
||||||
|
// 程序化赋值不触发校验,需手动重校验以清除/刷新残留错误
|
||||||
|
this.$refs.formRef?.validateField?.('appliedAmount').catch(() => {});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
'form.appliedAmount'(value) {
|
'form.appliedAmount'(value) {
|
||||||
@@ -1144,6 +1146,7 @@ export default {
|
|||||||
);
|
);
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.amountSyncing = false;
|
this.amountSyncing = false;
|
||||||
|
this.$refs.formRef?.validateField?.('appliedAmount').catch(() => {});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,13 +1,61 @@
|
|||||||
<template>
|
<template>
|
||||||
<basic-container class="payment-page">
|
<basic-container class="payment-page">
|
||||||
|
<section class="payment-search">
|
||||||
|
<el-form :model="searchForm" label-position="right" label-width="88px" @submit.prevent>
|
||||||
|
<div class="payment-search__grid">
|
||||||
|
<template v-for="field in visibleSearchFields" :key="field.prop">
|
||||||
|
<el-form-item :label="field.label">
|
||||||
|
<el-date-picker
|
||||||
|
v-if="field.type === 'daterange'"
|
||||||
|
v-model="searchForm[field.prop]"
|
||||||
|
type="daterange"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
range-separator="~"
|
||||||
|
start-placeholder="年/月/日"
|
||||||
|
end-placeholder="年/月/日"
|
||||||
|
/>
|
||||||
|
<el-select
|
||||||
|
v-else-if="field.type === 'select'"
|
||||||
|
v-model="searchForm[field.prop]"
|
||||||
|
clearable
|
||||||
|
placeholder="请选择"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in field.options"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-cascader
|
||||||
|
v-else-if="field.type === 'cascader'"
|
||||||
|
v-model="searchForm[field.prop]"
|
||||||
|
:options="organizationSearchTreeOptions"
|
||||||
|
:props="organizationCascaderProps"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择 所属组织"
|
||||||
|
/>
|
||||||
|
<el-input v-else v-model="searchForm[field.prop]" clearable placeholder="请输入" />
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<div class="payment-search__actions">
|
||||||
|
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button @click="handleReset">重置</el-button>
|
||||||
|
<el-button text :icon="searchExpanded ? ArrowUp : ArrowDown" @click="toggleSearch">
|
||||||
|
{{ searchExpanded ? '收起' : '展开' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</section>
|
||||||
<avue-crud
|
<avue-crud
|
||||||
ref="crud"
|
ref="crud"
|
||||||
:option="option"
|
:option="option"
|
||||||
:table-loading="loading"
|
:table-loading="loading"
|
||||||
:data="rows"
|
:data="rows"
|
||||||
v-model:page="page"
|
v-model:page="page"
|
||||||
@search-change="searchChange"
|
|
||||||
@search-reset="searchReset"
|
|
||||||
@selection-change="selectionChange"
|
@selection-change="selectionChange"
|
||||||
@current-change="currentChange"
|
@current-change="currentChange"
|
||||||
@size-change="sizeChange"
|
@size-change="sizeChange"
|
||||||
@@ -174,6 +222,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import * as api from '@/api/payment/paymentApplication';
|
import * as api from '@/api/payment/paymentApplication';
|
||||||
import { paymentApplicationOption } from '@/option/payment/paymentApplication';
|
import { paymentApplicationOption } from '@/option/payment/paymentApplication';
|
||||||
@@ -190,6 +239,8 @@ export default {
|
|||||||
mixins: [organizationSearch],
|
mixins: [organizationSearch],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
ArrowDown,
|
||||||
|
ArrowUp,
|
||||||
rows: [],
|
rows: [],
|
||||||
selection: [],
|
selection: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -197,6 +248,9 @@ export default {
|
|||||||
syncLoading: false,
|
syncLoading: false,
|
||||||
resultSyncing: false,
|
resultSyncing: false,
|
||||||
query: {},
|
query: {},
|
||||||
|
// 手写搜索区(与应收/应付明细同款):模型与展开状态
|
||||||
|
searchForm: {},
|
||||||
|
searchExpanded: false,
|
||||||
option: {},
|
option: {},
|
||||||
page: {
|
page: {
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
@@ -209,13 +263,37 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['permission']),
|
...mapGetters(['permission']),
|
||||||
|
// 搜索字段与应收/应付明细同结构;下拉选项沿用 api 常量
|
||||||
|
searchFields() {
|
||||||
|
return [
|
||||||
|
{ label: '单据号', prop: 'paymentNo', type: 'input' },
|
||||||
|
{ label: '日期', prop: 'applyDateRange', type: 'daterange' },
|
||||||
|
{ label: '客户名称', prop: 'payeeName', type: 'input' },
|
||||||
|
{ label: '项目名称', prop: 'projectName', type: 'input' },
|
||||||
|
{ label: '所属组织', prop: 'deptName', type: 'cascader' },
|
||||||
|
{ label: '关联结算单', prop: 'settlementNo', type: 'input' },
|
||||||
|
{ label: '付款类型', prop: 'paymentType', type: 'select', options: api.paymentTypeOptions },
|
||||||
|
{
|
||||||
|
label: '审核状态',
|
||||||
|
prop: 'approvalStatus',
|
||||||
|
type: 'select',
|
||||||
|
options: api.approvalStatusOptions,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '金蝶单据状态',
|
||||||
|
prop: 'kingdeeStatus',
|
||||||
|
type: 'select',
|
||||||
|
options: api.kingdeeStatusOptions,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
// 默认折叠只展示一行 4 个条件
|
||||||
|
visibleSearchFields() {
|
||||||
|
return this.searchExpanded ? this.searchFields : this.searchFields.slice(0, 4);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.option = paymentApplicationOption({
|
this.option = paymentApplicationOption();
|
||||||
paymentTypeOptions: api.paymentTypeOptions,
|
|
||||||
approvalStatusOptions: api.approvalStatusOptions,
|
|
||||||
kingdeeStatusOptions: api.kingdeeStatusOptions,
|
|
||||||
});
|
|
||||||
this.loadOrganizationOptions();
|
this.loadOrganizationOptions();
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -271,26 +349,30 @@ export default {
|
|||||||
this.$refs.crud?.toggleSelection?.();
|
this.$refs.crud?.toggleSelection?.();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
searchChange(params, done) {
|
// 搜索提交:组织级联路径转名称、日期区间拆成起止参数(与原 avue searchChange 同规则)
|
||||||
// 所属组织级联返回 id 路径数组,转成部门名称给后端
|
buildSearchParams() {
|
||||||
|
const params = { ...this.searchForm };
|
||||||
this.normalizeOrganizationSearch(params, 'deptName');
|
this.normalizeOrganizationSearch(params, 'deptName');
|
||||||
// 日期区间拆成后端需要的起止字段
|
|
||||||
const range = params.applyDateRange || [];
|
const range = params.applyDateRange || [];
|
||||||
delete params.applyDateRange;
|
delete params.applyDateRange;
|
||||||
this.query = {
|
return { ...params, applyStartDate: range[0] || '', applyEndDate: range[1] || '' };
|
||||||
...params,
|
},
|
||||||
applyStartDate: range[0] || '',
|
handleSearch() {
|
||||||
applyEndDate: range[1] || '',
|
this.query = this.buildSearchParams();
|
||||||
};
|
|
||||||
this.page.currentPage = 1;
|
this.page.currentPage = 1;
|
||||||
this.onLoad(this.page);
|
this.onLoad(this.page);
|
||||||
done();
|
|
||||||
},
|
},
|
||||||
searchReset() {
|
handleReset() {
|
||||||
|
this.searchForm = {};
|
||||||
this.query = {};
|
this.query = {};
|
||||||
this.page.currentPage = 1;
|
this.page.currentPage = 1;
|
||||||
this.onLoad(this.page);
|
this.onLoad(this.page);
|
||||||
},
|
},
|
||||||
|
toggleSearch() {
|
||||||
|
this.searchExpanded = !this.searchExpanded;
|
||||||
|
// 搜索区在 avue 外部,高度变化 avue 感知不到,手动触发表格高度重算,保证分页在一屏内
|
||||||
|
this.$nextTick(() => this.$refs.crud?.getTableHeight?.());
|
||||||
|
},
|
||||||
currentChange(currentPage) {
|
currentChange(currentPage) {
|
||||||
this.page.currentPage = currentPage;
|
this.page.currentPage = currentPage;
|
||||||
},
|
},
|
||||||
@@ -544,6 +626,56 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
// 搜索区与应收/应付明细页(settlement-detail-page__search)同款样式
|
||||||
|
.payment-search {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 12px 12px 4px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
|
:deep(.el-form-item__label) {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-search__grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, minmax(220px, 1fr));
|
||||||
|
gap: 8px 24px;
|
||||||
|
align-items: start;
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input),
|
||||||
|
:deep(.el-select),
|
||||||
|
:deep(.el-cascader),
|
||||||
|
:deep(.el-date-editor) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-search__actions {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
|
.payment-search__grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(220px, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 760px) {
|
||||||
|
.payment-search__grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.payment-page :deep(.el-table) {
|
.payment-page :deep(.el-table) {
|
||||||
--el-table-border-color: #eff1f7;
|
--el-table-border-color: #eff1f7;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
:table-loading="loading"
|
:table-loading="loading"
|
||||||
:data="rows"
|
:data="rows"
|
||||||
v-model:page="crudPage"
|
v-model:page="crudPage"
|
||||||
@search-change="(params, done) => $emit('search-change', params, done)"
|
|
||||||
@search-reset="$emit('search-reset')"
|
|
||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
@refresh-change="$emit('refresh')"
|
@refresh-change="$emit('refresh')"
|
||||||
@on-load="page => $emit('load', page)"
|
@on-load="page => $emit('load', page)"
|
||||||
@@ -61,7 +59,9 @@
|
|||||||
}}</span>
|
}}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #paymentStatusName="{ row }">{{ paymentName(row.paymentStatus) }}</template>
|
<template #paymentStatusName="{ row }">{{
|
||||||
|
paymentName(row.paymentStatus, row.settlementType)
|
||||||
|
}}</template>
|
||||||
|
|
||||||
<template #approvalStatusName="{ row }">
|
<template #approvalStatusName="{ row }">
|
||||||
<el-tag :type="statusType(row.approvalStatus)" class="status-text">{{
|
<el-tag :type="statusType(row.approvalStatus)" class="status-text">{{
|
||||||
@@ -154,8 +154,6 @@ export default {
|
|||||||
'load',
|
'load',
|
||||||
'action',
|
'action',
|
||||||
'update:selection',
|
'update:selection',
|
||||||
'search-change',
|
|
||||||
'search-reset',
|
|
||||||
],
|
],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -181,6 +179,10 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
/** 搜索区展开/收起后由父级调用:avue 表格是固定像素高度,需手动触发了重新计算,否则分页会被推出视口 */
|
||||||
|
recalcTableHeight() {
|
||||||
|
this.$nextTick(() => this.$refs.crud?.getTableHeight?.());
|
||||||
|
},
|
||||||
handleSelectionChange(selection) {
|
handleSelectionChange(selection) {
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
this.$emit('update:selection', selection);
|
this.$emit('update:selection', selection);
|
||||||
@@ -236,8 +238,8 @@ export default {
|
|||||||
invoiceName(value, settlementType) {
|
invoiceName(value, settlementType) {
|
||||||
return invoiceStatusName(value, settlementType);
|
return invoiceStatusName(value, settlementType);
|
||||||
},
|
},
|
||||||
paymentName(value) {
|
paymentName(value, settlementType) {
|
||||||
return paymentStatusName(value);
|
return paymentStatusName(value, settlementType);
|
||||||
},
|
},
|
||||||
kingdeeSyncName(value) {
|
kingdeeSyncName(value) {
|
||||||
return kingdeeSyncName(value);
|
return kingdeeSyncName(value);
|
||||||
|
|||||||
@@ -1,5 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<basic-container class="formal-page">
|
<basic-container class="formal-page">
|
||||||
|
<section class="formal-search">
|
||||||
|
<el-form :model="searchForm" label-position="right" label-width="88px" @submit.prevent>
|
||||||
|
<div class="formal-search__grid">
|
||||||
|
<template v-for="field in visibleSearchFields" :key="field.prop">
|
||||||
|
<el-form-item :label="field.label">
|
||||||
|
<el-date-picker
|
||||||
|
v-if="field.type === 'daterange'"
|
||||||
|
v-model="searchForm[field.prop]"
|
||||||
|
type="daterange"
|
||||||
|
format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
range-separator="~"
|
||||||
|
start-placeholder="年/月/日"
|
||||||
|
end-placeholder="年/月/日"
|
||||||
|
/>
|
||||||
|
<el-select
|
||||||
|
v-else-if="field.type === 'select'"
|
||||||
|
v-model="searchForm[field.prop]"
|
||||||
|
clearable
|
||||||
|
placeholder="请选择"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in field.options"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-cascader
|
||||||
|
v-else-if="field.type === 'cascader'"
|
||||||
|
v-model="searchForm[field.prop]"
|
||||||
|
:options="organizationSearchTreeOptions"
|
||||||
|
:props="organizationCascaderProps"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择 所属组织"
|
||||||
|
/>
|
||||||
|
<el-input v-else v-model="searchForm[field.prop]" clearable placeholder="请输入" />
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<div class="formal-search__actions">
|
||||||
|
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button @click="handleReset">重置</el-button>
|
||||||
|
<el-button text :icon="searchExpanded ? ArrowUp : ArrowDown" @click="toggleSearch">
|
||||||
|
{{ searchExpanded ? '收起' : '展开' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</section>
|
||||||
<el-tabs
|
<el-tabs
|
||||||
v-if="!lockedSettlementType"
|
v-if="!lockedSettlementType"
|
||||||
type="border-card"
|
type="border-card"
|
||||||
@@ -10,6 +60,7 @@
|
|||||||
<formal-settlement-table-panel
|
<formal-settlement-table-panel
|
||||||
v-if="activeSettlementType === 'payable'"
|
v-if="activeSettlementType === 'payable'"
|
||||||
key="payable"
|
key="payable"
|
||||||
|
ref="panel"
|
||||||
v-bind="tablePanelProps"
|
v-bind="tablePanelProps"
|
||||||
v-on="tablePanelListeners"
|
v-on="tablePanelListeners"
|
||||||
/>
|
/>
|
||||||
@@ -18,6 +69,7 @@
|
|||||||
<formal-settlement-table-panel
|
<formal-settlement-table-panel
|
||||||
v-if="activeSettlementType === 'receivable'"
|
v-if="activeSettlementType === 'receivable'"
|
||||||
key="receivable"
|
key="receivable"
|
||||||
|
ref="panel"
|
||||||
v-bind="tablePanelProps"
|
v-bind="tablePanelProps"
|
||||||
v-on="tablePanelListeners"
|
v-on="tablePanelListeners"
|
||||||
/>
|
/>
|
||||||
@@ -26,6 +78,7 @@
|
|||||||
<formal-settlement-table-panel
|
<formal-settlement-table-panel
|
||||||
v-else
|
v-else
|
||||||
key="locked"
|
key="locked"
|
||||||
|
ref="panel"
|
||||||
v-bind="tablePanelProps"
|
v-bind="tablePanelProps"
|
||||||
v-on="tablePanelListeners"
|
v-on="tablePanelListeners"
|
||||||
/>
|
/>
|
||||||
@@ -222,6 +275,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue';
|
||||||
import { createSettlementTransfer } from '@/utils/settlement-transfer';
|
import { createSettlementTransfer } from '@/utils/settlement-transfer';
|
||||||
import {
|
import {
|
||||||
hasSettlementPermission,
|
hasSettlementPermission,
|
||||||
@@ -234,6 +288,13 @@ import * as api from '@/api/settlement/formalSettlement';
|
|||||||
import * as paymentApi from '@/api/payment/paymentApplication';
|
import * as paymentApi from '@/api/payment/paymentApplication';
|
||||||
import * as invoiceReceiptApi from '@/api/payment/invoiceReceipt';
|
import * as invoiceReceiptApi from '@/api/payment/invoiceReceipt';
|
||||||
import { formalSettlementOption, kingdeeSyncName } from '@/option/settlement/formalSettlement';
|
import { formalSettlementOption, kingdeeSyncName } from '@/option/settlement/formalSettlement';
|
||||||
|
import {
|
||||||
|
approvalStatusOptions,
|
||||||
|
invoiceStatusOptions,
|
||||||
|
kingdeeSyncStatusOptions,
|
||||||
|
paymentStatusOptions,
|
||||||
|
} from '@/option/settlement/formalSettlementSearch';
|
||||||
|
import { getDictionary } from '@/api/system/dictbiz';
|
||||||
import organizationSearch from '@/mixins/organization-search';
|
import organizationSearch from '@/mixins/organization-search';
|
||||||
import FormalSettlementEditor from './components/formal-settlement-editor.vue';
|
import FormalSettlementEditor from './components/formal-settlement-editor.vue';
|
||||||
import FormalSettlementTablePanel from './components/formal-settlement-table-panel.vue';
|
import FormalSettlementTablePanel from './components/formal-settlement-table-panel.vue';
|
||||||
@@ -256,7 +317,16 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
ArrowDown,
|
||||||
|
ArrowUp,
|
||||||
query: {},
|
query: {},
|
||||||
|
// 手写搜索区(与应收/应付明细同款):模型与展开状态
|
||||||
|
searchForm: {},
|
||||||
|
searchExpanded: false,
|
||||||
|
// 发票状态/收付款状态下拉选项:来自数据字典(按结算类型区分收/付方向),
|
||||||
|
// 字典未配置时回退前端默认文案(见 loadStatusDicts)
|
||||||
|
invoiceStatusDict: [],
|
||||||
|
paymentStatusDict: [],
|
||||||
activeSettlementType: 'payable',
|
activeSettlementType: 'payable',
|
||||||
rows: [],
|
rows: [],
|
||||||
selection: [],
|
selection: [],
|
||||||
@@ -289,6 +359,47 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['permission', 'userInfo']),
|
...mapGetters(['permission', 'userInfo']),
|
||||||
|
// 搜索字段与应收/应付明细同结构;收付款/发票状态选项随结算类型区分
|
||||||
|
searchFields() {
|
||||||
|
return [
|
||||||
|
{ label: '结算单号', prop: 'formalSettlementNo', type: 'input' },
|
||||||
|
{ label: '项目名称', prop: 'projectName', type: 'input' },
|
||||||
|
{ label: '所属组织', prop: 'deptName', type: 'cascader' },
|
||||||
|
{ label: '合同编号', prop: 'contractNo', type: 'input' },
|
||||||
|
{ label: '预付结算单号', prop: 'preSettlementNo', type: 'input' },
|
||||||
|
{ label: '付款方', prop: 'payerName', type: 'input' },
|
||||||
|
{ label: '收款方', prop: 'payeeName', type: 'input' },
|
||||||
|
{
|
||||||
|
label: '发票状态',
|
||||||
|
prop: 'invoiceStatus',
|
||||||
|
type: 'select',
|
||||||
|
options: this.invoiceStatusDict,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.activeSettlementType === 'payable' ? '付款状态' : '收款状态',
|
||||||
|
prop: 'paymentStatus',
|
||||||
|
type: 'select',
|
||||||
|
options: this.paymentStatusDict,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '审核状态',
|
||||||
|
prop: 'approvalStatus',
|
||||||
|
type: 'select',
|
||||||
|
options: approvalStatusOptions,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '金蝶单据状态',
|
||||||
|
prop: 'kingdeeSyncStatus',
|
||||||
|
type: 'select',
|
||||||
|
options: kingdeeSyncStatusOptions,
|
||||||
|
},
|
||||||
|
{ label: '生成日期', prop: 'createDateRange', type: 'daterange' },
|
||||||
|
];
|
||||||
|
},
|
||||||
|
// 默认折叠只展示一行 4 个条件
|
||||||
|
visibleSearchFields() {
|
||||||
|
return this.searchExpanded ? this.searchFields : this.searchFields.slice(0, 4);
|
||||||
|
},
|
||||||
// 列随结算类型切换重建:收款结算单不展示「已指定应付」
|
// 列随结算类型切换重建:收款结算单不展示「已指定应付」
|
||||||
option() {
|
option() {
|
||||||
return formalSettlementOption(this.activeSettlementType);
|
return formalSettlementOption(this.activeSettlementType);
|
||||||
@@ -330,8 +441,6 @@ export default {
|
|||||||
refresh: () => this.onLoad(this.page),
|
refresh: () => this.onLoad(this.page),
|
||||||
load: this.onLoad,
|
load: this.onLoad,
|
||||||
action: this.onAction,
|
action: this.onAction,
|
||||||
'search-change': this.searchChange,
|
|
||||||
'search-reset': this.searchReset,
|
|
||||||
'update:selection': selection => {
|
'update:selection': selection => {
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
},
|
},
|
||||||
@@ -353,6 +462,8 @@ export default {
|
|||||||
activeSettlementType() {
|
activeSettlementType() {
|
||||||
// 切换结算类型后由新挂载的 avue-crud 触发 on-load,此处只重置分页,避免重复请求
|
// 切换结算类型后由新挂载的 avue-crud 触发 on-load,此处只重置分页,避免重复请求
|
||||||
this.page.currentPage = 1;
|
this.page.currentPage = 1;
|
||||||
|
// 收/付方向的字典文案不同,切 tab 后重拉
|
||||||
|
this.loadStatusDicts();
|
||||||
},
|
},
|
||||||
'$route.query.detailNo'(detailNo) {
|
'$route.query.detailNo'(detailNo) {
|
||||||
if (detailNo) this.openRouteDetail(detailNo);
|
if (detailNo) this.openRouteDetail(detailNo);
|
||||||
@@ -360,6 +471,7 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.loadOrganizationOptions();
|
this.loadOrganizationOptions();
|
||||||
|
this.loadStatusDicts();
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.isPageActive = true;
|
this.isPageActive = true;
|
||||||
@@ -402,25 +514,57 @@ export default {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
searchChange(params, done) {
|
/**
|
||||||
// 所属组织级联返回 id 路径,转成组织名称传给后端
|
* 发票状态/收付款状态下拉选项从字典加载(dictKey=后端状态值,dictValue=文案)。
|
||||||
|
* 收/付两个方向文案不同,按结算类型区分字典编码:
|
||||||
|
* invoice_status_payable / invoice_status_receivable
|
||||||
|
* payment_status_payable / payment_status_receivable
|
||||||
|
* 字典未配置或为空时回退前端默认文案,保证页面可用。
|
||||||
|
*/
|
||||||
|
loadStatusDicts() {
|
||||||
|
const type = this.activeSettlementType;
|
||||||
|
const fallback = {
|
||||||
|
invoice: invoiceStatusOptions(type),
|
||||||
|
payment: paymentStatusOptions(type),
|
||||||
|
};
|
||||||
|
const pick = res =>
|
||||||
|
(res?.data?.data || [])
|
||||||
|
.map(item => ({ label: item.dictValue, value: String(item.dictKey) }))
|
||||||
|
.filter(item => item.label && item.value);
|
||||||
|
Promise.all([
|
||||||
|
getDictionary({ code: `invoice_status_${type}` }).catch(() => null),
|
||||||
|
getDictionary({ code: `payment_status_${type}` }).catch(() => null),
|
||||||
|
]).then(([invoiceRes, paymentRes]) => {
|
||||||
|
const invoice = pick(invoiceRes);
|
||||||
|
const payment = pick(paymentRes);
|
||||||
|
this.invoiceStatusDict = invoice.length ? invoice : fallback.invoice;
|
||||||
|
this.paymentStatusDict = payment.length ? payment : fallback.payment;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 搜索提交:组织级联路径转名称、日期区间拆成起止参数(与原 avue searchChange 同规则)
|
||||||
|
buildSearchParams() {
|
||||||
|
const params = { ...this.searchForm };
|
||||||
this.normalizeOrganizationSearch(params, 'deptName');
|
this.normalizeOrganizationSearch(params, 'deptName');
|
||||||
const range = params.createDateRange || [];
|
const range = params.createDateRange || [];
|
||||||
delete params.createDateRange;
|
delete params.createDateRange;
|
||||||
this.query = {
|
return { ...params, createStartDate: range[0] || '', createEndDate: range[1] || '' };
|
||||||
...params,
|
},
|
||||||
createStartDate: range[0] || '',
|
handleSearch() {
|
||||||
createEndDate: range[1] || '',
|
this.query = this.buildSearchParams();
|
||||||
};
|
|
||||||
this.page.currentPage = 1;
|
this.page.currentPage = 1;
|
||||||
this.onLoad(this.page);
|
this.onLoad(this.page);
|
||||||
done();
|
|
||||||
},
|
},
|
||||||
searchReset() {
|
handleReset() {
|
||||||
|
this.searchForm = {};
|
||||||
this.query = {};
|
this.query = {};
|
||||||
this.page.currentPage = 1;
|
this.page.currentPage = 1;
|
||||||
this.onLoad(this.page);
|
this.onLoad(this.page);
|
||||||
},
|
},
|
||||||
|
toggleSearch() {
|
||||||
|
this.searchExpanded = !this.searchExpanded;
|
||||||
|
// 搜索区在 avue 外部,高度变化 avue 感知不到,需手动触发表格高度重算,保证分页在一屏内
|
||||||
|
this.$refs.panel?.recalcTableHeight();
|
||||||
|
},
|
||||||
onAction({ type, row }) {
|
onAction({ type, row }) {
|
||||||
const handlers = {
|
const handlers = {
|
||||||
view: () => this.openView(row),
|
view: () => this.openView(row),
|
||||||
@@ -881,6 +1025,56 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
// 搜索区与应收/应付明细页(settlement-detail-page__search)同款样式
|
||||||
|
.formal-search {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 12px 12px 4px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
|
:deep(.el-form-item__label) {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.formal-search__grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, minmax(220px, 1fr));
|
||||||
|
gap: 8px 24px;
|
||||||
|
align-items: start;
|
||||||
|
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input),
|
||||||
|
:deep(.el-select),
|
||||||
|
:deep(.el-cascader),
|
||||||
|
:deep(.el-date-editor) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.formal-search__actions {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1200px) {
|
||||||
|
.formal-search__grid {
|
||||||
|
grid-template-columns: repeat(2, minmax(220px, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 760px) {
|
||||||
|
.formal-search__grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.formal-page {
|
.formal-page {
|
||||||
:deep(.el-table) {
|
:deep(.el-table) {
|
||||||
--el-table-border-color: #eff1f7;
|
--el-table-border-color: #eff1f7;
|
||||||
|
|||||||
Reference in New Issue
Block a user