Merge remote-tracking branch 'websoft/master'
# Conflicts: # src/views/business/components/business-crud-page.vue # src/views/business/contract-manage.vue # src/views/settlement/components/pre-settlement-editor.vue # src/views/settlement/formal-settlement.vue
This commit is contained in:
@@ -21,13 +21,6 @@ export const config = {
|
||||
|
||||
export const option = {
|
||||
...createCrudOption([
|
||||
{
|
||||
label: '',
|
||||
prop: 'basicInfo',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
hide: true,
|
||||
},
|
||||
{
|
||||
label: '配置名称',
|
||||
prop: 'configName',
|
||||
@@ -167,22 +160,10 @@ export const option = {
|
||||
dicData: [],
|
||||
filterable: true,
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
prop: 'nodeConfigJson',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
hide: true,
|
||||
},
|
||||
]),
|
||||
saveBtn: false,
|
||||
updateBtn: false,
|
||||
addBtn: false,
|
||||
viewBtn: false,
|
||||
editBtn: false,
|
||||
delBtn: false,
|
||||
dialogTop: '4vh',
|
||||
dialogWidth: '96%',
|
||||
dialogCustomClass: 'process-config-dialog',
|
||||
menuWidth: 220,
|
||||
};
|
||||
|
||||
@@ -275,6 +275,8 @@ export const option = {
|
||||
),
|
||||
dialogWidth: '92%',
|
||||
dialogTop: '4vh',
|
||||
// label 宽度一致(容纳 6 汉字,超出换行由全局样式控制),右对齐由 labelPosition: 'right' 保证
|
||||
labelWidth: 100,
|
||||
// 自定义弹窗 class,用于让新增/编辑弹窗体占满视口高度、视觉居中(参照 vehicle/customer-archive)
|
||||
dialogCustomClass: 'shipping-template-dialog',
|
||||
};
|
||||
|
||||
@@ -45,6 +45,36 @@ export const config = {
|
||||
editStatus: ['draft', 'withdrawn', 'rejected', '草稿', '已撤回'],
|
||||
ignoreReadonlyEditStatus: ['draft', 'withdrawn', '草稿', '已撤回'],
|
||||
ignoreReadonlyDeleteStatus: ['draft', '草稿'],
|
||||
detailButton: true,
|
||||
detailButtonIgnoreDraftStatus: true,
|
||||
detailAlignCenter: true,
|
||||
detailSections: [
|
||||
{
|
||||
title: '申请信息',
|
||||
fields: [
|
||||
['applicationNo', '申请单号', 2],
|
||||
['projectName', '项目', 1],
|
||||
['projectCode', '项目编号', 1],
|
||||
['undertakeDeptName', '承办部门', 1],
|
||||
['applyDeptName', '申请部门', 1],
|
||||
['applicantName', '申请人', 1],
|
||||
['approvalStatus', '审批状态', 1],
|
||||
['currentNode', '当前节点', 1],
|
||||
['currentProcessor', '当前处理人', 1],
|
||||
['validUntil', '申请有效期至', 1],
|
||||
['remark', '备注', 2],
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '额度信息',
|
||||
fields: [
|
||||
['projectFundLimit', '项目资金使用额度(万元)', 1],
|
||||
['usedFundLimit', '已使用项目资金使用额度(万元)', 1],
|
||||
['remainingFundLimit', '剩余项目资金使用额度(万元)', 1],
|
||||
['applyLimit', '申请临时额度(万元)', 1],
|
||||
],
|
||||
},
|
||||
],
|
||||
operations: [
|
||||
{
|
||||
action: 'submitApproval',
|
||||
@@ -113,7 +143,7 @@ export const option = {
|
||||
value: 'projectName',
|
||||
},
|
||||
filterable: true,
|
||||
span: 8,
|
||||
span: 6,
|
||||
minWidth: 180,
|
||||
rules: textRule('项目名称', 100, true),
|
||||
},
|
||||
@@ -128,7 +158,7 @@ export const option = {
|
||||
prop: 'projectCode',
|
||||
hide: true,
|
||||
disabled: true,
|
||||
span: 8,
|
||||
span: 6,
|
||||
minWidth: 150,
|
||||
rules: textRule('项目编号', 50),
|
||||
},
|
||||
@@ -137,7 +167,7 @@ export const option = {
|
||||
prop: 'undertakeDeptName',
|
||||
hide: true,
|
||||
disabled: true,
|
||||
span: 8,
|
||||
span: 6,
|
||||
minWidth: 150,
|
||||
rules: textRule('承办部门', 50, true),
|
||||
},
|
||||
@@ -146,7 +176,7 @@ export const option = {
|
||||
prop: 'projectFundLimit',
|
||||
hide: true,
|
||||
disabled: true,
|
||||
span: 8,
|
||||
span: 6,
|
||||
minWidth: 200,
|
||||
rules: [nonNegativeRule('项目资金使用额度')],
|
||||
},
|
||||
@@ -155,7 +185,7 @@ export const option = {
|
||||
prop: 'usedFundLimit',
|
||||
hide: true,
|
||||
disabled: true,
|
||||
span: 8,
|
||||
span: 6,
|
||||
minWidth: 220,
|
||||
value: 0,
|
||||
rules: [nonNegativeRule('已使用项目资金额度')],
|
||||
@@ -165,7 +195,7 @@ export const option = {
|
||||
prop: 'remainingFundLimit',
|
||||
hide: true,
|
||||
disabled: true,
|
||||
span: 8,
|
||||
span: 6,
|
||||
minWidth: 230,
|
||||
value: 0,
|
||||
rules: [nonNegativeRule('剩余项目资金使用额度')],
|
||||
@@ -174,7 +204,7 @@ export const option = {
|
||||
label: '申请临时额度(万元)',
|
||||
prop: 'applyLimit',
|
||||
formslot: true,
|
||||
span: 8,
|
||||
span: 6,
|
||||
minWidth: 180,
|
||||
rules: [
|
||||
{ required: true, message: '请输入申请临时额度', trigger: 'blur' },
|
||||
@@ -187,7 +217,7 @@ export const option = {
|
||||
type: 'date',
|
||||
format: 'YYYY-MM-DD',
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
span: 8,
|
||||
span: 6,
|
||||
minWidth: 140,
|
||||
rules: [{ required: true, message: '请选择申请有效期至', trigger: 'change' }],
|
||||
},
|
||||
@@ -274,7 +304,7 @@ export const option = {
|
||||
},
|
||||
...auditColumns.map(column => ({ ...column, hide: true })),
|
||||
]),
|
||||
dialogWidth: 1400,
|
||||
dialogWidth: '96%',
|
||||
menuFixed: 'right',
|
||||
menuWidth: 320,
|
||||
index: false,
|
||||
|
||||
@@ -605,6 +605,8 @@ export const option = {
|
||||
},
|
||||
])
|
||||
),
|
||||
// label 固定宽度(容纳 6 汉字),覆盖 createCrudOption 默认 labelWidth:'auto'
|
||||
labelWidth: 100,
|
||||
dialogWidth: '96%',
|
||||
dialogTop: '4vh',
|
||||
dialogCustomClass: 'transport-plan-dialog',
|
||||
|
||||
@@ -999,6 +999,8 @@ export const option = {
|
||||
},
|
||||
])
|
||||
),
|
||||
// label 固定宽度(容纳 6 汉字),覆盖 createCrudOption 默认 labelWidth:'auto'
|
||||
labelWidth: 100,
|
||||
dialogWidth: '96%',
|
||||
dialogTop: '4vh',
|
||||
menuWidth: 280,
|
||||
|
||||
@@ -13,7 +13,7 @@ export const preSettlementFormFields = [
|
||||
{ label: '结算类型', prop: 'settlementType', readonly: true },
|
||||
{ label: '结算金额', prop: 'settlementAmount', readonly: true, money: true },
|
||||
{ label: '汇率日期', prop: 'exchangeRateDate', type: 'date' },
|
||||
{ label: '结算汇率', prop: 'exchangeRate', type: 'number' },
|
||||
{ label: '结算汇率', prop: 'exchangeRate', type: 'number', class: 'exchange-rate-input' },
|
||||
{ label: '本位币合计', prop: 'localSettlementAmount', readonly: true, money: true },
|
||||
{ label: '创建人', prop: 'createUserName', readonly: true },
|
||||
{ label: '创建日期', prop: 'createTime', readonly: true },
|
||||
|
||||
@@ -42,11 +42,11 @@ export const tableColumns = [
|
||||
{ label: '运输类型', prop: 'transportType', minWidth: 120 },
|
||||
{ label: '货物名称', prop: 'cargoName', minWidth: 130 },
|
||||
{ label: '货物类型', prop: 'cargoType', minWidth: 120 },
|
||||
{ label: '运输总量', prop: 'transportQuantity', minWidth: 120, align: 'right' },
|
||||
{ label: '里程(KM)', prop: 'mileage', minWidth: 120, align: 'right' },
|
||||
{ label: '运输总量', prop: 'transportQuantity', minWidth: 120 },
|
||||
{ label: '里程(KM)', prop: 'mileage', minWidth: 120 },
|
||||
{ label: '批次号', prop: 'batchNo', minWidth: 120 },
|
||||
{ label: '运输单价', prop: 'unitPriceText', minWidth: 120, align: 'right' },
|
||||
{ label: '费用合计', prop: 'totalAmountText', minWidth: 130, align: 'right' },
|
||||
{ label: '运输单价', prop: 'unitPriceText', minWidth: 120 },
|
||||
{ label: '费用合计', prop: 'totalAmountText', minWidth: 130 },
|
||||
{ label: '状态', prop: 'settlementStatusName', minWidth: 120 },
|
||||
{ label: '创建人', prop: 'createUserName', minWidth: 120 },
|
||||
{ label: '创建时间', prop: 'createTime', minWidth: 170 },
|
||||
@@ -61,15 +61,16 @@ export const feeDetailBaseColumns = [
|
||||
{ label: '运费计费类型', prop: 'billingType', minWidth: 130 },
|
||||
{ label: '运输量', prop: 'transportQuantityText', minWidth: 120 },
|
||||
{ label: '运费计算单位', prop: 'priceUnit', minWidth: 130 },
|
||||
{ label: '运输单价', prop: 'unitPrice', minWidth: 120, align: 'right' },
|
||||
{ label: '里程(KM)', prop: 'mileage', minWidth: 120, align: 'right' },
|
||||
{ label: '运输费', prop: 'freightAmount', minWidth: 120, align: 'right' },
|
||||
{ label: '运输单价', prop: 'unitPrice', minWidth: 120 },
|
||||
{ label: '里程(KM)', prop: 'mileage', minWidth: 120 },
|
||||
{ label: '运输费', prop: 'freightAmount', minWidth: 180 }
|
||||
|
||||
];
|
||||
|
||||
export const feeDetailTailColumns = [
|
||||
{ label: '原总金额', prop: 'originalAmountText', minWidth: 120, align: 'right' },
|
||||
{ label: '调整金额', prop: 'adjustAmountText', minWidth: 120, align: 'right' },
|
||||
{ label: '调整后总金额', prop: 'afterAmountText', minWidth: 140, align: 'right' },
|
||||
{ label: '原总金额', prop: 'originalAmountText', minWidth: 120 },
|
||||
{ label: '调整金额', prop: 'adjustAmountText', minWidth: 120 },
|
||||
{ label: '调整后总金额', prop: 'afterAmountText', minWidth: 140 },
|
||||
{ label: '备注', prop: 'remark', minWidth: 160 },
|
||||
{ label: '最后录入人', prop: 'updateUserName', minWidth: 120 },
|
||||
{ label: '最后录入时间', prop: 'updateTime', minWidth: 170 },
|
||||
@@ -116,10 +117,10 @@ export const generateWaybillColumns = [
|
||||
{ label: '发货联系人', prop: 'departureContact', minWidth: 130 },
|
||||
{ label: '到货地址', prop: 'arrivalAddress', minWidth: 220 },
|
||||
{ label: '收货联系人', prop: 'arrivalContact', minWidth: 130 },
|
||||
{ label: '单价', prop: 'unitPrice', minWidth: 110, align: 'right' },
|
||||
{ label: '运费', prop: 'freight', minWidth: 110, align: 'right' },
|
||||
{ label: '其他费用合计', prop: 'otherFeeTotal', minWidth: 140, align: 'right' },
|
||||
{ label: '运费合计', prop: 'freightTotal', minWidth: 120, align: 'right' },
|
||||
{ label: '单价', prop: 'unitPrice', minWidth: 110 },
|
||||
{ label: '运费', prop: 'freight', minWidth: 110 },
|
||||
{ label: '其他费用合计', prop: 'otherFeeTotal', minWidth: 140 },
|
||||
{ label: '运费合计', prop: 'freightTotal', minWidth: 120 },
|
||||
{ label: '客户合同', prop: 'contractName', minWidth: 160 },
|
||||
{ label: '发货计划', prop: 'planName', minWidth: 140 },
|
||||
{ label: '运输批次', prop: 'batchNo', minWidth: 140 },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const settlementAdjustmentFormFields = [
|
||||
{ label: '单据号', prop: 'adjustmentNo' },
|
||||
{ label: '* 关联结算单号', prop: 'formalSettlementId' },
|
||||
{ label: '关联结算单号', prop: 'formalSettlementId' },
|
||||
{ label: '客户/客商名称', prop: 'customerName' },
|
||||
{ label: '结算单类型', prop: 'settlementTypeName' },
|
||||
{ label: '关联合同名称', prop: 'contractName' },
|
||||
|
||||
+27
-24
@@ -37,7 +37,7 @@
|
||||
}
|
||||
|
||||
.el-col {
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.el-main {
|
||||
@@ -510,6 +510,24 @@
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
// 发货模板 label 固定宽度(option labelWidth:100 容纳 6 汉字),超出自动换行
|
||||
.shipping-template-dialog .el-form-item__label {
|
||||
white-space: normal;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
// 运输计划 label 固定宽度(option labelWidth:100 容纳 6 汉字),超出自动换行
|
||||
.transport-plan-dialog .el-form-item__label {
|
||||
white-space: normal;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
// 运单管理 label 固定宽度(option labelWidth:100 容纳 6 汉字),超出自动换行
|
||||
.waybill-manage-dialog .el-form-item__label {
|
||||
white-space: normal;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
// 运输计划新增/编辑弹窗:参照 vehicle/customer-archive,弹窗体接近全屏(上下各留 20px 边距);
|
||||
// 同时覆盖 Avue 库内置 .avue-dialog 的 max-height: calc(100% - 200px) 上限,
|
||||
// 改由 flex 控制,底部操作栏(avue 内置 footer,渲染在 body 内部)sticky 贴底始终可见
|
||||
@@ -607,26 +625,11 @@
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
// 过程配置新增/编辑弹窗:avue-form 整体白卡透明化,
|
||||
// 让 <section-card> 分组白卡(基本信息 / 现行过程节点 / 节点设置)独立成卡、卡间露出灰底,
|
||||
// 与 business/project-apply 表单页的分组卡片风格统一
|
||||
.process-config-dialog .avue-form {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
// formslot 外层 el-form-item 默认 margin-bottom 与 section-card 自身 margin 叠加会拉大卡距,
|
||||
// 归零后卡间距统一为 section-card 自身的 12px(与 project-apply 一致)
|
||||
.process-config-dialog .avue-form__group > .el-col > .el-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
// 抵消全局 .avue-crud__dialog .avue-dialog__footer 的 -30px 上移
|
||||
// (avue-form 已透明化,footer 若上移会压住最后一张分组卡片)
|
||||
.process-config-dialog .avue-dialog__footer,
|
||||
.avue-crud__dialog .process-config-dialog .avue-dialog__footer {
|
||||
margin-top: 0 !important;
|
||||
// 过程配置新增/编辑/查看弹窗(手写 el-dialog,参照 vehicle/credit-score-quantification):
|
||||
// 灰底弹窗体(全站 .el-dialog__body 已统一)内堆叠 <section-card> 分组白卡,
|
||||
// 卡间 12px 间距由 section-card 自身 margin-bottom 保证,与项目其他弹窗风格统一
|
||||
.process-config-dialog .el-dialog__body {
|
||||
max-height: calc(100vh - 170px);
|
||||
}
|
||||
|
||||
// 统一表格线条颜色
|
||||
@@ -989,6 +992,6 @@
|
||||
.el-form-item--default {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
//.el-form-item {
|
||||
// margin-bottom: 15px !important;
|
||||
//}
|
||||
|
||||
@@ -1012,7 +1012,7 @@ export default {
|
||||
}
|
||||
|
||||
.el-input:first-child {
|
||||
flex: 0 0 34%;
|
||||
flex: 0 0 42.5%;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
|
||||
@@ -20,16 +20,28 @@
|
||||
<template v-for="(route, index) in routes" :key="route.segmentNo">
|
||||
<div class="route-overview__node">
|
||||
<span :class="['route-badge', index === 0 ? 'start' : 'middle']">{{ index === 0 ? '起' : '经' }}</span>
|
||||
<strong>{{ route.departureName || '-' }}</strong>
|
||||
<small>{{ route.departureAddress || '-' }}</small>
|
||||
<small>{{ contactText(route.departureContact, route.departurePhone) }}</small>
|
||||
<el-tooltip :content="route.departureName || '-'" placement="top" :show-after="120">
|
||||
<strong>{{ route.departureName || '-' }}</strong>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="route.departureAddress || '-'" placement="top" :show-after="120">
|
||||
<small>{{ route.departureAddress || '-' }}</small>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="contactText(route.departureContact, route.departurePhone)" placement="top" :show-after="120">
|
||||
<small>{{ contactText(route.departureContact, route.departurePhone) }}</small>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="route-overview__line"></div>
|
||||
<div v-if="index === routes.length - 1" class="route-overview__node">
|
||||
<span class="route-badge end">终</span>
|
||||
<strong>{{ route.arrivalName || '-' }}</strong>
|
||||
<small>{{ route.arrivalAddress || '-' }}</small>
|
||||
<small>{{ contactText(route.arrivalContact, route.arrivalPhone) }}</small>
|
||||
<el-tooltip :content="route.arrivalName || '-'" placement="top" :show-after="120">
|
||||
<strong>{{ route.arrivalName || '-' }}</strong>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="route.arrivalAddress || '-'" placement="top" :show-after="120">
|
||||
<small>{{ route.arrivalAddress || '-' }}</small>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="contactText(route.arrivalContact, route.arrivalPhone)" placement="top" :show-after="120">
|
||||
<small>{{ contactText(route.arrivalContact, route.arrivalPhone) }}</small>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -677,10 +689,10 @@ export default {
|
||||
.overview-content { display: grid; grid-template-columns: minmax(400px, .9fr) minmax(620px, 1.6fr); gap: 28px; padding: 8px 24px 20px; }
|
||||
.overview-meta { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px 24px; margin: 0; dt { margin-bottom: 6px; color: #909399; font-size: 13px; } dd { margin: 0; color: #409eff; font-size: 14px; word-break: break-all; } }
|
||||
.overview-meta dd.overview-meta__plain-value { color: #303133; }
|
||||
.route-overview { display: flex; align-items: flex-start; justify-content: flex-end; padding-top: 8px; overflow-x: auto; }
|
||||
.route-overview__node { display: grid; flex: 0 0 130px; justify-items: center; gap: 6px; text-align: center; strong { font-size: 16px; white-space: nowrap; } small { color: #606266; white-space: nowrap; } }
|
||||
.route-overview { display: flex; align-items: flex-start; justify-content: flex-start; padding: 8px 24px 0; overflow-x: auto; }
|
||||
.route-overview__node { display: grid; flex: 0 0 auto; min-width: 130px; max-width: 200px; justify-items: center; gap: 6px; text-align: center; padding: 0 4px; strong { font-size: 16px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } small { color: #606266; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } }
|
||||
.route-badge { display: inline-flex; width: 32px; height: 32px; align-items: center; justify-content: center; border-radius: 4px; background: #67c23a; color: #fff; font-weight: 600; &.start { background: #409eff; } &.end { background: #e6a23c; } }
|
||||
.route-overview__line { flex: 1 0 56px; min-width: 56px; height: 32px; margin-top: 0; border-bottom: 6px solid #e4e7ed; }
|
||||
.route-overview__line { flex: 0 1 56px; min-width: 24px; height: 32px; margin-top: 0; border-bottom: 6px solid #e4e7ed; }
|
||||
.segment-header { min-height: 46px; padding: 0 20px; border-bottom: 1px solid #eff1f7; font-weight: 600; em { color: #409eff; font-style: normal; } }
|
||||
.segment-content { padding: 16px 24px; }
|
||||
.dispatch-form { :deep(.el-form-item) { margin-bottom: 16px; } :deep(.el-input), :deep(.el-select), :deep(.el-date-editor), :deep(.el-input-number) { width: 100%; } }
|
||||
@@ -705,4 +717,7 @@ export default {
|
||||
.table-actions { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
@media screen and (max-width: 1200px) { .overview-content { grid-template-columns: 1fr; } .route-overview { justify-content: flex-start; } }
|
||||
@media screen and (max-width: 992px) { .dispatch-bottom { left: 0; width: 100%; } }
|
||||
.route-overview {
|
||||
margin-top: -30px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1752,7 +1752,7 @@ export default {
|
||||
font-size: 16px;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
.goods-heading {
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
<div class="dialog-section-title">基本信息</div>
|
||||
<el-row :gutter="28">
|
||||
<el-col :span="24"><el-form-item label="变更类型"><el-radio-group v-model="form.changeType"><el-radio label="合同信息变更" /><el-radio label="终止合同" /></el-radio-group></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="合同期限"><el-date-picker v-model="period" type="daterange" value-format="YYYY-MM-DD" range-separator="至" /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="一式"><div class="inline-field"><el-input-number v-model="form.copyCount" :min="1" controls-position="right" /><span>份</span></div></el-form-item></el-col>
|
||||
<el-col :span="8"><el-form-item label="回款账期"><el-input-number v-model="form.paymentDays" :min="0" controls-position="right" /><span class="unit">天</span></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同期限"><el-date-picker v-model="period" type="daterange" value-format="YYYY-MM-DD" range-separator="至" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="一式"><div class="inline-field"><el-input-number v-model="form.copyCount" :min="1" controls-position="right" /><span>份</span></div></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="回款账期"><el-input-number v-model="form.paymentDays" :min="0" controls-position="right" /><span class="unit">天</span></el-form-item></el-col>
|
||||
<el-col :span="24"><el-form-item label="备注"><el-input v-model="form.remark" type="textarea" maxlength="2000" show-word-limit /></el-form-item></el-col>
|
||||
</el-row>
|
||||
</section>
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
v-model="form"
|
||||
ref="crud"
|
||||
:permission="permissionList"
|
||||
:before-open="beforeOpen"
|
||||
@row-save="rowSave"
|
||||
@row-update="rowUpdate"
|
||||
@row-del="rowDel"
|
||||
@search-change="searchChange"
|
||||
@search-reset="searchReset"
|
||||
@@ -25,7 +22,7 @@
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
v-if="hasPermission('process_config_add')"
|
||||
@click="$refs.crud.rowAdd()"
|
||||
@click="openConfig()"
|
||||
>新建过程配置
|
||||
</el-button>
|
||||
<el-button
|
||||
@@ -46,27 +43,6 @@
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<template #menu-form-before="{ disabled }">
|
||||
<template v-if="!dialogReadonly">
|
||||
<el-button
|
||||
plain
|
||||
:loading="disabled"
|
||||
:disabled="disabled"
|
||||
@click="handleProcessConfigSave('draft')"
|
||||
>
|
||||
保存草稿
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="disabled"
|
||||
:disabled="disabled"
|
||||
@click="handleProcessConfigSave('enabled')"
|
||||
>
|
||||
保存并启用
|
||||
</el-button>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template #status="{ row }">
|
||||
<el-tag :type="statusTagType(row.status)">
|
||||
{{ row.statusName || displayStatus(row.status) }}
|
||||
@@ -79,300 +55,18 @@
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #basicInfo-form>
|
||||
<section-card title="基本信息">
|
||||
<el-form
|
||||
:model="form"
|
||||
label-position="right"
|
||||
label-width="calc(6em + 24px)"
|
||||
>
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="配置名称" required>
|
||||
<el-input
|
||||
v-model="form.configName"
|
||||
:disabled="dialogReadonly"
|
||||
maxlength="100"
|
||||
placeholder="请输入"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="项目" required>
|
||||
<el-select
|
||||
v-model="selectedProjectId"
|
||||
clearable
|
||||
filterable
|
||||
remote
|
||||
:remote-method="loadProjectOptions"
|
||||
:loading="projectLoading"
|
||||
:disabled="dialogReadonly"
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
@change="handleProjectChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in projectOptions"
|
||||
:key="item.id"
|
||||
:label="formatProjectLabel(item)"
|
||||
:value="String(item.id)"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="运输完成时限">
|
||||
<div class="process-config-page__finish-days">
|
||||
<span>默认</span>
|
||||
<el-input
|
||||
v-model="form.defaultFinishDays"
|
||||
:disabled="dialogReadonly"
|
||||
maxlength="3"
|
||||
placeholder="请输入"
|
||||
@input="handleFinishDaysInput"
|
||||
/>
|
||||
<span>天后完成运输</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注">
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
:disabled="dialogReadonly"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
placeholder="请输入"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</section-card>
|
||||
</template>
|
||||
|
||||
<template #nodeConfigJson-form>
|
||||
<div class="process-config-page__custom-form">
|
||||
<section-card title="现行过程节点">
|
||||
<div class="process-config-page__timeline" v-if="enabledNodes.length">
|
||||
<div class="process-config-page__timeline-line"></div>
|
||||
<div
|
||||
v-for="node in enabledNodes"
|
||||
:key="node.key"
|
||||
class="process-config-page__timeline-item"
|
||||
>
|
||||
<span class="process-config-page__timeline-dot"></span>
|
||||
<div class="process-config-page__timeline-name">{{ node.name }}</div>
|
||||
<div class="process-config-page__timeline-desc">
|
||||
<div v-for="text in timelineDescriptions(node)" :key="text">{{ text }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" />
|
||||
</section-card>
|
||||
|
||||
<section-card title="节点设置">
|
||||
<el-table
|
||||
class="process-config-page__node-table"
|
||||
border
|
||||
:data="nodeRows"
|
||||
:span-method="nodeSpanMethod"
|
||||
>
|
||||
<el-table-column label="节点设置" width="136">
|
||||
<template #default="{ row, $index }">
|
||||
<div class="process-config-page__node-cell">
|
||||
<el-checkbox
|
||||
v-model="row.enabled"
|
||||
:disabled="dialogReadonly"
|
||||
@change="syncNodeFields"
|
||||
/>
|
||||
<span class="process-config-page__node-name">{{ row.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作要求" min-width="660">
|
||||
<template #default="{ row }">
|
||||
<div class="process-config-page__requirements">
|
||||
<template v-if="row.key === 'accept'">
|
||||
<div class="process-config-page__require-line">
|
||||
<span class="process-config-page__require-label">是否确认</span>
|
||||
<el-radio-group
|
||||
v-model="row.confirmMode"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio label="yes">是</el-radio>
|
||||
<el-radio label="no_confirm_accept">无需确认接单</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-page__require-line">
|
||||
<span class="process-config-page__require-label">确认接单人</span>
|
||||
<el-checkbox
|
||||
v-model="row.confirmDriver"
|
||||
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
|
||||
@change="syncNodeFields"
|
||||
>司机</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="row.key === 'return'">
|
||||
<div class="process-config-page__require-line">
|
||||
<span class="process-config-page__require-label">是否确认</span>
|
||||
<el-radio-group
|
||||
v-model="row.confirmMode"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="handleReturnConfirmChange(row)"
|
||||
>
|
||||
<el-radio label="yes">是</el-radio>
|
||||
<el-radio label="no_confirm_complete">无需确认完成</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-page__require-line">
|
||||
<span class="process-config-page__require-label">确认完成</span>
|
||||
<el-checkbox
|
||||
v-model="row.confirmInternal"
|
||||
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
|
||||
@change="syncNodeFields"
|
||||
>内部人员</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div class="process-config-page__require-grid">
|
||||
<div class="process-config-page__require-line">
|
||||
<span class="process-config-page__require-label">是否打卡</span>
|
||||
<el-radio-group
|
||||
v-model="row.punch"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-page__require-line" v-if="row.supportCargo">
|
||||
<span class="process-config-page__require-label">上传货量</span>
|
||||
<el-radio-group
|
||||
v-model="row.uploadCargo"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div
|
||||
class="process-config-page__require-line process-config-page__require-line--wide"
|
||||
v-if="row.key === 'transit'"
|
||||
>
|
||||
<span class="process-config-page__require-label">打卡频次,每</span>
|
||||
<el-input
|
||||
v-model="row.frequencyDays"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.punch"
|
||||
maxlength="3"
|
||||
@input="value => handleFrequencyInput(row, value)"
|
||||
/>
|
||||
<span>天打卡1次</span>
|
||||
</div>
|
||||
<div class="process-config-page__require-line">
|
||||
<span class="process-config-page__require-label">打卡定位</span>
|
||||
<el-radio-group
|
||||
v-model="row.location"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.punch"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-page__require-line" v-if="row.supportCargo">
|
||||
<span class="process-config-page__require-label">上传货量类型</span>
|
||||
<el-checkbox-group
|
||||
v-model="row.cargoTypes"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.uploadCargo"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-checkbox label="重量">重量</el-checkbox>
|
||||
<el-checkbox label="体积">体积</el-checkbox>
|
||||
<el-checkbox label="数量">数量</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div
|
||||
class="process-config-page__require-line process-config-page__require-line--wide"
|
||||
v-if="row.key === 'transit'"
|
||||
>
|
||||
<span class="process-config-page__require-label">打卡时段</span>
|
||||
<el-time-picker
|
||||
v-model="row.timeStart"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.punch"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
placeholder="开始"
|
||||
/>
|
||||
<span>-</span>
|
||||
<el-time-picker
|
||||
v-model="row.timeEnd"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.punch"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
placeholder="结束"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件要求" min-width="320">
|
||||
<template #default="{ row }">
|
||||
<div class="process-config-page__attachments" v-if="row.supportVoucher">
|
||||
<div class="process-config-page__require-line">
|
||||
<span class="process-config-page__require-label">上传凭证</span>
|
||||
<el-radio-group
|
||||
v-model="row.uploadVoucher"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-page__require-line">
|
||||
<span class="process-config-page__require-label">凭证类型</span>
|
||||
<el-checkbox-group
|
||||
v-model="row.voucherTypes"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.uploadVoucher"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-checkbox v-for="item in row.voucherOptions" :key="item" :label="item">
|
||||
{{ item }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #menu="{ row, index }">
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="hasPermission('process_config_view')"
|
||||
@click="$refs.crud.rowView(row, index)"
|
||||
@click="openConfig(row, true)"
|
||||
>
|
||||
查看
|
||||
</el-link>
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="canEdit(row)"
|
||||
@click="$refs.crud.rowEdit(row, index)"
|
||||
@click="openConfig(row)"
|
||||
>
|
||||
编辑
|
||||
</el-link>
|
||||
@@ -407,6 +101,311 @@
|
||||
</template>
|
||||
</avue-crud>
|
||||
|
||||
<el-dialog
|
||||
:title="dialogReadonly ? '查看过程配置' : form.id ? '编辑过程配置' : '新建过程配置'"
|
||||
append-to-body
|
||||
v-model="configBox"
|
||||
width="96%"
|
||||
top="4vh"
|
||||
class="process-config-dialog"
|
||||
:close-on-click-modal="false"
|
||||
@closed="handleDialogClosed"
|
||||
>
|
||||
<div class="process-config-form">
|
||||
<section-card title="基本信息">
|
||||
<el-form
|
||||
:model="form"
|
||||
label-position="right"
|
||||
label-width="calc(6em + 24px)"
|
||||
:disabled="dialogReadonly"
|
||||
>
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="配置名称" required>
|
||||
<el-input
|
||||
v-model="form.configName"
|
||||
maxlength="100"
|
||||
placeholder="请输入"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="项目" required>
|
||||
<el-select
|
||||
v-model="selectedProjectId"
|
||||
clearable
|
||||
filterable
|
||||
remote
|
||||
:remote-method="loadProjectOptions"
|
||||
:loading="projectLoading"
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
@change="handleProjectChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in projectOptions"
|
||||
:key="item.id"
|
||||
:label="formatProjectLabel(item)"
|
||||
:value="String(item.id)"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="运输完成时限">
|
||||
<div class="process-config-form__finish-days">
|
||||
<span>默认</span>
|
||||
<el-input
|
||||
v-model="form.defaultFinishDays"
|
||||
maxlength="3"
|
||||
placeholder="请输入"
|
||||
@input="handleFinishDaysInput"
|
||||
/>
|
||||
<span>天后完成运输</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注">
|
||||
<el-input
|
||||
v-model="form.remark"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
placeholder="请输入"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</section-card>
|
||||
|
||||
<section-card title="现行过程节点">
|
||||
<div class="process-config-form__timeline" v-if="enabledNodes.length">
|
||||
<div class="process-config-form__timeline-line"></div>
|
||||
<div
|
||||
v-for="node in enabledNodes"
|
||||
:key="node.key"
|
||||
class="process-config-form__timeline-item"
|
||||
>
|
||||
<span class="process-config-form__timeline-dot"></span>
|
||||
<div class="process-config-form__timeline-name">{{ node.name }}</div>
|
||||
<div class="process-config-form__timeline-desc">
|
||||
<div v-for="text in timelineDescriptions(node)" :key="text">{{ text }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" />
|
||||
</section-card>
|
||||
|
||||
<section-card title="节点设置">
|
||||
<el-table
|
||||
class="process-config-form__node-table"
|
||||
border
|
||||
:data="nodeRows"
|
||||
:span-method="nodeSpanMethod"
|
||||
>
|
||||
<el-table-column label="节点设置" width="136">
|
||||
<template #default="{ row }">
|
||||
<div class="process-config-form__node-cell">
|
||||
<el-checkbox
|
||||
v-model="row.enabled"
|
||||
:disabled="dialogReadonly"
|
||||
@change="syncNodeFields"
|
||||
/>
|
||||
<span class="process-config-form__node-name">{{ row.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作要求" min-width="660">
|
||||
<template #default="{ row }">
|
||||
<div class="process-config-form__requirements">
|
||||
<template v-if="row.key === 'accept'">
|
||||
<div class="process-config-form__require-line">
|
||||
<span class="process-config-form__require-label">是否确认</span>
|
||||
<el-radio-group
|
||||
v-model="row.confirmMode"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio label="yes">是</el-radio>
|
||||
<el-radio label="no_confirm_accept">无需确认接单</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-form__require-line">
|
||||
<span class="process-config-form__require-label">确认接单人</span>
|
||||
<el-checkbox
|
||||
v-model="row.confirmDriver"
|
||||
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
|
||||
@change="syncNodeFields"
|
||||
>司机</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="row.key === 'return'">
|
||||
<div class="process-config-form__require-line">
|
||||
<span class="process-config-form__require-label">是否确认</span>
|
||||
<el-radio-group
|
||||
v-model="row.confirmMode"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="handleReturnConfirmChange(row)"
|
||||
>
|
||||
<el-radio label="yes">是</el-radio>
|
||||
<el-radio label="no_confirm_complete">无需确认完成</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-form__require-line">
|
||||
<span class="process-config-form__require-label">确认完成</span>
|
||||
<el-checkbox
|
||||
v-model="row.confirmInternal"
|
||||
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
|
||||
@change="syncNodeFields"
|
||||
>内部人员</el-checkbox
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<div class="process-config-form__require-grid">
|
||||
<div class="process-config-form__require-line">
|
||||
<span class="process-config-form__require-label">是否打卡</span>
|
||||
<el-radio-group
|
||||
v-model="row.punch"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-form__require-line" v-if="row.supportCargo">
|
||||
<span class="process-config-form__require-label">上传货量</span>
|
||||
<el-radio-group
|
||||
v-model="row.uploadCargo"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div
|
||||
class="process-config-form__require-line process-config-form__require-line--wide"
|
||||
v-if="row.key === 'transit'"
|
||||
>
|
||||
<span class="process-config-form__require-label">打卡频次,每</span>
|
||||
<el-input
|
||||
v-model="row.frequencyDays"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.punch"
|
||||
maxlength="3"
|
||||
@input="value => handleFrequencyInput(row, value)"
|
||||
/>
|
||||
<span>天打卡1次</span>
|
||||
</div>
|
||||
<div class="process-config-form__require-line">
|
||||
<span class="process-config-form__require-label">打卡定位</span>
|
||||
<el-radio-group
|
||||
v-model="row.location"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.punch"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-form__require-line" v-if="row.supportCargo">
|
||||
<span class="process-config-form__require-label">上传货量类型</span>
|
||||
<el-checkbox-group
|
||||
v-model="row.cargoTypes"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.uploadCargo"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-checkbox label="重量">重量</el-checkbox>
|
||||
<el-checkbox label="体积">体积</el-checkbox>
|
||||
<el-checkbox label="数量">数量</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div
|
||||
class="process-config-form__require-line process-config-form__require-line--wide"
|
||||
v-if="row.key === 'transit'"
|
||||
>
|
||||
<span class="process-config-form__require-label">打卡时段</span>
|
||||
<el-time-picker
|
||||
v-model="row.timeStart"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.punch"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
placeholder="开始"
|
||||
/>
|
||||
<span>-</span>
|
||||
<el-time-picker
|
||||
v-model="row.timeEnd"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.punch"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
placeholder="结束"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件要求" min-width="320">
|
||||
<template #default="{ row }">
|
||||
<div class="process-config-form__attachments" v-if="row.supportVoucher">
|
||||
<div class="process-config-form__require-line">
|
||||
<span class="process-config-form__require-label">上传凭证</span>
|
||||
<el-radio-group
|
||||
v-model="row.uploadVoucher"
|
||||
:disabled="dialogReadonly || !row.enabled"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-radio :label="true">是</el-radio>
|
||||
<el-radio :label="false">否</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div class="process-config-form__require-line">
|
||||
<span class="process-config-form__require-label">凭证类型</span>
|
||||
<el-checkbox-group
|
||||
v-model="row.voucherTypes"
|
||||
:disabled="dialogReadonly || !row.enabled || !row.uploadVoucher"
|
||||
@change="syncNodeFields"
|
||||
>
|
||||
<el-checkbox v-for="item in row.voucherOptions" :key="item" :label="item">
|
||||
{{ item }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="configBox = false">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:loading="submitting"
|
||||
v-if="!dialogReadonly"
|
||||
@click="submitConfig('draft')"
|
||||
>
|
||||
保存草稿
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="submitting"
|
||||
v-if="!dialogReadonly"
|
||||
@click="submitConfig('enabled')"
|
||||
>
|
||||
保存并启用
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<empty-pagination
|
||||
:page="page"
|
||||
@size-change="sizeChange"
|
||||
@@ -507,6 +506,8 @@ export default {
|
||||
loading: true,
|
||||
data: [],
|
||||
dialogReadonly: false,
|
||||
configBox: false,
|
||||
submitting: false,
|
||||
projectOptions: [],
|
||||
projectLoading: false,
|
||||
selectedProjectId: '',
|
||||
@@ -518,7 +519,6 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
submitStatus: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -880,11 +880,6 @@ export default {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
stopSubmitLoading(loading) {
|
||||
if (typeof loading === 'function') {
|
||||
loading();
|
||||
}
|
||||
},
|
||||
needsDuplicateVoucherConfirm() {
|
||||
const signNode = this.nodeRows.find(item => item.key === 'sign');
|
||||
const returnNode = this.nodeRows.find(item => item.key === 'return');
|
||||
@@ -914,14 +909,45 @@ export default {
|
||||
}
|
||||
);
|
||||
},
|
||||
submitRow(row, done, loading, status = this.submitStatus) {
|
||||
this.submitStatus = 1;
|
||||
this.syncNodeFields();
|
||||
const submitRow = this.normalizeRow({ ...row, status });
|
||||
if (!this.validateRow(submitRow)) {
|
||||
this.stopSubmitLoading(loading);
|
||||
openConfig(row, readonly = false) {
|
||||
this.dialogReadonly = readonly;
|
||||
if (!row || !row.id) {
|
||||
this.form = {
|
||||
configName: '',
|
||||
projectIds: '',
|
||||
projectNames: '',
|
||||
defaultFinishDays: '',
|
||||
remark: '',
|
||||
status: 0,
|
||||
};
|
||||
this.selectedProjectId = '';
|
||||
this.resetNodeRows();
|
||||
this.configBox = true;
|
||||
return;
|
||||
}
|
||||
api.getDetail(row.id).then(res => {
|
||||
this.form = res.data.data || {};
|
||||
this.selectedProjectId = this.form.projectIds ? String(this.form.projectIds) : '';
|
||||
this.ensureSelectedProjectOption();
|
||||
this.parseNodeConfig(this.form);
|
||||
this.configBox = true;
|
||||
});
|
||||
},
|
||||
handleDialogClosed() {
|
||||
this.submitting = false;
|
||||
this.dialogReadonly = false;
|
||||
},
|
||||
submitConfig(mode) {
|
||||
if (this.submitting) return;
|
||||
this.syncNodeFields();
|
||||
const submitRow = this.normalizeRow({
|
||||
...this.form,
|
||||
status: mode === 'draft' ? 2 : 1,
|
||||
});
|
||||
if (!this.validateRow(submitRow)) {
|
||||
return;
|
||||
}
|
||||
this.submitting = true;
|
||||
this.checkEnabledProjectBeforeSubmit(submitRow)
|
||||
.then(exists => {
|
||||
if (exists) {
|
||||
@@ -932,9 +958,9 @@ export default {
|
||||
.then(() => this.confirmDuplicateVoucher())
|
||||
.then(() => api.submit(submitRow))
|
||||
.then(() => {
|
||||
this.configBox = false;
|
||||
this.onLoad(this.page);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
done();
|
||||
})
|
||||
.catch(error => {
|
||||
if (
|
||||
@@ -944,21 +970,11 @@ export default {
|
||||
) {
|
||||
window.console.log(error);
|
||||
}
|
||||
this.stopSubmitLoading(loading);
|
||||
})
|
||||
.finally(() => {
|
||||
this.submitting = false;
|
||||
});
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
this.submitRow(row, done, loading);
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
this.submitRow(row, done, loading);
|
||||
},
|
||||
handleProcessConfigSave(mode) {
|
||||
this.submitStatus = mode === 'draft' ? 2 : 1;
|
||||
if (this.$refs.crud && typeof this.$refs.crud.rowSave === 'function') {
|
||||
this.$refs.crud.rowSave();
|
||||
}
|
||||
},
|
||||
rowDel(row) {
|
||||
this.$confirm('确定将选择数据删除?', {
|
||||
confirmButtonText: '确定',
|
||||
@@ -1001,35 +1017,6 @@ export default {
|
||||
}
|
||||
this.selectionClear();
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.dialogReadonly = type === 'view';
|
||||
this.submitStatus = 1;
|
||||
if (type === 'add') {
|
||||
this.form = {
|
||||
configName: '',
|
||||
projectIds: '',
|
||||
projectNames: '',
|
||||
defaultFinishDays: '',
|
||||
remark: '',
|
||||
status: 0,
|
||||
};
|
||||
this.selectedProjectId = '';
|
||||
this.resetNodeRows();
|
||||
done();
|
||||
return;
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
api.getDetail(this.form.id).then(res => {
|
||||
this.form = res.data.data || {};
|
||||
this.selectedProjectId = this.form.projectIds ? String(this.form.projectIds) : '';
|
||||
this.ensureSelectedProjectOption();
|
||||
this.parseNodeConfig(this.form);
|
||||
done();
|
||||
});
|
||||
return;
|
||||
}
|
||||
done();
|
||||
},
|
||||
searchReset() {
|
||||
this.query = {};
|
||||
this.applyDefaultDeptSearch();
|
||||
@@ -1164,6 +1151,13 @@ export default {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
:deep(.avue-crud__header) {
|
||||
margin-top: 12px;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.process-config-form {
|
||||
&__finish-days {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1174,10 +1168,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
&__custom-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__timeline {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -1285,11 +1275,6 @@ export default {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
:deep(.avue-crud__header) {
|
||||
margin-top: 12px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
--el-table-border-color: #eff1f7;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
:model="form"
|
||||
:rules="formRules"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
label-width="150"
|
||||
class="project-apply-form"
|
||||
:disabled="dialogReadonly"
|
||||
>
|
||||
@@ -1964,7 +1964,7 @@ export default {
|
||||
|
||||
&__grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
column-gap: 24px;
|
||||
row-gap: 0;
|
||||
margin-bottom: 12px;
|
||||
@@ -1972,6 +1972,13 @@ export default {
|
||||
border-radius: 0 0 6px 6px;
|
||||
padding: 14px 16px 4px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
|
||||
|
||||
// label 固定宽度:可容纳 6 个汉字,超出自动换行(覆盖全局 min-width:160px 与 auto 行内宽度)
|
||||
:deep(.el-form-item__label) {
|
||||
width: 108px !important;
|
||||
min-width: 0 !important;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
&__picker-icon {
|
||||
|
||||
@@ -364,7 +364,7 @@
|
||||
:before-close="beforeProgressDialogClose"
|
||||
@opened="loadProgress"
|
||||
>
|
||||
<section class="voucher-manage-page__progress-search">
|
||||
<section-card class="voucher-manage-page__progress-search">
|
||||
<el-form :model="progressQuery" label-position="right" label-width="160px"
|
||||
><div class="voucher-manage-page__search-grid">
|
||||
<el-form-item label="凭证批次号"
|
||||
@@ -391,7 +391,7 @@
|
||||
</div>
|
||||
</div></el-form
|
||||
>
|
||||
</section>
|
||||
</section-card>
|
||||
<el-table :data="progressRows" border class="voucher-manage-page__table"
|
||||
><el-table-column type="selection" width="52" /><el-table-column
|
||||
type="index"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
label-width="auto"
|
||||
>
|
||||
<el-row :gutter="24">
|
||||
<el-col v-for="field in fields" :key="field.prop" :span="8">
|
||||
<el-col v-for="field in fields" :key="field.prop" :span="6">
|
||||
<el-form-item :label="field.label" :prop="field.prop">
|
||||
<el-date-picker
|
||||
v-if="field.type === 'date' && editable"
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
<template>
|
||||
<div class="fs-table-panel">
|
||||
<div class="fs-table-panel__toolbar">
|
||||
<div>
|
||||
<el-button
|
||||
v-if="hasPermission('formal_settlement_add')"
|
||||
type="primary"
|
||||
@click="$emit('create')"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('formal_settlement_payment')"
|
||||
type="primary"
|
||||
plain
|
||||
disabled
|
||||
@click="$emit('payment')"
|
||||
>付款申请</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('formal_settlement_sync')"
|
||||
type="primary"
|
||||
plain
|
||||
disabled
|
||||
@click="$emit('sync')"
|
||||
>同步金蝶</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('formal_settlement_print')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="emitSingle('print')"
|
||||
>打印结算单</el-button
|
||||
>
|
||||
<el-button
|
||||
v-if="hasPermission('formal_settlement_export')"
|
||||
type="primary"
|
||||
plain
|
||||
@click="$emit('export')"
|
||||
>导出</el-button
|
||||
>
|
||||
</div>
|
||||
<div class="fs-table-panel__toolbar-right">
|
||||
<el-tooltip content="刷新" placement="top">
|
||||
<el-button :icon="Refresh" text @click="$emit('refresh')" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="rows"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link v-if="column.link && row[column.prop]" type="primary" @click="emitAction('view', row)">{{
|
||||
row[column.prop]
|
||||
}}</el-link>
|
||||
<el-tag v-else-if="column.status" :type="statusType(row.approvalStatus)">{{
|
||||
displayValue(row[column.prop])
|
||||
}}</el-tag>
|
||||
<span v-else-if="column.money">{{ formatMoney(row[column.prop], row.currency) }}</span>
|
||||
<span v-else-if="column.prop === 'invoiceStatusName'">{{
|
||||
invoiceName(row.invoiceStatus)
|
||||
}}</span>
|
||||
<span v-else-if="column.prop === 'paymentStatusName'">{{
|
||||
paymentName(row.paymentStatus)
|
||||
}}</span>
|
||||
<span v-else>{{ displayValue(row[column.prop]) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" fixed="right" align="center">
|
||||
<template #default="{ row }"
|
||||
><div class="fs-table-panel__links">
|
||||
<el-link
|
||||
v-for="action in rowActions(row)"
|
||||
:key="action.type"
|
||||
:type="action.danger ? 'danger' : 'primary'"
|
||||
@click="emitAction(action.type, row)"
|
||||
>{{ action.label }}</el-link
|
||||
>
|
||||
</div></template
|
||||
>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="fs-table-panel__pagination">
|
||||
<el-pagination
|
||||
:current-page="page.current"
|
||||
:page-size="page.size"
|
||||
:total="page.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="current => $emit('page-change', { current, size: page.size })"
|
||||
@size-change="size => $emit('page-change', { current: 1, size })"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Refresh } from '@element-plus/icons-vue';
|
||||
import {
|
||||
invoiceStatusOptions,
|
||||
paymentStatusOptions,
|
||||
} from '@/option/settlement/formalSettlementSearch';
|
||||
|
||||
export default {
|
||||
name: 'FormalSettlementTablePanel',
|
||||
props: {
|
||||
rows: { type: Array, default: () => [] },
|
||||
columns: { type: Array, default: () => [] },
|
||||
loading: { type: Boolean, default: false },
|
||||
page: { type: Object, required: true },
|
||||
hasPermission: { type: Function, required: true },
|
||||
},
|
||||
emits: ['create', 'payment', 'sync', 'print', 'export', 'refresh', 'page-change', 'action'],
|
||||
data() {
|
||||
return {
|
||||
Refresh,
|
||||
selection: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSelectionChange(value) {
|
||||
this.selection = value;
|
||||
this.$emit('update:selection', value);
|
||||
},
|
||||
emitAction(type, row) {
|
||||
this.$emit('action', { type, row });
|
||||
},
|
||||
emitSingle(type) {
|
||||
if (this.selection.length !== 1) {
|
||||
this.$message.warning(`${type === 'print' ? '打印' : '操作'}需选择一条正式结算单`);
|
||||
return;
|
||||
}
|
||||
this.$emit('action', { type, row: this.selection[0] });
|
||||
},
|
||||
isEditable(row) {
|
||||
return ['draft', 'returned'].includes(row.approvalStatus);
|
||||
},
|
||||
rowActions(row) {
|
||||
const actions = [];
|
||||
if (this.hasPermission('formal_settlement_view'))
|
||||
actions.push({ type: 'view', label: '查看' });
|
||||
if (this.hasPermission('formal_settlement_edit') && this.isEditable(row))
|
||||
actions.push({ type: 'edit', label: '编辑' });
|
||||
if (this.hasPermission('formal_settlement_delete') && row.approvalStatus === 'draft')
|
||||
actions.push({ type: 'delete', label: '删除', danger: true });
|
||||
if (this.hasPermission('formal_settlement_submit') && this.isEditable(row))
|
||||
actions.push({ type: 'submit', label: '提交' });
|
||||
if (this.hasPermission('formal_settlement_approve') && row.approvalStatus === 'reviewing') {
|
||||
actions.push({ type: 'approve', label: '通过' });
|
||||
actions.push({ type: 'return', label: '驳回', danger: true });
|
||||
}
|
||||
if (
|
||||
this.hasPermission('formal_settlement_void') &&
|
||||
row.approvalStatus === 'approved' &&
|
||||
row.kingdeeSyncStatus !== 'synced'
|
||||
)
|
||||
actions.push({ type: 'void', label: '作废', danger: true });
|
||||
return actions;
|
||||
},
|
||||
statusType(status) {
|
||||
return (
|
||||
{ approved: 'success', reviewing: 'warning', returned: 'danger', voided: 'info' }[status] ||
|
||||
''
|
||||
);
|
||||
},
|
||||
invoiceName(value) {
|
||||
return invoiceStatusOptions.find(item => item.value === value)?.label || value || '-';
|
||||
},
|
||||
paymentName(value) {
|
||||
return paymentStatusOptions.find(item => item.value === value)?.label || value || '-';
|
||||
},
|
||||
displayValue(value) {
|
||||
return value === null || value === undefined || value === '' ? '-' : value;
|
||||
},
|
||||
formatMoney(value, currency = 'RMB') {
|
||||
return `${Number(value || 0).toFixed(2)} ${currency || 'RMB'}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.fs-table-panel__toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.fs-table-panel__toolbar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.fs-table-panel__links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.fs-table-panel__pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
@@ -10,7 +10,7 @@
|
||||
label-width="auto"
|
||||
>
|
||||
<el-row :gutter="24">
|
||||
<el-col v-for="field in fields" :key="field.prop" :span="8"
|
||||
<el-col v-for="field in fields" :key="field.prop" :span="6"
|
||||
><el-form-item :label="field.label" :prop="field.prop"
|
||||
><el-select
|
||||
v-if="field.prop === 'formalSettlementId' && editable"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
label-width="auto"
|
||||
>
|
||||
<el-row :gutter="24">
|
||||
<el-col v-for="field in formFields" :key="field.prop" :span="8">
|
||||
<el-col v-for="field in formFields" :key="field.prop" :span="6">
|
||||
<el-form-item :label="field.label" :prop="field.prop">
|
||||
<el-input
|
||||
v-if="field.prop === 'formalSettlementNo' && editable"
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<div class="tr-table-panel">
|
||||
<div class="tr-table-panel__toolbar">
|
||||
<div>
|
||||
<el-button
|
||||
v-if="hasPermission('transport_reconciliation_add')"
|
||||
type="primary"
|
||||
@click="$emit('create')"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button type="primary" plain @click="$emit('export')">导出</el-button>
|
||||
</div>
|
||||
<div class="tr-table-panel__toolbar-right">
|
||||
<el-tooltip content="刷新" placement="top">
|
||||
<el-button :icon="Refresh" text @click="$emit('refresh')" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="rows"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link v-if="column.link" type="primary" @click="emitAction('view', row)">{{
|
||||
row[column.prop] || '-'
|
||||
}}</el-link>
|
||||
<span v-else-if="column.money">{{ formatMoney(row[column.prop], row.currency) }}</span>
|
||||
<el-tag
|
||||
v-else-if="column.prop === 'reconciliationStatusName'"
|
||||
:type="row.reconciliationStatus === 'completed' ? 'success' : 'warning'"
|
||||
>{{ row[column.prop] || '-' }}</el-tag
|
||||
>
|
||||
<span v-else>{{ displayValue(row[column.prop]) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="220" fixed="right" align="center">
|
||||
<template #default="{ row }"
|
||||
><div class="tr-table-panel__links">
|
||||
<el-link
|
||||
v-for="action in rowActions(row)"
|
||||
:key="action.type"
|
||||
:type="action.danger ? 'danger' : 'primary'"
|
||||
@click="emitAction(action.type, row)"
|
||||
>{{ action.label }}</el-link
|
||||
>
|
||||
</div></template
|
||||
>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="tr-table-panel__pagination">
|
||||
<el-pagination
|
||||
:current-page="page.current"
|
||||
:page-size="page.size"
|
||||
:total="page.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="current => $emit('page-change', { current, size: page.size })"
|
||||
@size-change="size => $emit('page-change', { current: 1, size })"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Refresh } from '@element-plus/icons-vue';
|
||||
|
||||
export default {
|
||||
name: 'TransportReconciliationTablePanel',
|
||||
props: {
|
||||
rows: { type: Array, default: () => [] },
|
||||
columns: { type: Array, default: () => [] },
|
||||
loading: { type: Boolean, default: false },
|
||||
page: { type: Object, required: true },
|
||||
hasPermission: { type: Function, required: true },
|
||||
},
|
||||
emits: ['create', 'export', 'refresh', 'page-change', 'update:selection', 'action'],
|
||||
data() {
|
||||
return {
|
||||
Refresh,
|
||||
selection: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSelectionChange(value) {
|
||||
this.selection = value;
|
||||
this.$emit('update:selection', value);
|
||||
},
|
||||
emitAction(type, row) {
|
||||
this.$emit('action', { type, row });
|
||||
},
|
||||
isEditable(row) {
|
||||
return row.reconciliationStatus === 'unfinished';
|
||||
},
|
||||
rowActions(row) {
|
||||
const actions = [{ type: 'view', label: '查看' }];
|
||||
if (this.hasPermission('transport_reconciliation_edit') && this.isEditable(row))
|
||||
actions.push({ type: 'edit', label: '编辑' });
|
||||
if (this.hasPermission('transport_reconciliation_delete') && this.isEditable(row))
|
||||
actions.push({ type: 'delete', label: '删除', danger: true });
|
||||
if (this.hasPermission('transport_reconciliation_complete') && this.isEditable(row))
|
||||
actions.push({ type: 'complete', label: '确认' });
|
||||
return actions;
|
||||
},
|
||||
displayValue(value) {
|
||||
return value === null || value === undefined || value === '' ? '-' : value;
|
||||
},
|
||||
formatMoney(value, currency = 'RMB') {
|
||||
return `${Number(value || 0).toFixed(2)} ${currency || 'RMB'}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tr-table-panel__toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.tr-table-panel__toolbar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.tr-table-panel__links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.tr-table-panel__pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
@@ -343,7 +343,6 @@ export default {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-height: 56px;
|
||||
padding: 12px;
|
||||
}
|
||||
&__toolbar-right {
|
||||
display: flex;
|
||||
|
||||
@@ -31,91 +31,43 @@
|
||||
</section>
|
||||
|
||||
<section class="reconciliation-page__table-panel">
|
||||
<div class="reconciliation-page__toolbar">
|
||||
<div>
|
||||
<el-button
|
||||
v-if="hasPermission('transport_reconciliation_add')"
|
||||
type="primary"
|
||||
@click="openCreate"
|
||||
>新增</el-button
|
||||
>
|
||||
<el-button type="primary" plain @click="handleExport">导出</el-button>
|
||||
</div>
|
||||
<div class="reconciliation-page__toolbar-right">
|
||||
<el-tooltip content="刷新" placement="top">
|
||||
<el-button :icon="Refresh" text @click="loadTable" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<el-tabs
|
||||
v-model="settlementType"
|
||||
class="reconciliation-page__settlement-tabs"
|
||||
type="card"
|
||||
type="border-card"
|
||||
@tab-change="handleTabChange"
|
||||
>
|
||||
<el-tab-pane label="应付" name="payable" />
|
||||
<el-tab-pane label="应收" name="receivable" />
|
||||
<el-tab-pane label="应付" name="payable">
|
||||
<transport-reconciliation-table-panel
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:page="page"
|
||||
:has-permission="hasPermission"
|
||||
@create="openCreate"
|
||||
@export="handleExport"
|
||||
@refresh="loadTable"
|
||||
@page-change="handlePageChange"
|
||||
@update:selection="selection = $event"
|
||||
@action="handleAction"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="应收" name="receivable">
|
||||
<transport-reconciliation-table-panel
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:page="page"
|
||||
:has-permission="hasPermission"
|
||||
@create="openCreate"
|
||||
@export="handleExport"
|
||||
@refresh="loadTable"
|
||||
@page-change="handlePageChange"
|
||||
@update:selection="selection = $event"
|
||||
@action="handleAction"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-table v-loading="loading" :data="rows" border @selection-change="selection = $event">
|
||||
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||
<el-table-column
|
||||
v-for="column in columns"
|
||||
:key="column.prop"
|
||||
v-bind="column"
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-link v-if="column.link" type="primary" @click="openView(row)">{{
|
||||
row[column.prop] || '-'
|
||||
}}</el-link>
|
||||
<span v-else-if="column.money">{{ formatMoney(row[column.prop], row.currency) }}</span>
|
||||
<el-tag
|
||||
v-else-if="column.prop === 'reconciliationStatusName'"
|
||||
:type="row.reconciliationStatus === 'completed' ? 'success' : 'warning'"
|
||||
>{{ row[column.prop] || '-' }}</el-tag
|
||||
>
|
||||
<span v-else>{{ displayValue(row[column.prop]) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="220" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="reconciliation-page__links">
|
||||
<el-link type="primary" @click="openView(row)">查看</el-link>
|
||||
<el-link
|
||||
v-if="hasPermission('transport_reconciliation_edit') && isEditable(row)"
|
||||
type="primary"
|
||||
@click="openEdit(row)"
|
||||
>编辑</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="hasPermission('transport_reconciliation_delete') && isEditable(row)"
|
||||
type="danger"
|
||||
@click="handleDelete(row)"
|
||||
>删除</el-link
|
||||
>
|
||||
<el-link
|
||||
v-if="hasPermission('transport_reconciliation_complete') && isEditable(row)"
|
||||
type="primary"
|
||||
@click="handleComplete(row)"
|
||||
>确认</el-link
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="reconciliation-page__pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="page.current"
|
||||
v-model:page-size="page.size"
|
||||
:total="page.total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="loadTable"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<transport-reconciliation-editor
|
||||
@@ -136,6 +88,7 @@ import * as api from '@/api/settlement/transportReconciliation';
|
||||
import { transportReconciliationSearchFields } from '@/option/settlement/transportReconciliationSearch';
|
||||
import { transportReconciliationTableColumns } from '@/option/settlement/transportReconciliationTable';
|
||||
import TransportReconciliationEditor from './components/transport-reconciliation-editor.vue';
|
||||
import TransportReconciliationTablePanel from './components/transport-reconciliation-table-panel.vue';
|
||||
|
||||
const emptyQuery = () => ({
|
||||
reconciliationNo: '',
|
||||
@@ -151,7 +104,7 @@ const emptyQuery = () => ({
|
||||
|
||||
export default {
|
||||
name: 'TransportReconciliation',
|
||||
components: { TransportReconciliationEditor },
|
||||
components: { TransportReconciliationEditor, TransportReconciliationTablePanel },
|
||||
data() {
|
||||
return {
|
||||
ArrowDown,
|
||||
@@ -210,10 +163,21 @@ export default {
|
||||
this.page.current = 1;
|
||||
this.loadTable();
|
||||
},
|
||||
handleSizeChange() {
|
||||
this.page.current = 1;
|
||||
handlePageChange({ current, size }) {
|
||||
this.page.current = current;
|
||||
this.page.size = size;
|
||||
this.loadTable();
|
||||
},
|
||||
handleAction({ type, row }) {
|
||||
const map = {
|
||||
view: this.openView,
|
||||
edit: this.openEdit,
|
||||
delete: this.handleDelete,
|
||||
complete: this.handleComplete,
|
||||
};
|
||||
const fn = map[type];
|
||||
if (fn) fn(row);
|
||||
},
|
||||
openCreate() {
|
||||
this.editor = { visible: true, id: null, readonly: false };
|
||||
},
|
||||
@@ -307,35 +271,12 @@ export default {
|
||||
.reconciliation-page__table-panel {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.reconciliation-page__toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-height: 56px;
|
||||
//padding: 12px;
|
||||
}
|
||||
.reconciliation-page__toolbar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.reconciliation-page__settlement-tabs {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.reconciliation-page__settlement-tabs :deep(.el-tabs__header) {
|
||||
margin: 0;
|
||||
}
|
||||
.reconciliation-page__links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.reconciliation-page__pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 12px;
|
||||
}
|
||||
.reconciliation-page :deep(.el-table) {
|
||||
--el-table-border-color: #eff1f7;
|
||||
background: #fff;
|
||||
|
||||
@@ -1601,5 +1601,7 @@ export default {
|
||||
color: #d40000;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 14px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -137,13 +137,13 @@
|
||||
:model="shipForm"
|
||||
:rules="formRules"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
label-width="100"
|
||||
:disabled="readonly"
|
||||
class="ship-form archive-form"
|
||||
>
|
||||
<section-card title="基础船舶信息">
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="船舶所属组织" prop="organizationName">
|
||||
<el-select
|
||||
v-model="shipForm.organizationName"
|
||||
@@ -160,12 +160,12 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="船名" prop="shipName">
|
||||
<el-input v-model="shipForm.shipName" maxlength="20" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="安放龙骨日期/建造完工日期" prop="keelLayingDate">
|
||||
<div class="date-range-inline">
|
||||
<el-date-picker
|
||||
@@ -186,7 +186,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="总长" prop="totalLength">
|
||||
<el-input
|
||||
v-model="shipForm.totalLength"
|
||||
@@ -196,7 +196,7 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="船宽" prop="shipWidth">
|
||||
<el-input
|
||||
v-model="shipForm.shipWidth"
|
||||
@@ -206,7 +206,7 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="型深" prop="moldedDepth">
|
||||
<el-input
|
||||
v-model="shipForm.moldedDepth"
|
||||
@@ -218,7 +218,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="最大船高" prop="maxShipHeight">
|
||||
<el-input
|
||||
v-model="shipForm.maxShipHeight"
|
||||
@@ -228,7 +228,7 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="空载吃水" prop="lightDraft">
|
||||
<el-input
|
||||
v-model="shipForm.lightDraft"
|
||||
@@ -238,7 +238,7 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="满载吃水" prop="fullLoadDraft">
|
||||
<el-input
|
||||
v-model="shipForm.fullLoadDraft"
|
||||
@@ -250,7 +250,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="航区" prop="navigationArea">
|
||||
<div class="navigation-area-field">
|
||||
<el-select v-model="shipForm.navigationArea" placeholder="请选择">
|
||||
@@ -1226,6 +1226,12 @@ export default {
|
||||
:deep(.el-input-number) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// label 固定宽度:可容纳 6 个汉字,超出自动换行
|
||||
:deep(.el-form-item__label) {
|
||||
white-space: normal;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.date-range-inline {
|
||||
@@ -1368,4 +1374,7 @@ export default {
|
||||
color: #d40000;
|
||||
font-weight: 600;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 14px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1536,4 +1536,8 @@ export default {
|
||||
color: #d40000;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 14px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1102,7 +1102,7 @@ export default {
|
||||
padding: 4px 0 6px;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 18px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
@@ -1141,7 +1141,7 @@ export default {
|
||||
column-gap: 112px;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 18px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1079,7 +1079,7 @@
|
||||
ref="scoreForm"
|
||||
:model="currentScore"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
label-width="150"
|
||||
:disabled="readonly"
|
||||
class="score-detail-form"
|
||||
>
|
||||
@@ -4416,8 +4416,8 @@ export default {
|
||||
flex-wrap: nowrap;
|
||||
|
||||
:deep(.el-date-editor) {
|
||||
flex: 0 0 150px;
|
||||
width: 150px;
|
||||
flex: 0 0 140px;
|
||||
width: 140px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -4501,7 +4501,7 @@ export default {
|
||||
padding: 8px 36px 0;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 18px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
@@ -4629,7 +4629,7 @@ export default {
|
||||
max-width: 620px;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-input) {
|
||||
@@ -4856,15 +4856,11 @@ export default {
|
||||
|
||||
.archive-page-form {
|
||||
min-height: 100%;
|
||||
//padding: 20px 24px 92px;
|
||||
//background: #fff;
|
||||
}
|
||||
|
||||
.archive-form__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
|
||||
.archive-page-form & {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
@@ -4901,4 +4897,10 @@ export default {
|
||||
max-height: 72vh;
|
||||
overflow: auto;
|
||||
}
|
||||
.el-col{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 14px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user