Compare commits
5
Commits
6bc9981ffc
...
c68ce66405
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c68ce66405 | ||
|
|
9948c8f33b | ||
|
|
2b4179f3cd | ||
|
|
bac0da2b5f | ||
|
|
9e5fbfd2d4 |
@@ -31,3 +31,16 @@
|
|||||||
3. option:将 `expireStatus` 列的 `search: true → search: false`(否则会在搜索网格里多渲染一个空输入框);`searchIndex` 设为 ≥ 真实搜索列数(vehicle: `4 → 6`;ship 已是 `6`),使 `columnLen ≤ searchIndex`,Avue 不再显示「展开」按钮。
|
3. option:将 `expireStatus` 列的 `search: true → search: false`(否则会在搜索网格里多渲染一个空输入框);`searchIndex` 设为 ≥ 真实搜索列数(vehicle: `4 → 6`;ship 已是 `6`),使 `columnLen ≤ searchIndex`,Avue 不再显示「展开」按钮。
|
||||||
- 原理:Avue `header-search3.js` 中 `#search-menu` 插槽内容渲染进 `menu-form`,位于默认搜索/重置按钮之后、展开按钮之前;`order: -1` 将标签推到按钮左侧。
|
- 原理:Avue `header-search3.js` 中 `#search-menu` 插槽内容渲染进 `menu-form`,位于默认搜索/重置按钮之后、展开按钮之前;`order: -1` 将标签推到按钮左侧。
|
||||||
- 验证:`node --check` 两个 option 文件通过;页面刷新即可见效果。
|
- 验证:`node --check` 两个 option 文件通过;页面刷新即可见效果。
|
||||||
|
|
||||||
|
## process-config.vue 弹窗重构为手写 el-dialog(对齐 customer-archive 风格)
|
||||||
|
|
||||||
|
- 需求:用户要求 `/business/process-config.vue` 排版风格改成和 `/vehicle/customer-archive.vue` 一样,保持风格统一。
|
||||||
|
- 根因:两页弹窗架构根本不同——customer-archive 用手写 `<el-dialog>` + `section-card` 分组 + `#footer` 按钮;process-config 原用 Avue 内置弹窗(`#basicInfo-form`/`#nodeConfigJson-form` 插槽 + `#menu-form-before` 保存按钮)。要真正统一,只能把 process-config 改成手写弹窗。
|
||||||
|
- 模板改动(已完成):
|
||||||
|
- 移除 avue-crud 的 `:before-open`/`@row-save`/`@row-update`/`@row-del` 与 `#menu-form-before`、`#basicInfo-form`、`#nodeConfigJson-form` 插槽。
|
||||||
|
- 在 `</avue-crud>` 后新增手写 `<el-dialog class="process-dialog" v-model="processBox" width="92%" top="4vh" append-to-body @closed="resetProcess">`,内部 `<el-form ref="processForm" :model="form" label-width="calc(6em + 24px)" :disabled="dialogReadonly" class="process-form dialog-form-label-fixed">`,含 3 个 `section-card`:基本信息 / 现行过程节点(时间线)/ 节点设置(节点表格);`#footer` 含 保存草稿(plain) + 保存并启用(primary) + 取消/关闭。
|
||||||
|
- 顶部「新建过程配置」、表格「查看/编辑」链接改调 `openProcessConfig()` / `openProcessConfig(row, true)` / `openProcessConfig(row, false)`。
|
||||||
|
- 脚本改动(本次完成):删除 Avue 生命周期方法 `beforeOpen/rowSave/rowUpdate/submitRow/stopSubmitLoading/handleProcessConfigSave`;新增 `openProcessConfig(row, readonly)`(load 详情后 `this.form=data` + `selectedProjectId` + `parseNodeConfig` + 开框;新增则清空表单 + `resetNodeRows`)、`submitProcessConfig(mode)`(`this.$refs.processForm.validate` → `syncNodeFields` → `normalizeRow` → `validateRow` → `confirmDuplicateVoucher` → `api.submit`,成功后关框并刷新)、`resetProcess()`(`@closed` 重置 `dialogReadonly/submitting/submitStatus/form/selectedProjectId` + `resetNodeRows` + `clearValidate`)。`data()` 已含 `processBox/submitting`、`computed.dialogTitle`;`rowDel`/`handleCopy`/`handleAction` 不变(独立 API 调用)。
|
||||||
|
- option 改动(已完成):`src/option/business/process-config.js` 置 `saveBtn/updateBtn/addBtn/viewBtn/editBtn/delBtn:false`,关闭 Avue 内置弹窗按钮。
|
||||||
|
- 样式:新增 `:deep(.process-dialog .el-dialog__body){max-height:72vh;overflow:auto}`,对齐 customer-archive 的 `.archive-dialog` 滚动行为(长内容时 body 滚动、footer 固定)。
|
||||||
|
- 验证:`vite build --outDir /tmp/pc-build-check` 全量编译通过(仅动态导入 chunk 警告,与本改动无关);之前 `npm run build` 失败仅因沙箱 safe-delete 守卫清理旧 dist/ 触发,非代码错误。
|
||||||
|
|||||||
@@ -177,6 +177,10 @@ export const option = {
|
|||||||
]),
|
]),
|
||||||
saveBtn: false,
|
saveBtn: false,
|
||||||
updateBtn: false,
|
updateBtn: false,
|
||||||
|
addBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
dialogTop: '10px',
|
dialogTop: '10px',
|
||||||
dialogWidth: '96%',
|
dialogWidth: '96%',
|
||||||
menuWidth: 220,
|
menuWidth: 220,
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ export const option = {
|
|||||||
value: 'projectName',
|
value: 'projectName',
|
||||||
},
|
},
|
||||||
filterable: true,
|
filterable: true,
|
||||||
span: 12,
|
span: 8,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
rules: textRule('项目名称', 100, true),
|
rules: textRule('项目名称', 100, true),
|
||||||
},
|
},
|
||||||
@@ -128,7 +128,7 @@ export const option = {
|
|||||||
prop: 'projectCode',
|
prop: 'projectCode',
|
||||||
hide: true,
|
hide: true,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
span: 12,
|
span: 8,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
rules: textRule('项目编号', 50),
|
rules: textRule('项目编号', 50),
|
||||||
},
|
},
|
||||||
@@ -137,7 +137,7 @@ export const option = {
|
|||||||
prop: 'undertakeDeptName',
|
prop: 'undertakeDeptName',
|
||||||
hide: true,
|
hide: true,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
span: 12,
|
span: 8,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
rules: textRule('承办部门', 50, true),
|
rules: textRule('承办部门', 50, true),
|
||||||
},
|
},
|
||||||
@@ -146,7 +146,7 @@ export const option = {
|
|||||||
prop: 'projectFundLimit',
|
prop: 'projectFundLimit',
|
||||||
hide: true,
|
hide: true,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
span: 12,
|
span: 8,
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
rules: [nonNegativeRule('项目资金使用额度')],
|
rules: [nonNegativeRule('项目资金使用额度')],
|
||||||
},
|
},
|
||||||
@@ -155,7 +155,7 @@ export const option = {
|
|||||||
prop: 'usedFundLimit',
|
prop: 'usedFundLimit',
|
||||||
hide: true,
|
hide: true,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
span: 12,
|
span: 8,
|
||||||
minWidth: 220,
|
minWidth: 220,
|
||||||
value: 0,
|
value: 0,
|
||||||
rules: [nonNegativeRule('已使用项目资金额度')],
|
rules: [nonNegativeRule('已使用项目资金额度')],
|
||||||
@@ -165,7 +165,7 @@ export const option = {
|
|||||||
prop: 'remainingFundLimit',
|
prop: 'remainingFundLimit',
|
||||||
hide: true,
|
hide: true,
|
||||||
disabled: true,
|
disabled: true,
|
||||||
span: 12,
|
span: 8,
|
||||||
minWidth: 230,
|
minWidth: 230,
|
||||||
value: 0,
|
value: 0,
|
||||||
rules: [nonNegativeRule('剩余项目资金使用额度')],
|
rules: [nonNegativeRule('剩余项目资金使用额度')],
|
||||||
@@ -174,7 +174,7 @@ export const option = {
|
|||||||
label: '申请临时额度(万元)',
|
label: '申请临时额度(万元)',
|
||||||
prop: 'applyLimit',
|
prop: 'applyLimit',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
span: 12,
|
span: 8,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入申请临时额度', trigger: 'blur' },
|
{ required: true, message: '请输入申请临时额度', trigger: 'blur' },
|
||||||
@@ -187,7 +187,7 @@ export const option = {
|
|||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
span: 12,
|
span: 8,
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
rules: [{ required: true, message: '请选择申请有效期至', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择申请有效期至', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -806,3 +806,16 @@
|
|||||||
.el-form-item__label {
|
.el-form-item__label {
|
||||||
margin-left: 12px !important;
|
margin-left: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-form-item--default .el-form-item__label {
|
||||||
|
line-height: 14px;
|
||||||
|
}
|
||||||
|
.el-form-item--label-right .el-form-item__label {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.el-form-item--default {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
.el-form-item {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13681,7 +13681,7 @@ export default {
|
|||||||
min-width: 56px;
|
min-width: 56px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
margin: 0 14px;
|
margin: 0 14px;
|
||||||
border-bottom: 3px solid #303133;
|
border-bottom: 4px solid #e4e7ed;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__transport-plan-waybill-card {
|
&__transport-plan-waybill-card {
|
||||||
@@ -13859,9 +13859,9 @@ export default {
|
|||||||
&::before {
|
&::before {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
order: 2;
|
order: 2;
|
||||||
height: 2px;
|
height: 4px;
|
||||||
content: '';
|
content: '';
|
||||||
background: #606266;
|
background: #e4e7ed;
|
||||||
}
|
}
|
||||||
|
|
||||||
b.end {
|
b.end {
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export default {
|
|||||||
.route-map__node { display: grid; flex: 0 0 150px; justify-items: center; gap: 6px; text-align: center; strong { font-size: 16px; white-space: nowrap; } small { color: #606266; white-space: nowrap; } }
|
.route-map__node { display: grid; flex: 0 0 150px; justify-items: center; gap: 6px; text-align: center; strong { font-size: 16px; white-space: nowrap; } small { color: #606266; white-space: nowrap; } }
|
||||||
.route-map__progress { color: #409eff !important; }
|
.route-map__progress { color: #409eff !important; }
|
||||||
.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-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-map__line { flex: 1 0 64px; min-width: 64px; height: 32px; border-bottom: 2px solid #606266; }
|
.route-map__line { flex: 1 0 64px; min-width: 64px; height: 32px; border-bottom: 6px solid #e4e7ed; }
|
||||||
.execution-detail-heading { padding: 20px 24px 12px; h3 { margin: 0; padding-left: 12px; border-left: 4px solid #409eff; font-size: 16px; } }
|
.execution-detail-heading { padding: 20px 24px 12px; h3 { margin: 0; padding-left: 12px; border-left: 4px solid #409eff; font-size: 16px; } }
|
||||||
.segment-detail { padding: 16px 24px; border-top: 1px solid #eff1f7; header { display: flex; align-items: center; justify-content: space-between; margin: -16px -24px 8px; padding: 12px 24px; cursor: pointer; background: #fafbfc; h3 { display: flex; min-width: 0; align-items: center; flex-wrap: wrap; gap: 12px; margin: 0; font-size: 16px; } em { color: #409eff; font-style: normal; } } }
|
.segment-detail { padding: 16px 24px; border-top: 1px solid #eff1f7; header { display: flex; align-items: center; justify-content: space-between; margin: -16px -24px 8px; padding: 12px 24px; cursor: pointer; background: #fafbfc; h3 { display: flex; min-width: 0; align-items: center; flex-wrap: wrap; gap: 12px; margin: 0; font-size: 16px; } em { color: #409eff; font-style: normal; } } }
|
||||||
.segment-detail__progress { color: #606266; font-size: 14px; font-weight: 400; }
|
.segment-detail__progress { color: #606266; font-size: 14px; font-weight: 400; }
|
||||||
|
|||||||
@@ -651,7 +651,7 @@ export default {
|
|||||||
.route-overview { display: flex; align-items: flex-start; justify-content: flex-end; padding-top: 8px; overflow-x: auto; }
|
.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__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-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-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: 2px solid #606266; }
|
.route-overview__line { flex: 1 0 56px; min-width: 56px; 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-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; }
|
.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%; } }
|
.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%; } }
|
||||||
|
|||||||
@@ -2446,7 +2446,7 @@ export default {
|
|||||||
.loading-detail__value { display: flex; flex-wrap: wrap; gap: 8px; text-align: left; }
|
.loading-detail__value { display: flex; flex-wrap: wrap; gap: 8px; text-align: left; }
|
||||||
.loading-detail__steps { display: flex; align-items: flex-start; overflow-x: auto; padding: 8px 4px 16px; }
|
.loading-detail__steps { display: flex; align-items: flex-start; overflow-x: auto; padding: 8px 4px 16px; }
|
||||||
.loading-detail__step { position: relative; min-width: 190px; flex: 1; text-align: center; }
|
.loading-detail__step { position: relative; min-width: 190px; flex: 1; text-align: center; }
|
||||||
.loading-detail__step:not(:last-child)::after { position: absolute; z-index: 0; top: 16px; left: calc(50% + 25px); width: calc(100% - 50px); height: 2px; content: ''; background: #606266; }
|
.loading-detail__step:not(:last-child)::after { position: absolute; z-index: 0; top: 16px; left: calc(50% + 25px); width: calc(100% - 50px); height: 6px; content: ''; background: #e4e7ed; }
|
||||||
.loading-detail__step-line { display: flex; align-items: center; justify-content: center; }
|
.loading-detail__step-line { display: flex; align-items: center; justify-content: center; }
|
||||||
.loading-detail__step-dot { position: relative; z-index: 1; display: inline-flex; width: 34px; height: 34px; align-items: center; justify-content: center; color: #fff; border-radius: 4px; font-weight: 600; }
|
.loading-detail__step-dot { position: relative; z-index: 1; display: inline-flex; width: 34px; height: 34px; align-items: center; justify-content: center; color: #fff; border-radius: 4px; font-weight: 600; }
|
||||||
.loading-detail__step-dot.start { background: #409eff; }.loading-detail__step-dot.middle { background: #67c23a; }.loading-detail__step-dot.end { background: #e6a23c; }
|
.loading-detail__step-dot.start { background: #409eff; }.loading-detail__step-dot.middle { background: #67c23a; }.loading-detail__step-dot.end { background: #e6a23c; }
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
<div class="route-point">
|
<div class="route-point">
|
||||||
<span :class="['route-node', node.type]">{{ node.text }}</span>
|
<span :class="['route-node', node.type]">{{ node.text }}</span>
|
||||||
<div class="route-detail">
|
<div class="route-detail">
|
||||||
<strong>{{ node.name }}</strong>
|
<el-tooltip placement="top"><template #content>{{ node.name }}</template><strong>{{ node.name }}</strong></el-tooltip>
|
||||||
<span v-for="line in node.lines" :key="line">{{ line }}</span>
|
<span v-for="line in node.lines" :key="line">{{ line }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -516,8 +516,8 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.route-connector {
|
.route-connector {
|
||||||
width: clamp(180px, 20vw, 344px);
|
width: clamp(180px, 20vw, 266px);
|
||||||
flex: 0 0 clamp(180px, 20vw, 344px);
|
flex: 0 0 clamp(180px, 20vw, 266px);
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
margin: 0 -6px;
|
margin: 0 -6px;
|
||||||
small {
|
small {
|
||||||
@@ -530,8 +530,8 @@ export default {
|
|||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
:deep(.el-progress-bar__outer) {
|
:deep(.el-progress-bar__outer) {
|
||||||
height: 8px !important;
|
height: 6px !important;
|
||||||
background-color: #f1f2f5;
|
background-color: #e4e7ed;
|
||||||
}
|
}
|
||||||
:deep(.el-progress-bar__inner) {
|
:deep(.el-progress-bar__inner) {
|
||||||
background-color: #409eff;
|
background-color: #409eff;
|
||||||
@@ -543,6 +543,8 @@ export default {
|
|||||||
header {
|
header {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
.el-link {
|
.el-link {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -8,10 +8,6 @@
|
|||||||
v-model="form"
|
v-model="form"
|
||||||
ref="crud"
|
ref="crud"
|
||||||
:permission="permissionList"
|
:permission="permissionList"
|
||||||
:before-open="beforeOpen"
|
|
||||||
@row-save="rowSave"
|
|
||||||
@row-update="rowUpdate"
|
|
||||||
@row-del="rowDel"
|
|
||||||
@search-change="searchChange"
|
@search-change="searchChange"
|
||||||
@search-reset="searchReset"
|
@search-reset="searchReset"
|
||||||
@selection-change="selectionChange"
|
@selection-change="selectionChange"
|
||||||
@@ -25,7 +21,7 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
icon="el-icon-plus"
|
icon="el-icon-plus"
|
||||||
v-if="hasPermission('process_config_add')"
|
v-if="hasPermission('process_config_add')"
|
||||||
@click="$refs.crud.rowAdd()"
|
@click="openProcessConfig()"
|
||||||
>新建过程配置
|
>新建过程配置
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -46,27 +42,6 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</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 }">
|
<template #status="{ row }">
|
||||||
<el-tag :type="statusTagType(row.status)">
|
<el-tag :type="statusTagType(row.status)">
|
||||||
{{ row.statusName || displayStatus(row.status) }}
|
{{ row.statusName || displayStatus(row.status) }}
|
||||||
@@ -79,101 +54,154 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #basicInfo-form>
|
<template #menu="{ row, index }">
|
||||||
<section-card title="基本信息">
|
<el-link
|
||||||
<el-form
|
type="primary"
|
||||||
:model="form"
|
v-if="hasPermission('process_config_view')"
|
||||||
label-position="right"
|
@click="openProcessConfig(row, true)"
|
||||||
label-width="calc(6em + 24px)"
|
>
|
||||||
>
|
查看
|
||||||
<el-row :gutter="18">
|
</el-link>
|
||||||
<el-col :span="6">
|
<el-link
|
||||||
<el-form-item label="配置名称" required>
|
type="primary"
|
||||||
<el-input
|
v-if="canEdit(row)"
|
||||||
v-model="form.configName"
|
@click="openProcessConfig(row, false)"
|
||||||
:disabled="dialogReadonly"
|
>
|
||||||
maxlength="100"
|
编辑
|
||||||
placeholder="请输入"
|
</el-link>
|
||||||
/>
|
<el-link
|
||||||
</el-form-item>
|
type="primary"
|
||||||
</el-col>
|
v-if="hasPermission('process_config_copy')"
|
||||||
<el-col :span="6">
|
@click="handleCopy(row)"
|
||||||
<el-form-item label="项目" required>
|
>
|
||||||
<el-select
|
复制
|
||||||
v-model="selectedProjectId"
|
</el-link>
|
||||||
clearable
|
<el-link
|
||||||
filterable
|
type="primary"
|
||||||
remote
|
v-if="canEnable(row)"
|
||||||
:remote-method="loadProjectOptions"
|
@click="handleAction('enable', row)"
|
||||||
:loading="projectLoading"
|
>
|
||||||
:disabled="dialogReadonly"
|
启用
|
||||||
placeholder="请选择"
|
</el-link>
|
||||||
style="width: 100%"
|
<el-link
|
||||||
@change="handleProjectChange"
|
type="primary"
|
||||||
>
|
v-if="canDisable(row)"
|
||||||
<el-option
|
@click="handleAction('disable', row)"
|
||||||
v-for="item in projectOptions"
|
>
|
||||||
:key="item.id"
|
停用
|
||||||
:label="formatProjectLabel(item)"
|
</el-link>
|
||||||
:value="String(item.id)"
|
<el-link
|
||||||
/>
|
type="danger"
|
||||||
</el-select>
|
v-if="canDelete(row)"
|
||||||
</el-form-item>
|
@click="rowDel(row)"
|
||||||
</el-col>
|
>
|
||||||
<el-col :span="12">
|
删除
|
||||||
<el-form-item label="运输完成时限">
|
</el-link>
|
||||||
<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>
|
||||||
|
</avue-crud>
|
||||||
|
|
||||||
<template #nodeConfigJson-form>
|
<el-dialog
|
||||||
<div class="process-config-page__custom-form">
|
:title="dialogTitle"
|
||||||
<section-card title="现行过程节点">
|
append-to-body
|
||||||
<div class="process-config-page__timeline" v-if="enabledNodes.length">
|
v-model="processBox"
|
||||||
<div class="process-config-page__timeline-line"></div>
|
width="92%"
|
||||||
<div
|
top="4vh"
|
||||||
v-for="node in enabledNodes"
|
class="process-dialog"
|
||||||
:key="node.key"
|
@closed="resetProcess"
|
||||||
class="process-config-page__timeline-item"
|
>
|
||||||
>
|
<el-form
|
||||||
<span class="process-config-page__timeline-dot"></span>
|
ref="processForm"
|
||||||
<div class="process-config-page__timeline-name">{{ node.name }}</div>
|
:model="form"
|
||||||
<div class="process-config-page__timeline-desc">
|
label-position="right"
|
||||||
<div v-for="text in timelineDescriptions(node)" :key="text">{{ text }}</div>
|
label-width="calc(6em + 24px)"
|
||||||
|
:disabled="dialogReadonly"
|
||||||
|
class="process-form dialog-form-label-fixed"
|
||||||
|
>
|
||||||
|
<section-card title="基本信息">
|
||||||
|
<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>
|
</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>
|
||||||
|
</section-card>
|
||||||
|
|
||||||
|
<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>
|
</div>
|
||||||
<el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" />
|
</div>
|
||||||
</section-card>
|
<el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" />
|
||||||
|
</section-card>
|
||||||
|
|
||||||
<section-card title="节点设置">
|
<section-card title="节点设置">
|
||||||
<el-table
|
<el-table
|
||||||
class="process-config-page__node-table"
|
class="process-config-page__node-table"
|
||||||
border
|
border
|
||||||
@@ -357,55 +385,21 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</section-card>
|
</section-card>
|
||||||
</div>
|
</el-form>
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #menu="{ row, index }">
|
<template #footer>
|
||||||
<el-link
|
<template v-if="!dialogReadonly">
|
||||||
type="primary"
|
<el-button plain :loading="submitting" :disabled="submitting" @click="submitProcessConfig('draft')">
|
||||||
v-if="hasPermission('process_config_view')"
|
保存草稿
|
||||||
@click="$refs.crud.rowView(row, index)"
|
</el-button>
|
||||||
>
|
<el-button type="primary" :loading="submitting" :disabled="submitting" @click="submitProcessConfig('enabled')">
|
||||||
查看
|
保存并启用
|
||||||
</el-link>
|
</el-button>
|
||||||
<el-link
|
</template>
|
||||||
type="primary"
|
<el-button @click="processBox = false">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
|
||||||
v-if="canEdit(row)"
|
|
||||||
@click="$refs.crud.rowEdit(row, index)"
|
|
||||||
>
|
|
||||||
编辑
|
|
||||||
</el-link>
|
|
||||||
<el-link
|
|
||||||
type="primary"
|
|
||||||
v-if="hasPermission('process_config_copy')"
|
|
||||||
@click="handleCopy(row)"
|
|
||||||
>
|
|
||||||
复制
|
|
||||||
</el-link>
|
|
||||||
<el-link
|
|
||||||
type="primary"
|
|
||||||
v-if="canEnable(row)"
|
|
||||||
@click="handleAction('enable', row)"
|
|
||||||
>
|
|
||||||
启用
|
|
||||||
</el-link>
|
|
||||||
<el-link
|
|
||||||
type="primary"
|
|
||||||
v-if="canDisable(row)"
|
|
||||||
@click="handleAction('disable', row)"
|
|
||||||
>
|
|
||||||
停用
|
|
||||||
</el-link>
|
|
||||||
<el-link
|
|
||||||
type="danger"
|
|
||||||
v-if="canDelete(row)"
|
|
||||||
@click="rowDel(row)"
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</el-link>
|
|
||||||
</template>
|
</template>
|
||||||
</avue-crud>
|
</el-dialog>
|
||||||
|
|
||||||
<empty-pagination
|
<empty-pagination
|
||||||
:page="page"
|
:page="page"
|
||||||
@@ -519,6 +513,8 @@ export default {
|
|||||||
},
|
},
|
||||||
selectionList: [],
|
selectionList: [],
|
||||||
submitStatus: 1,
|
submitStatus: 1,
|
||||||
|
processBox: false,
|
||||||
|
submitting: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -540,6 +536,10 @@ export default {
|
|||||||
enabledNodes() {
|
enabledNodes() {
|
||||||
return this.nodeRows.filter(item => item.enabled);
|
return this.nodeRows.filter(item => item.enabled);
|
||||||
},
|
},
|
||||||
|
dialogTitle() {
|
||||||
|
if (this.dialogReadonly) return '查看过程配置';
|
||||||
|
return this.form.id ? '编辑过程配置' : '新增过程配置';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.resetNodeRows();
|
this.resetNodeRows();
|
||||||
@@ -853,11 +853,6 @@ export default {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
stopSubmitLoading(loading) {
|
|
||||||
if (typeof loading === 'function') {
|
|
||||||
loading();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
needsDuplicateVoucherConfirm() {
|
needsDuplicateVoucherConfirm() {
|
||||||
const signNode = this.nodeRows.find(item => item.key === 'sign');
|
const signNode = this.nodeRows.find(item => item.key === 'sign');
|
||||||
const returnNode = this.nodeRows.find(item => item.key === 'return');
|
const returnNode = this.nodeRows.find(item => item.key === 'return');
|
||||||
@@ -887,39 +882,74 @@ export default {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
submitRow(row, done, loading, status = this.submitStatus) {
|
openProcessConfig(row, readonly = false) {
|
||||||
|
this.dialogReadonly = readonly;
|
||||||
this.submitStatus = 1;
|
this.submitStatus = 1;
|
||||||
this.syncNodeFields();
|
if (row && row.id) {
|
||||||
const submitRow = this.normalizeRow({ ...row, status });
|
api.getDetail(row.id).then(res => {
|
||||||
if (!this.validateRow(submitRow)) {
|
const data = res.data.data || {};
|
||||||
this.stopSubmitLoading(loading);
|
this.form = data;
|
||||||
|
this.selectedProjectId = data.projectIds ? String(data.projectIds) : '';
|
||||||
|
this.ensureSelectedProjectOption();
|
||||||
|
this.parseNodeConfig(data);
|
||||||
|
this.processBox = true;
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.confirmDuplicateVoucher()
|
this.form = {
|
||||||
.then(() => api.submit(submitRow))
|
configName: '',
|
||||||
.then(() => {
|
projectIds: '',
|
||||||
this.onLoad(this.page);
|
projectNames: '',
|
||||||
this.$message({ type: 'success', message: '操作成功!' });
|
defaultFinishDays: '',
|
||||||
done();
|
remark: '',
|
||||||
})
|
status: 0,
|
||||||
.catch(error => {
|
};
|
||||||
if (error !== 'cancel' && error !== 'close') {
|
this.selectedProjectId = '';
|
||||||
window.console.log(error);
|
this.resetNodeRows();
|
||||||
}
|
this.processBox = true;
|
||||||
this.stopSubmitLoading(loading);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
rowSave(row, done, loading) {
|
submitProcessConfig(mode) {
|
||||||
this.submitRow(row, done, loading);
|
this.$refs.processForm.validate(valid => {
|
||||||
|
if (!valid) return;
|
||||||
|
this.submitting = true;
|
||||||
|
this.submitStatus = mode === 'draft' ? 2 : 1;
|
||||||
|
this.syncNodeFields();
|
||||||
|
const submitRow = this.normalizeRow({ ...this.form, status: this.submitStatus });
|
||||||
|
if (!this.validateRow(submitRow)) {
|
||||||
|
this.submitting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.confirmDuplicateVoucher()
|
||||||
|
.then(() => api.submit(submitRow))
|
||||||
|
.then(() => {
|
||||||
|
this.submitting = false;
|
||||||
|
this.processBox = false;
|
||||||
|
this.onLoad(this.page);
|
||||||
|
this.$message({ type: 'success', message: '操作成功!' });
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.submitting = false;
|
||||||
|
if (error !== 'cancel' && error !== 'close') {
|
||||||
|
window.console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
rowUpdate(row, index, done, loading) {
|
resetProcess() {
|
||||||
this.submitRow(row, done, loading);
|
this.dialogReadonly = false;
|
||||||
},
|
this.submitting = false;
|
||||||
handleProcessConfigSave(mode) {
|
this.submitStatus = 1;
|
||||||
this.submitStatus = mode === 'draft' ? 2 : 1;
|
this.form = {
|
||||||
if (this.$refs.crud && typeof this.$refs.crud.rowSave === 'function') {
|
configName: '',
|
||||||
this.$refs.crud.rowSave();
|
projectIds: '',
|
||||||
}
|
projectNames: '',
|
||||||
|
defaultFinishDays: '',
|
||||||
|
remark: '',
|
||||||
|
status: 0,
|
||||||
|
};
|
||||||
|
this.selectedProjectId = '';
|
||||||
|
this.resetNodeRows();
|
||||||
|
this.$refs.processForm?.clearValidate();
|
||||||
},
|
},
|
||||||
rowDel(row) {
|
rowDel(row) {
|
||||||
this.$confirm('确定将选择数据删除?', {
|
this.$confirm('确定将选择数据删除?', {
|
||||||
@@ -963,35 +993,6 @@ export default {
|
|||||||
}
|
}
|
||||||
this.selectionClear();
|
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() {
|
searchReset() {
|
||||||
this.query = {};
|
this.query = {};
|
||||||
this.applyDefaultDeptSearch();
|
this.applyDefaultDeptSearch();
|
||||||
@@ -1239,5 +1240,10 @@ export default {
|
|||||||
:deep(.el-table__body tr:nth-child(even) > td.el-table__cell) {
|
:deep(.el-table__body tr:nth-child(even) > td.el-table__cell) {
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.process-dialog .el-dialog__body) {
|
||||||
|
max-height: 72vh;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -153,15 +153,16 @@
|
|||||||
destroy-on-close
|
destroy-on-close
|
||||||
:before-close="beforeUploadDialogClose"
|
:before-close="beforeUploadDialogClose"
|
||||||
>
|
>
|
||||||
<el-form
|
<section-card>
|
||||||
ref="uploadFormRef"
|
<el-form
|
||||||
:model="editing"
|
ref="uploadFormRef"
|
||||||
:rules="rules"
|
:model="editing"
|
||||||
label-position="right"
|
:rules="rules"
|
||||||
label-width="auto"
|
label-position="right"
|
||||||
class="voucher-manage-page__upload-form"
|
label-width="auto"
|
||||||
>
|
class="voucher-manage-page__upload-form"
|
||||||
<el-form-item label="项目名称" prop="projectId"
|
>
|
||||||
|
<el-form-item label="项目名称" prop="projectId"
|
||||||
><el-select
|
><el-select
|
||||||
v-model="editing.projectId"
|
v-model="editing.projectId"
|
||||||
class="voucher-manage-page__project-select"
|
class="voucher-manage-page__project-select"
|
||||||
@@ -169,13 +170,13 @@
|
|||||||
filterable
|
filterable
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
@change="changeProject"
|
@change="changeProject"
|
||||||
><el-option
|
><el-option
|
||||||
v-for="item in projectOptions"
|
v-for="item in projectOptions"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:label="item.projectName"
|
:label="item.projectName"
|
||||||
:value="item.id" /></el-select
|
:value="item.id" /></el-select
|
||||||
></el-form-item>
|
></el-form-item>
|
||||||
<el-form-item label="执行凭证" prop="fileUrl"
|
<el-form-item label="执行凭证" prop="fileUrl"
|
||||||
><el-upload
|
><el-upload
|
||||||
action="#"
|
action="#"
|
||||||
accept=".zip,.7z"
|
accept=".zip,.7z"
|
||||||
@@ -183,26 +184,28 @@
|
|||||||
:limit="1"
|
:limit="1"
|
||||||
:on-change="selectVoucherFile"
|
:on-change="selectVoucherFile"
|
||||||
:on-remove="clearFile"
|
:on-remove="clearFile"
|
||||||
><el-button
|
><el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
:loading="uploading"
|
:loading="uploading"
|
||||||
:disabled="!editing.projectId || uploading"
|
:disabled="!editing.projectId || uploading"
|
||||||
>上传</el-button
|
>上传</el-button
|
||||||
><template #tip
|
><template #tip
|
||||||
><span class="voucher-manage-page__upload-tip"
|
><span class="voucher-manage-page__upload-tip"
|
||||||
>支持 zip、7z 格式,采用分片上传,上传中断后可在“上传进度”继续上传。</span
|
>支持 zip、7z 格式,采用分片上传,上传中断后可在“上传进度”继续上传。</span
|
||||||
></template
|
></template
|
||||||
></el-upload
|
></el-upload
|
||||||
><el-progress
|
><el-progress
|
||||||
v-if="uploading || editing.fileTaskId"
|
v-if="uploading || editing.fileTaskId"
|
||||||
:percentage="uploadPercent"
|
:percentage="uploadPercent"
|
||||||
:status="uploadPercent === 100 ? 'success' : undefined"
|
:status="uploadPercent === 100 ? 'success' : undefined"
|
||||||
class="voucher-manage-page__upload-progress"
|
class="voucher-manage-page__upload-progress"
|
||||||
/></el-form-item>
|
/></el-form-item>
|
||||||
<el-form-item label="关联运输批次" prop="waybillImportBatchIds"
|
<el-form-item label="关联运输批次" prop="waybillImportBatchIds"
|
||||||
><el-button type="primary" @click="openBatchDialog">选择</el-button></el-form-item
|
><el-button type="primary" @click="openBatchDialog">选择</el-button></el-form-item
|
||||||
>
|
>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</section-card>
|
||||||
|
|
||||||
<el-table :data="selectedBatches" border
|
<el-table :data="selectedBatches" border
|
||||||
><el-table-column type="index" label="序号" width="80" /><el-table-column
|
><el-table-column type="index" label="序号" width="80" /><el-table-column
|
||||||
prop="batchNo"
|
prop="batchNo"
|
||||||
@@ -405,6 +408,7 @@ import md5 from 'js-md5';
|
|||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { getList as getProjectList } from '@/api/business/project-apply';
|
import { getList as getProjectList } from '@/api/business/project-apply';
|
||||||
import * as api from '@/api/business/voucher-manage';
|
import * as api from '@/api/business/voucher-manage';
|
||||||
|
import SectionCard from '@/components/section-card/main.vue';
|
||||||
|
|
||||||
const loading = ref(false),
|
const loading = ref(false),
|
||||||
rows = ref([]),
|
rows = ref([]),
|
||||||
|
|||||||
Reference in New Issue
Block a user