Merge remote-tracking branch 'websoft/master'

This commit is contained in:
2026-08-13 20:56:00 +08:00
44 changed files with 1170 additions and 806 deletions
+31
View File
@@ -0,0 +1,31 @@
# 2026-08-12
## 全站自定义表单弹窗样式统一为客商档案风格
- 新增全局弹窗表单标准类 `.dialog-form--carded``src/styles/element-ui.scss`),统一实现:
- `section-card` 白底卡片分组
- label 固定宽度 `calc(6em + 24px)`、右对齐、上下居中
- input/select/cascader/tree-select/date-editor/textarea 等控件固定宽度 250px
- radio/checkbox 组宽度自适应
- 改造文件清单:
- `src/views/flow/manager.vue`:流程变更弹窗
- `src/views/flow/follow.vue`:流程删除弹窗
- `src/views/system/param.vue`:参数编辑弹窗
- `src/views/system/authlock.vue`:锁定用户、解锁确认弹窗
- `src/views/system/user.vue`:用户编辑、修改密码弹窗
- `src/views/business/components/waybill-import-dialog.vue`:新建导入弹窗表单区
- 已跳过(非编辑表单弹窗):`system/dept.vue` 承运商选择搜索弹窗、`business/master-order-editor.vue` 页面级组件。
- `npm run build` 构建通过。
## 港口码头(port-terminal)编辑弹窗 input 宽度统一 250px
- 文件:`src/views/base/port-terminal.vue`
- 做法:option 加 `dialogCustomClass: 'port-terminal-edit-dialog'`,并在文件末尾新增非 scoped `<style>` 块,`.port-terminal-edit-dialog .el-input { width: 250px !important }`
- 说明:弹窗 `append-to-body`,scoped 命中不到,故用全局样式 + 自定义 dialog class 限定作用域;`.el-input``.el-select` 统一 `width: 250px !important`(含 formslot 内带内联 `width:100%` 的 country/cityCode/districtCode 下拉,!important 覆盖)。`textarea`(详细地址/备注)、类型 `el-radio-group` 维持自适应,未改。新增弹窗复用同一 dialog,故一并生效。
## 港口码头 详细地址/备注字段形态调整(接续上方宽度统一)
- `detailAddress`:移除 `type: 'textarea'` / `minRows: 3` 改单行 input;因属整行字段需放宽,启用 `formslot` + 模板 `#detailAddress-form` 手写 `<el-input class="detail-address-input">`,并用 `.port-terminal-edit-dialog .detail-address-input { width: 100% !important }` 覆盖全局 250px 规则,占满整行。表格列仍由 `slot: true` + `#detailAddress` 显示插槽控制。
- `remark``minRows: 4``2`(约 2 行高度),仍为 textarea(本身不受 250px 规则约束,已是整行宽)。
- 表单字段排序调整:按截图示意重新排为——类型(10) → 名称(20) → 编码(30) → 国家(40) → 城市(50) → 区县(60) → 详细地址(70) → 经度(80) → 纬度(90) → 上级港口(100) → 备注(无 order 置底)。即区县和详细地址插在国家/城市那一行下面。
- 备注宽度改为 80%`remark``formslot: true` + 模板 `#remark-form` 手写 `<el-input type="textarea" class="remark-input" :rows="2" maxlength="200" show-word-limit>`CSS `.port-terminal-edit-dialog .remark-input { width: 80% !important }`。注意:详细地址 `.detail-address-input` 当前宽度为 81%(用户手动调整,非本次设定)。
+95
View File
@@ -0,0 +1,95 @@
# 2026-08-13 工作记录
## business-crud-page.vue UI 对齐 customer-archivesection-card 间隔 + 表单排列统一)
### 问题
- 该组件内 `.section-card { margin-bottom: 0 !important }`scoped 顶层)把全局 8px 卡片间距清零,导致弹窗里的 section-card 卡片贴在一起(与 customer-archive 的留白不一致)。
- 手写的 dispatch-item 表单 markup 仍写 `label-width="auto"`(虽被共享 CSS 块强制为 `calc(6em+24px)`,但不直观)。
### 改动(src/views/business/components/business-crud-page.vue
1. 删除 `margin-bottom:0 !important` 覆盖,改为 `.section-card{margin-bottom:8px !important; &:last-child{margin-bottom:0}}`,与 customer-archive/全局 element-ui.scss 的 8px 节奏一致。
2. `.business-crud-page__detail-content`(详情弹窗,原本 `gap:12px`)改为 `gap:8px` 并给内部 `.section-card{margin-bottom:0 !important}`,避免 8px 外边距 + gap 双重留白。
3. `:deep(.avue-form__group:has(.dialog-section-title))` 白卡 `margin-bottom:16px→8px`,使主弹窗分组白卡与 section-card 同节奏。
4. `&__dispatch-summary``margin-bottom:12px→8px`
5. dispatch-item 表单 `label-width="auto"→"calc(6em + 24px)"`(与 task-form/freight-form 共享的 label 标准一致;参考 customer-archive 的右侧固定宽 label + `el-row :gutter` 网格思路)。
### 验证
- 仅改 scoped SCSS + 1 处 markup 属性,未动逻辑;SFC 结构未变。表单组件排列本就通过共享 `__task-form/__freight-form/__dispatch-item-form` 块统一为 `calc(6em+24px)` label + 4 列网格,本次使其显式对齐。
## 弹窗样式与交互调整(base 模块)
### 1. port-terminal.vue 港口/码头弹窗
- 去掉浏览器 input autocomplete 地址联想:新增 `disableDialogAutocomplete()` 方法(批量给 `.port-terminal-edit-dialog` 内 input/textarea 设 autocomplete=off 等),在 `beforeOpen` 两个分支 `done()` 后用 `setTimeout(50)` 调用。
- option 字段调整(用户此前需求,已指导):详细地址 `detailAddress``span:24→12``order:86→88`,与区县 `districtCode`(span12,order87) 并排。
### 2. railway-station.vue 铁路车站弹窗
- label 宽度 85→108option `labelWidth:'auto'→'108px'`(字符串不生效),再补 `dialogCustomClass:'railway-station-edit-dialog'` + 非 scoped `<style>` 强制 `.el-form-item__label{width:108px!important}`
### 3. 全站弹窗底部浮动按钮(统一规范)
-`src/styles/element-ui.scss` 新增全局规则:`.el-dialog__body{max-height:calc(100vh-200px);overflow-y:auto}` + `.el-dialog__footer{白底+上边框+轻阴影}`,实现取消/保存按钮固定在底部(参照 business/project-apply)。全站 Avue 弹窗自动生效,含 railway-station。已记入 MEMORY.md 长期规范。
### 4. port-terminal.vue 字段分组白卡 + label 108(本次)
- 改用 Avue `option.group` 把表单分成 3 张白卡:基础信息 / 位置信息 / 其他信息(对齐 driver/vehicle/ship/customer-archive 的 section-card 风格)。
- root `column` 保留不动(脚本大量用 `findColumn(this.option.column,...)` 动态设 dicData/显示),在 `created()` 里循环把 root 列 `display=false`,使其只服务表格/搜索、不重复渲染进表单。
- 新增 `getColumnsByProp(prop)` 助手,统一把 8 处 `dicData`/显示切换同时作用于 root 与 group 两处(否则 group 列的级联下拉不会刷新)。
- 样式:外层 `.avue-form` 透明化(卡片交由分组);`.avue-form__group` 白卡 + 4px 主色竖条标题 + 内容区左右 16px;`.el-form-item__label{width:108px!important}` 对齐 railway-station。
- 关键坑:Avue form 的 `columnOption` 会把 root column 也作为「无标题组」渲染进表单,故 group 页必须给 root 列 `display:false`,否则字段重复;且动态 dicData 必须双写 root+group。
### 5. port-terminal.vue 回退分组白卡 + label 108(用户要求)
- 用户决定不在本页使用分组白卡与 label 宽度 108,已全部回退:
- 删除 `option.group` 三张白卡,恢复扁平 `column` 结构(`sed` 删 695974 行)。
- `created()` 去掉 root 列 `display=false` 循环;删除 `getColumnsByProp` 助手;`setColumnDisplay` 与 8 处 `dicData`/显示切换全部还原为 `findColumn(this.option.column, prop)` 写法。
- 样式块恢复:`.avue-form` 恢复为单张白卡(去透明化),删除 `.avue-form__group` 分组白卡规则与 `.el-form-item__label{width:108px}`;保留灰底 + 浮动底栏统一风格、input/select 250px、备注 85%。
- 校验:SFC 解析通过,无 getColumnsByProp/group/avue-form__group/label108 残留。
### 6. railway-station.vue 对齐 port-terminal 统一风格(用户要求"按 port-terminal 效果改"
- 扩充 `.railway-station-edit-dialog` 非 scoped 样式块,对齐 port-terminal:灰底 `.el-dialog__body`(#f2f2f2, padding 8px) + 表单白卡 `.avue-form`(白底/圆角6/轻阴影/内边距16px) + 浮动底栏 `.avue-dialog__footer`(白底/圆角/轻阴影/右对齐) + 输入框 `.el-input,.el-select` 宽 250px + 备注 `.remark-input` 宽 85%。
- 给备注字段(`prop:'remark'`)加 `class:'remark-input'`,使备注 85% 规则生效(原字段仅 `type:textarea`,无 class)。
- 保留用户之前要求的 `labelWidth:'108px'``.el-form-item__label{width:108px!important}`
- 未包含 port-terminal 的「关闭浏览器地址联想 autocomplete」逻辑(用户未要求,railway 未反馈该问题);如需一致可后续补。
- 校验:SFC 解析通过。
### 7. 方向纠正:应改 port-terminal 参考 railway-station(非改 railway 参考 port
- 用户澄清:第6条方向搞反了。正确语义是「改 port-terminal,参考 railway-station」。railway-station 是参考样板,不应被改。
- 还原 railway-station(撤销第6条):删除误加的冗余专属灰底白卡/250px/备注85% 块(该块 `.avue-form{padding:16px}` 会与全局 `.el-dialog .avue-form` 的 24px 冲突造成不齐),仅保留 `labelWidth:'108px'` + `.el-form-item__label{width:108px!important}`;移除备注字段误加的 `class:'remark-input'`
- 关键认知:全局 `src/styles/element-ui.scss` 第240-265行**已有完整弹窗标准规则**(灰底 `.el-dialog__body`#f2f2f2 + 白卡 `.el-dialog .avue-form` padding 24px + 浮动底栏 `.avue-crud__dialog .avue-dialog__footer`)。railway-station「整齐」即靠全局规则 + label 108;专属块属冗余且会覆盖全局 24px→16px 导致不齐。
- 改造 port-terminal 对齐 railway-station:保留专属灰底白卡兜底(其历史未命中全局,保留以防回归),补 `labelWidth:'108px'` + 样式块 `.el-form-item__label{width:108px!important}`;并将专属块 `.avue-form` padding 由 16px 改为 **24px** 以与全局/railway 一致。
- 校验:两文件 SFC 解析通过;railway 无 remark-input/padding16px 残留;port-terminal 已含 label 108 + padding 24px。
### 8. railway-station.vue label 加宽(用户反馈太挤)
- 用户反馈新增弹窗中"所属区县"label 太挤(实测约 85×32px),要求加宽。
- 已把 `option.labelWidth: '108px' → '140px'`,同步全局覆盖 `.el-form-item__label{width:108px!important} → 140px!important`
- 140px 够"所属区县"4字+必填星号+留白,也覆盖表单其他 label("行政区划编号"6字 + * 也够)。若仍觉不够可再调到 160px。
## process-config.vue 套用 customer-archive 样式(用户要求"和 business-crud-page 一样的问题"
- 根因同商务页:本页原用灰色 `div.dialog-section-title` 标题 + 自定义 `__field` flex 布局(label `flex:0 0 150px`),既无白卡样式也无 8px 卡片间距,与 customer-archive 的 `<section-card>` 白卡风格不一致。Avue form 本身 `labelPosition:'right'``labelWidth:'auto'`,故原页才需自定义固定宽 label。
- 改动(src/views/business/process-config.vue):
1. `#basicInfo-form` 槽:去掉 `process-config-page__section` + `dialog-section-title`,改为 `<section-card title="基本信息">` + 嵌套 `<el-form label-position="right" label-width="calc(6em + 24px)">` + `<el-row :gutter="18">` + `el-col`(配置名称6/项目6/运输完成时限12/备注24) + `el-form-item`,与 customer-archive 右侧固定宽 label 栅格完全对齐。必填项加 `required`
2. `#nodeConfigJson-form` 槽:两个 `dialog-section-title`(现行过程节点 / 节点设置)分别改为 `<section-card title=...>` 包裹(timeline 与 el-table 内容不变)。
3. 删除不再使用的 `__section/__field/__field-label/__field-label--required` 样式;保留 `__finish-days` 与节点表格相关样式。
- 卡片间距:全局 `.section-card{margin-bottom:8px}` 在本页生效(无 `!important` 覆盖),三张白卡自动保持 8px 间隔。
- 校验:@vue/compiler-sfc 编译通过,3 个 section-card 均正确闭合;未动任何业务逻辑(validateRow/syncNodeFields 等不变)。
## business-crud-page.vue 待调度列表汇总「件」蓝色高亮
- 需求:调度弹窗「待调度列表」标题右侧汇总 `共50吨、100件 | 已调度 50吨、100件,剩余0吨、0件` 中,单位是「件」的数字用蓝色显示。
- 改造(src/views/business/components/business-crud-page.vue):
1. 新增 computed `dispatchSummarySegments`,把原纯文本 `dispatchSummaryText` 拆成结构化三段(共/已调度/剩余),每段 items 带 `{unit, value, isPiece: unit==='件'}`,文本拼接方式与原格式完全一致(含空格、`|``、`、逗号)。
2. 模板(约 2546 行)由 `{{ dispatchSummaryText }}` 改为 `v-for` 渲染;`件` 数字包裹 `<span class="dispatch-summary-value is-piece">`
3. 样式:`.business-crud-page__dispatch-list-summary .dispatch-summary-value.is-piece { color:#409eff; font-weight:600 }`(项目主蓝,轻微加粗更醒目)。
- 校验:文本格式与原串逐字符一致,仅「件」数字变色;未动 `dispatchSummaryItems` 等其它逻辑。
- 修正(用户反馈):原把整段「数字+件」一起变蓝导致「件」字也蓝。改为数字与单位拆成两个 span(`dispatch-summary-value` 仅含数字、`dispatch-summary-unit` 含单位),蓝色与加粗只作用于数字,「件」字保持默认色。
- 二次修正(用户反馈):「吨」数字也要蓝。将 `isPiece``unit==='件'` 放宽为恒 `true`,即所有单位的数字均蓝色、单位字默认色(覆盖 吨/件/方 等)。
## business-crud-page.vue 调度弹窗顶部两卡片对齐 + 下方间距 12px
- 需求:截图显示「基本信息」与「收发货路线」两张 section-card 高度不一致,且与下方「待调度列表」间距需 12px。
- 改动(src/views/business/components/business-crud-page.vue):
1. `&__dispatch-summary` 容器 `margin-bottom:8px→12px`,并在容器内覆盖 `.section-card{margin-bottom:0 !important}`,避免 section-card 自带 8px margin 与容器 margin 叠加。
2. `&__dispatch-summary-card``&__dispatch-route-card``min-height:260px`;内部 `:deep(.section-card)``:deep(.section-card__body)``flex:1` 并设 `display:flex;flex-direction:column`,确保左右卡片外框与内部白底区域都等高对齐。
- 校验:grid `align-items:stretch` + section-card flex:1 撑满,卡片底部会对齐;下方间距精确 12px。
## business-crud-page.vue「货物信息」标题与右侧链接水平对齐
- 需求:截图显示「货物信息」标题与右侧「导入货物」「常用货物」两个 `el-link` 不在同一水平线。
- 改动(src/views/business/components/business-crud-page.vue):
1. `.dialog-section-title > span { line-height: 1 }` 收紧标题文字行高。
2. `&__section-actions .el-link { display:inline-flex; align-items:center; line-height:1 }` 让链接严格垂直居中。
- 校验:两处使用 `.dialog-section-title--action.business-crud-page__goods-title` + `__section-actions` 的货物信息标题都会生效。
+8
View File
@@ -24,6 +24,14 @@
### 简单分组(仅 3 项) ### 简单分组(仅 3 项)
- 联系信息等仅 3 项的分组,可用 `el-col :span="8"` 让三项均分一行,避免 4 列网格留白。 - 联系信息等仅 3 项的分组,可用 `el-col :span="8"` 让三项均分一行,避免 4 列网格留白。
### 弹窗底部操作栏浮动效果(全站统一规范)
- **需求来源**:用户要求参考 `business/project-apply`(手写 el-dialog + `#footer` slotbody `max-height:76vh;overflow-y:auto`footer 固定底部)实现"取消/保存按钮浮动在底部"。因绝大多数页面是 Avue CRUD 内置弹窗(无法用 `#footer` slot),统一用**全局 CSS** 实现,全站自动生效。
- **实现位置**`src/styles/element-ui.scss`(在 `.el-dialog .el-form-item` 规则之后新增)。
- **规则**
- `.el-dialog__body { max-height: calc(100vh - 200px); overflow-y: auto; overflow-x: hidden; }` —— 内容超高时独立滚动,footer(位于 body 之外)始终可见。
- `.el-dialog__footer { margin:0; padding:12px 20px; background:#fff; border-top:1px solid var(--el-border-color-lighter,#ebeef5); box-shadow:0 -2px 8px rgba(0,0,0,.04); border-radius:0 0 var(--el-dialog-border-radius,4px); .el-button+.el-button{margin-left:8px} }` —— 视觉底栏(白底+上边框+轻阴影),与主内容区分。
- **注意**`.el-dialog__body``max-height` 会作用于所有弹窗(含纯展示/表格弹窗),无 footer 的弹窗不受影响;project-apply 自身 `.project-apply-dialog .el-dialog__body{76vh}` 特异性更高仍优先。如需让某弹窗豁免,加更具体 class 覆盖即可。
### 上传证件区域尺寸规范(transportCapacity 模块强制) ### 上传证件区域尺寸规范(transportCapacity 模块强制)
- **比例**:中国二代身份证标准尺寸 85.6 × 53.98 mm → 宽:高 = **1.586 : 1**(横放) - **比例**:中国二代身份证标准尺寸 85.6 × 53.98 mm → 宽:高 = **1.586 : 1**(横放)
- **尺寸**:取真实身份证的 ~75% → 固定 **240 × 151 px**1.586:1 精确:151 × 1.586 ≈ 240 - **尺寸**:取真实身份证的 ~75% → 固定 **240 × 151 px**1.586:1 精确:151 × 1.586 ≈ 240
+1 -1
View File
@@ -172,7 +172,7 @@ export const getCargoTypeOption = ctx => ({
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
placeholder: '请输入', placeholder: '请输入',
+2 -2
View File
@@ -74,7 +74,7 @@ export const createOption = () => ({
prop: 'detailAddress', prop: 'detailAddress',
formslot: true, formslot: true,
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
minWidth: 220, minWidth: 220,
showOverflowTooltip: true, showOverflowTooltip: true,
@@ -136,7 +136,7 @@ export const createOption = () => ({
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 160, minWidth: 160,
overHidden: true, overHidden: true,
+1 -1
View File
@@ -254,7 +254,7 @@ export const option = createCrudOption([
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
maxlength: 200, maxlength: 200,
showWordLimit: true, showWordLimit: true,
+1 -1
View File
@@ -127,7 +127,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
maxlength: 500, maxlength: 500,
+1 -1
View File
@@ -253,7 +253,7 @@ export const option = createCrudOption([
prop: 'signType', prop: 'signType',
type: 'select', type: 'select',
search: false, search: false,
span: 6, span: 8,
order: 190, order: 190,
dicData: signTypeOptions, dicData: signTypeOptions,
minWidth: 120, minWidth: 120,
+1 -1
View File
@@ -101,7 +101,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
addDisplay: false, addDisplay: false,
+2 -2
View File
@@ -373,7 +373,7 @@ export default {
label: '任务描述', label: '任务描述',
prop: 'jobDescription', prop: 'jobDescription',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
}, },
], ],
@@ -509,7 +509,7 @@ export default {
labelTip: '供开发者使用,用于功能扩展,powerjob 自身不会使用该字段', labelTip: '供开发者使用,用于功能扩展,powerjob 自身不会使用该字段',
prop: 'extra', prop: 'extra',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
}, },
], ],
+1 -1
View File
@@ -74,7 +74,7 @@ export default {
label: '任务备注', label: '任务备注',
prop: 'jobRemark', prop: 'jobRemark',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
}, },
], ],
+2 -2
View File
@@ -147,7 +147,7 @@ export const option = {
label: '事故原因及损坏情况', label: '事故原因及损坏情况',
prop: 'accidentReasonDamage', prop: 'accidentReasonDamage',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
search: true, search: true,
minWidth: 220, minWidth: 220,
@@ -159,7 +159,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
overHidden: true, overHidden: true,
@@ -166,7 +166,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
overHidden: true, overHidden: true,
+1 -1
View File
@@ -124,7 +124,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
order: 10, order: 10,
minWidth: 180, minWidth: 180,
+1 -1
View File
@@ -137,7 +137,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
overHidden: true, overHidden: true,
+1 -1
View File
@@ -167,7 +167,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
hide: true, hide: true,
rules: [{ max: 200, message: '备注最多 200 个字', trigger: 'blur' }], rules: [{ max: 200, message: '备注最多 200 个字', trigger: 'blur' }],
+1 -1
View File
@@ -118,7 +118,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
overHidden: true, overHidden: true,
+1 -1
View File
@@ -155,7 +155,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
overHidden: true, overHidden: true,
+1 -1
View File
@@ -127,7 +127,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
overHidden: true, overHidden: true,
@@ -123,7 +123,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
overHidden: true, overHidden: true,
@@ -65,7 +65,7 @@ export const option = {
label: '变更内容', label: '变更内容',
prop: 'changeContent', prop: 'changeContent',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
search: true, search: true,
minWidth: 260, minWidth: 260,
@@ -79,7 +79,7 @@ export const option = {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
overHidden: true, overHidden: true,
+2 -2
View File
@@ -181,7 +181,7 @@ export const option = {
label: '过程描述', label: '过程描述',
prop: 'processDescription', prop: 'processDescription',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
minWidth: 220, minWidth: 220,
overHidden: true, overHidden: true,
@@ -195,7 +195,7 @@ export const option = {
label: '处理结果', label: '处理结果',
prop: 'processResult', prop: 'processResult',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
minWidth: 220, minWidth: 220,
overHidden: true, overHidden: true,
+70 -5
View File
@@ -173,7 +173,29 @@
.el-dialog .el-form-item--small.el-form-item, .el-dialog .el-form-item--small.el-form-item,
.el-dialog .el-form-item--large.el-form-item, .el-dialog .el-form-item--large.el-form-item,
.el-dialog .el-form-item--medium.el-form-item { .el-dialog .el-form-item--medium.el-form-item {
margin-bottom: 20px; //margin-bottom: 20px;
}
/* 全站弹窗:底部操作栏浮动效果(参照 business/project-apply
* - body 超高时内部独立滚动,footer(取消/保存等按钮)始终固定在底部可见
* - footer 加视觉底栏:白底 + 上边框 + 轻阴影,与主内容区分 */
.el-dialog__body {
max-height: calc(100vh - 200px);
overflow-y: auto;
overflow-x: hidden;
}
.el-dialog__footer {
margin: 0;
padding: 12px 20px;
background: #fff;
border-top: 1px solid var(--el-border-color-lighter, #ebeef5);
//box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04);
border-radius: 0 0 var(--el-dialog-border-radius, 4px);
.el-button + .el-button {
margin-left: 8px;
}
} }
.el-dialog__title, .el-dialog__title,
@@ -217,7 +239,7 @@
// 1) 所有弹窗内容区统一灰底 + 8px 内边距(全站统一) // 1) 所有弹窗内容区统一灰底 + 8px 内边距(全站统一)
.el-dialog__body { .el-dialog__body {
background-color: #f2f2f2; background-color: #f2f2f2;
padding: 8px !important; padding: 12px !important;
} }
// Avue CRUD 弹窗:表单白卡 + 底部按钮区视觉合一(按钮在卡片内部) // Avue CRUD 弹窗:表单白卡 + 底部按钮区视觉合一(按钮在卡片内部)
@@ -305,9 +327,9 @@
} }
} }
// 4) 弹窗内表单项默认上下间距 20px(覆盖默认 18px / 22px,与 customer-archive 对齐) // 4) 弹窗内表单项默认上下间距 16px(覆盖默认 18px / 22px,与 customer-archive 对齐)
.el-dialog .el-form-item { .el-dialog .el-form-item {
margin-bottom: 20px; //margin-bottom: 16px;
} }
// 5) 通用分组白卡组件(<section-card>):标题融入卡头 // 5) 通用分组白卡组件(<section-card>):标题融入卡头
@@ -315,7 +337,8 @@
background: #fff; background: #fff;
border-radius: 6px; border-radius: 6px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
margin-bottom: 8px; margin-bottom: 12px;
padding-bottom: 8px;
overflow: hidden; overflow: hidden;
&:last-child { &:last-child {
@@ -362,6 +385,40 @@
row-gap: 0; row-gap: 0;
} }
// 7) 卡片式弹窗表单标准(与 vehicle/customer-archive 编辑弹窗一致)
// 在 el-dialog 上添加 class="dialog-form--carded" 即可生效
.dialog-form--carded {
.el-form-item {
align-items: center;
margin-bottom: 20px;
}
.el-form-item__label {
flex: 0 0 calc(6em + 24px) !important;
width: calc(6em + 24px) !important;
white-space: normal !important;
word-break: break-all;
overflow-wrap: anywhere;
line-height: 18px;
}
.el-form-item__content > .el-input,
.el-form-item__content > .el-select,
.el-form-item__content > .el-cascader,
.el-form-item__content > .el-tree-select,
.el-form-item__content > .el-input-number,
.el-form-item__content > .el-date-editor,
.el-form-item__content > .el-textarea {
width: 250px;
max-width: 100%;
}
.el-form-item__content > .el-radio-group,
.el-form-item__content > .el-checkbox-group {
width: auto;
}
}
.avue-crud__dialog .avue-dialog__footer > .el-button { .avue-crud__dialog .avue-dialog__footer > .el-button {
margin-left: 12px; margin-left: 12px;
} }
@@ -724,3 +781,11 @@
opacity: 0.55; opacity: 0.55;
} }
} }
.avue-crud__dialog .avue-dialog__footer{
border-top: 0 !important;
margin-top: -30px !important;
}
.el-form-item__label {
margin-left: 20px !important;
}
+2 -2
View File
@@ -370,7 +370,7 @@ export default {
label: '详细地址', label: '详细地址',
prop: 'detailAddress', prop: 'detailAddress',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
minWidth: 220, minWidth: 220,
overHidden: false, overHidden: false,
@@ -429,7 +429,7 @@ export default {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
hide: true, hide: true,
maxlength: 200, maxlength: 200,
+1 -1
View File
@@ -271,7 +271,7 @@ export default {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
hide: true, hide: true,
maxlength: 200, maxlength: 200,
+101 -18
View File
@@ -75,6 +75,7 @@
filterable filterable
:disabled="isParentRegionLocked" :disabled="isParentRegionLocked"
:placeholder="isParentRegionLocked ? '自动带出' : '请选择国家'" :placeholder="isParentRegionLocked ? '自动带出' : '请选择国家'"
autocomplete="off"
style="width: 100%" style="width: 100%"
@change="handleCountryChange" @change="handleCountryChange"
> >
@@ -171,6 +172,27 @@
<template #detailAddress="{ row }"> <template #detailAddress="{ row }">
<span class="port-terminal-page__detail-address">{{ row.detailAddress || '-' }}</span> <span class="port-terminal-page__detail-address">{{ row.detailAddress || '-' }}</span>
</template> </template>
<template #detailAddress-form>
<el-input
v-model="form.detailAddress"
class="detail-address-input"
clearable
maxlength="255"
show-word-limit
placeholder="请输入"
/>
</template>
<template #remark-form>
<el-input
v-model="form.remark"
class="remark-input"
type="textarea"
:rows="2"
maxlength="200"
show-word-limit
placeholder="请输入"
/>
</template>
<template #longitude-form> <template #longitude-form>
<el-input <el-input
v-model="form.longitude" v-model="form.longitude"
@@ -195,7 +217,7 @@
@load="onLoad(page, query)" @load="onLoad(page, query)"
/> />
<el-dialog title="港口码头主数据导入" append-to-body v-model="excelBox" width="555px"> <el-dialog title="港口码头主数据导入" append-to-body v-model="excelBox" width="500px">
<avue-form :option="excelOption" v-model="excelForm"> <avue-form :option="excelOption" v-model="excelForm">
<template #excelTemplate> <template #excelTemplate>
<el-button type="primary" @click="handleTemplate"> <el-button type="primary" @click="handleTemplate">
@@ -303,6 +325,7 @@ const removeExcelColumnsByHeaders = async (blob, options = {}) => {
return new Blob([buffer], { type: 'application/vnd.ms-excel' }); return new Blob([buffer], { type: 'application/vnd.ms-excel' });
}; };
const newLocal = '请选择类型';
export default { export default {
data() { data() {
const validateCode = (rule, value, callback) => { const validateCode = (rule, value, callback) => {
@@ -368,9 +391,10 @@ export default {
option: { option: {
height: 'auto', height: 'auto',
calcHeight: 32, calcHeight: 32,
dialogWidth: 980, dialogWidth: 900,
dialogCustomClass: 'port-terminal-edit-dialog',
labelPosition: 'right', labelPosition: 'right',
labelWidth: 'auto', labelWidth: '108px',
tip: false, tip: false,
searchShow: true, searchShow: true,
searchLabelWidth: 160, searchLabelWidth: 160,
@@ -396,7 +420,7 @@ export default {
formslot: true, formslot: true,
width: 140, width: 140,
span: 12, span: 12,
order: 70, order: 89,
placeholder: '请输入编码', placeholder: '请输入编码',
rules: [ rules: [
{ required: true, message: '请输入编码', trigger: 'blur' }, { required: true, message: '请输入编码', trigger: 'blur' },
@@ -412,7 +436,7 @@ export default {
search: true, search: true,
searchOrder: 7, searchOrder: 7,
span: 12, span: 12,
order: 80, order: 90,
placeholder: '请输入', placeholder: '请输入',
rules: [{ required: true, message: '请输入港口/码头名称', trigger: 'blur' }], rules: [{ required: true, message: '请输入港口/码头名称', trigger: 'blur' }],
}, },
@@ -444,7 +468,7 @@ export default {
dicData: [], dicData: [],
hide: true, hide: true,
span: 12, span: 12,
order: 90, order: 100,
placeholder: '请选择', placeholder: '请选择',
rules: [{ required: false, message: '请选择上级港口', trigger: 'change' }], rules: [{ required: false, message: '请选择上级港口', trigger: 'change' }],
change: ({ value }) => this.handleParentChange(value), change: ({ value }) => this.handleParentChange(value),
@@ -478,7 +502,7 @@ export default {
filterable: true, filterable: true,
dicData: [], dicData: [],
span: 12, span: 12,
order: 60, order: 89,
minWidth: 140, minWidth: 140,
overHidden: false, overHidden: false,
placeholder: '自动带出', placeholder: '自动带出',
@@ -492,7 +516,7 @@ export default {
formslot: true, formslot: true,
hide: true, hide: true,
span: 12, span: 12,
order: 50, order: 88,
placeholder: '自动带出', placeholder: '自动带出',
rules: [{ required: true, message: '请选择所属城市', trigger: 'change' }], rules: [{ required: true, message: '请选择所属城市', trigger: 'change' }],
}, },
@@ -515,6 +539,7 @@ export default {
type: 'select', type: 'select',
formslot: true, formslot: true,
hide: true, hide: true,
order: 87,
props: { props: {
label: 'title', label: 'title',
value: 'id', value: 'id',
@@ -543,7 +568,7 @@ export default {
formslot: true, formslot: true,
minWidth: 130, minWidth: 130,
span: 12, span: 12,
order: 20, order: 68,
placeholder: '请输入', placeholder: '请输入',
overHidden: false, overHidden: false,
rules: [ rules: [
@@ -557,7 +582,7 @@ export default {
formslot: true, formslot: true,
minWidth: 130, minWidth: 130,
span: 12, span: 12,
order: 10, order: 66,
placeholder: '请输入', placeholder: '请输入',
overHidden: false, overHidden: false,
rules: [ rules: [
@@ -578,13 +603,12 @@ export default {
{ {
label: '详细地址', label: '详细地址',
prop: 'detailAddress', prop: 'detailAddress',
type: 'textarea',
slot: true, slot: true,
minRows: 3, formslot: true,
span: 24, span: 12,
minWidth: 220, minWidth: 220,
overHidden: false, overHidden: false,
order: 30, order: 86,
placeholder: '请输入', placeholder: '请输入',
maxlength: 255, maxlength: 255,
showWordLimit: true, showWordLimit: true,
@@ -611,8 +635,9 @@ export default {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
formslot: true,
hide: true, hide: true,
maxlength: 200, maxlength: 200,
showWordLimit: true, showWordLimit: true,
@@ -805,9 +830,12 @@ export default {
this.clearCityValue(); this.clearCityValue();
}, },
handleCategoryChange(value, reset = true) { handleCategoryChange(value, reset = true) {
const required = value === '码头';
const parentColumn = this.findColumn(this.option.column, 'parentId'); const parentColumn = this.findColumn(this.option.column, 'parentId');
parentColumn.rules[0].required = value === '码头'; if (parentColumn && parentColumn.rules && parentColumn.rules[0]) {
this.setColumnDisplay('parentId', value === '码头'); parentColumn.rules[0].required = required;
}
this.setColumnDisplay('parentId', required);
if (value === '港口') { if (value === '港口') {
this.form.parentId = undefined; this.form.parentId = undefined;
this.form.parentCode = ''; this.form.parentCode = '';
@@ -1057,7 +1085,7 @@ export default {
return false; return false;
} }
if (isBlank(row.category)) { if (isBlank(row.category)) {
this.$message.warning('请选择类型'); this.$message.warning(newLocal);
return false; return false;
} }
if (row.category === '码头' && isBlank(row.parentId)) { if (row.category === '码头' && isBlank(row.parentId)) {
@@ -1209,6 +1237,7 @@ export default {
this.handleCategoryChange(this.form.category, false); this.handleCategoryChange(this.form.category, false);
this.syncTerminalCode(); this.syncTerminalCode();
done(); done();
setTimeout(() => this.disableDialogAutocomplete(), 50);
}); });
}); });
return; return;
@@ -1232,8 +1261,21 @@ export default {
this.handleDistrictChange(this.form.districtCode); this.handleDistrictChange(this.form.districtCode);
} }
done(); done();
setTimeout(() => this.disableDialogAutocomplete(), 50);
}); });
}, },
disableDialogAutocomplete() {
this.$nextTick(() => {
const dialog = document.querySelector('.port-terminal-edit-dialog');
if (!dialog) return;
dialog.querySelectorAll('input, textarea').forEach(el => {
el.setAttribute('autocomplete', 'off');
el.setAttribute('autocorrect', 'off');
el.setAttribute('autocapitalize', 'off');
el.setAttribute('spellcheck', 'false');
});
});
},
searchReset() { searchReset() {
this.query = {}; this.query = {};
this.setCityOptions([]); this.setCityOptions([]);
@@ -1338,3 +1380,44 @@ export default {
padding: 4px 0; padding: 4px 0;
} }
</style> </style>
<style lang="scss">
/* 港口码头编辑/新增弹窗:对齐 railway-station 统一风格(灰底 + 白卡表单 + 浮动底栏,padding 24px 与全局弹窗标准一致) */
//.port-terminal-edit-dialog {
// /* 灰底内容区 */
// .el-dialog__body {
// background-color: #f2f2f2;
// padding: 8px;
// }
// /* 表单白卡(与全局 .el-dialog .avue-form 一致,padding 24px 对齐 customer-archive / railway-station */
// .avue-form {
// background: #fff;
// border-radius: 6px;
// box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
// padding: 24px !important;
// margin-bottom: 0;
// }
// /* 底部按钮区白卡(Avue 弹窗 footer 在 body 内,接续白卡) */
// .avue-dialog__footer {
// background: #fff;
// border-radius: 0 0 6px 6px;
// box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
// padding: 16px 24px !important;
// display: flex;
// justify-content: flex-end;
// }
// /* label 宽度统一 108px(对齐 railway-station,标签对齐更整齐) */
// .el-form-item__label {
// width: 108px !important;
// }
// /* 所有 input 文本框、select 下拉控件统一宽度 250px */
// .el-input,
// .el-select {
// width: 250px !important;
// }
// /* 备注宽度 85% */
// .remark-input {
// width: 85% !important;
// }
//}
</style>
+15 -3
View File
@@ -202,8 +202,9 @@ export default {
height: 'auto', height: 'auto',
calcHeight: 32, calcHeight: 32,
dialogWidth: 980, dialogWidth: 980,
dialogCustomClass: 'railway-station-edit-dialog',
labelPosition: 'right', labelPosition: 'right',
labelWidth: 'auto', labelWidth: '140px',
tip: false, tip: false,
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
@@ -339,7 +340,7 @@ export default {
label: '详细地址', label: '详细地址',
prop: 'detailAddress', prop: 'detailAddress',
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 2,
span: 24, span: 24,
minWidth: 220, minWidth: 220,
overHidden: false, overHidden: false,
@@ -393,7 +394,7 @@ export default {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 2,
span: 24, span: 24,
hide: true, hide: true,
maxlength: 200, maxlength: 200,
@@ -892,5 +893,16 @@ export default {
:deep(.el-table td .cell) { :deep(.el-table td .cell) {
white-space: nowrap; white-space: nowrap;
} }
}
</style>
<style lang="scss">
/* 铁路车站编辑/新增弹窗:强制 label 宽度 140px(覆盖 Avue 默认 auto 计算值),灰底白卡与浮动底栏由全局 element-ui.scss 弹窗标准规则统一提供 */
.railway-station-edit-dialog {
.el-form-item__label {
width: 140px !important;
}
} }
</style> </style>
@@ -27,7 +27,7 @@
:icon="actionButtonLikeSearch ? undefined : 'el-icon-plus'" :icon="actionButtonLikeSearch ? undefined : 'el-icon-plus'"
v-if="canCreate" v-if="canCreate"
@click="$refs.crud.rowAdd()" @click="$refs.crud.rowAdd()"
>{{ config.createText || '新增' }} >{{ config.createText || '新增' }}
</el-button> </el-button>
<el-button <el-button
type="primary" type="primary"
@@ -39,7 +39,7 @@
!readonlyScope !readonlyScope
" "
@click="handleImport" @click="handleImport"
>{{ config.importText || '批量导入' }} >{{ config.importText || '批量导入' }}
</el-button> </el-button>
<el-button <el-button
type="primary" type="primary"
@@ -47,7 +47,7 @@
plain plain
v-if="config.templateUrl && hasPermission(`${config.permission}_template`)" v-if="config.templateUrl && hasPermission(`${config.permission}_template`)"
@click="handleTemplate" @click="handleTemplate"
>下载模板 >下载模板
</el-button> </el-button>
<el-button <el-button
type="primary" type="primary"
@@ -55,7 +55,7 @@
plain plain
v-if="config.exportUrl && hasPermission(`${config.permission}_export`)" v-if="config.exportUrl && hasPermission(`${config.permission}_export`)"
@click="handleExport" @click="handleExport"
>批量导出 >批量导出
</el-button> </el-button>
<el-button <el-button
type="success" type="success"
@@ -63,14 +63,14 @@
plain plain
v-if="canBatchComplete" v-if="canBatchComplete"
@click="handleBatchComplete" @click="handleBatchComplete"
>批量完成 >批量完成
</el-button> </el-button>
<el-button <el-button
type="primary" type="primary"
:plain="!actionButtonLikeSearch" :plain="!actionButtonLikeSearch"
v-if="canRoadLoading" v-if="canRoadLoading"
@click="handleRoadLoading" @click="handleRoadLoading"
>{{ config.roadLoadingText || '公路配载' }} >{{ config.roadLoadingText || '公路配载' }}
</el-button> </el-button>
<el-button <el-button
type="danger" type="danger"
@@ -82,7 +82,7 @@
!readonlyScope !readonlyScope
" "
@click="handleDelete" @click="handleDelete"
>批量删除 >批量删除
</el-button> </el-button>
</template> </template>
@@ -1130,20 +1130,20 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<template v-if="hasTransportType"> <template v-if="hasTransportType">
<el-form-item v-if="isCarrierMode" label="承运商" required> <el-form-item v-if="isCarrierMode" label="承运商" required>
<el-select <el-select
v-model="form.carrierName" v-model="form.carrierName"
placeholder="请选择承运商" placeholder="请选择承运商"
filterable filterable
clearable clearable
:loading="taskCarrierLoading" :loading="taskCarrierLoading"
:disabled="dialogReadonly || form.carrierType !== '承运商'" :disabled="dialogReadonly || form.carrierType !== '承运商'"
@visible-change="visible => visible && loadTaskCarrierOptions()" @visible-change="visible => visible && loadTaskCarrierOptions()"
@change="handleTaskCarrierChange" @change="handleTaskCarrierChange"
> >
<el-option <el-option
v-for="item in taskCarrierOptions" v-for="item in taskCarrierOptions"
:key=" :key="
item.id || item.id ||
item.customerName || item.customerName ||
item.carrierName || item.carrierName ||
@@ -1151,275 +1151,275 @@
item.name || item.name ||
item.customerCode item.customerCode
" "
:label="item.customerName || item.carrierName || item.fullName || item.name" :label="item.customerName || item.carrierName || item.fullName || item.name"
:value="item.customerName || item.carrierName || item.fullName || item.name" :value="item.customerName || item.carrierName || item.fullName || item.name"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="isRoadTransport"
label="司机"
:required="form.carrierType === '自运'"
>
<el-select
v-model="form.driverName"
placeholder="请选择或输入司机"
filterable
clearable
allow-create
default-first-option
:loading="taskDriverLoading"
:disabled="dialogReadonly"
@visible-change="visible => visible && loadTaskDriverOptions()"
@change="handleTaskDriverChange"
>
<el-option
v-for="item in taskDriverOptions"
:key="item.id || item.driverName || item.mobile"
:label="item.driverName || item.name"
:value="item.driverName || item.name"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="isRoadTransport"
label="手机号"
:required="form.carrierType === '自运'"
>
<el-input
v-model="form.driverPhone"
placeholder="请输入手机号"
clearable
maxlength="20"
:disabled="dialogReadonly"
/> />
</el-select> </el-form-item>
</el-form-item> <el-form-item :label="transportVehicleNoLabel" required>
<el-form-item <el-input
v-if="isRoadTransport" v-model="form.vehicleNo"
label="司机" :placeholder="`请输入${transportVehicleNoLabel}`"
:required="form.carrierType === '自运'" clearable
> maxlength="30"
<el-select :disabled="dialogReadonly"
v-model="form.driverName"
placeholder="请选择或输入司机"
filterable
clearable
allow-create
default-first-option
:loading="taskDriverLoading"
:disabled="dialogReadonly"
@visible-change="visible => visible && loadTaskDriverOptions()"
@change="handleTaskDriverChange"
>
<el-option
v-for="item in taskDriverOptions"
:key="item.id || item.driverName || item.mobile"
:label="item.driverName || item.name"
:value="item.driverName || item.name"
/> />
</el-select> </el-form-item>
</el-form-item> <el-form-item v-if="isNonRoadTransport" label="船长">
<el-form-item <el-input
v-if="isRoadTransport" v-model="form.captainName"
label="手机号" placeholder="请输入船长"
:required="form.carrierType === '自运'" clearable
> maxlength="20"
<el-input :disabled="dialogReadonly"
v-model="form.driverPhone"
placeholder="请输入手机号"
clearable
maxlength="20"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item :label="transportVehicleNoLabel" required>
<el-input
v-model="form.vehicleNo"
:placeholder="`请输入${transportVehicleNoLabel}`"
clearable
maxlength="30"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item v-if="isNonRoadTransport" label="船长">
<el-input
v-model="form.captainName"
placeholder="请输入船长"
clearable
maxlength="20"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item v-if="isNonRoadTransport && isCarrierMode" label="联系电话">
<el-input
v-model="form.driverPhone"
placeholder="请输入联系电话"
clearable
maxlength="20"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item v-if="isNonRoadTransport" label="箱号">
<el-input
v-model="form.containerNo"
placeholder="请输入箱号"
clearable
maxlength="30"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item v-if="isNonRoadTransport" label="舱位">
<el-input
v-model="form.cabinNo"
placeholder="请输入舱位"
clearable
maxlength="30"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item v-if="showRoadEscortFields" label="挂车车牌号">
<el-input
v-model="form.trailerVehicleNo"
placeholder="请输入挂车车牌号"
clearable
maxlength="30"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item v-if="showRoadEscortFields" label="押运人">
<el-input
v-model="form.escortName"
placeholder="请输入押运人"
clearable
maxlength="20"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item v-if="showRoadEscortFields" label="押运人手机号">
<el-input
v-model="form.escortPhone"
placeholder="请输入押运人手机号"
clearable
maxlength="20"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item label="货物类型" required>
<el-cascader
v-model="form.cargoTypePath"
:options="transportCargoTypeOptions"
:props="transportCargoTypeCascaderProps"
placeholder="请选择到二级"
clearable
filterable
:disabled="dialogReadonly"
:filter-method="filterBillingCargoType"
@visible-change="visible => visible && ensureBillingCargoTypeOptions()"
@change="handleTaskCargoTypeChange"
/>
</el-form-item>
<el-form-item label="货物名称">
<el-select
v-model="form.cargoName"
placeholder="请选择或输入货物"
filterable
allow-create
default-first-option
clearable
:disabled="dialogReadonly || !form.cargoType"
:loading="taskCargoLoading"
@visible-change="visible => visible && loadTaskCargoOptionsForForm()"
@change="handleTaskCargoChange"
>
<el-option
v-for="item in taskCargoOptions"
:key="item.id || item.cargoCode || item.cargoName"
:label="formatBillingCargoTypeLabel(item)"
:value="formatBillingCargoTypeLabel(item)"
/> />
</el-select> </el-form-item>
</el-form-item> <el-form-item v-if="isNonRoadTransport && isCarrierMode" label="联系电话">
<el-form-item label="规格"> <el-input
<el-input v-model="form.driverPhone"
v-model="form.specification" placeholder="请输入联系电话"
placeholder="选择货物自动回填" clearable
clearable maxlength="20"
:disabled="dialogReadonly" :disabled="dialogReadonly"
/> />
</el-form-item> </el-form-item>
<el-form-item label="号"> <el-form-item v-if="isNonRoadTransport" label="箱号">
<el-input <el-input
v-model="form.model" v-model="form.containerNo"
placeholder="选择货物自动回填" placeholder="请输入箱号"
clearable clearable
:disabled="dialogReadonly" maxlength="30"
/> :disabled="dialogReadonly"
</el-form-item> />
<el-form-item label="数量"> </el-form-item>
<el-input <el-form-item v-if="isNonRoadTransport" label="舱位">
v-model="form.quantity" <el-input
placeholder="请输入数量" v-model="form.cabinNo"
clearable placeholder="请输入舱位"
:disabled="dialogReadonly" clearable
@input="value => handleTaskNumberInput('quantity', value)" maxlength="30"
> :disabled="dialogReadonly"
<template #append> />
<el-select </el-form-item>
v-model="form.quantityUnit" <el-form-item v-if="showRoadEscortFields" label="挂车车牌号">
class="business-crud-page__append-select business-crud-page__append-select--wide" <el-input
placeholder="单位" v-model="form.trailerVehicleNo"
:disabled="dialogReadonly" placeholder="请输入挂车车牌号"
@visible-change="visible => visible && loadTaskQuantityUnitOptions()" clearable
> maxlength="30"
<el-option :disabled="dialogReadonly"
v-for="item in taskQuantityUnitOptions" />
:key="item.value" </el-form-item>
:label="item.label" <el-form-item v-if="showRoadEscortFields" label="押运人">
:value="item.value" <el-input
/> v-model="form.escortName"
</el-select> placeholder="请输入押运人"
</template> clearable
</el-input> maxlength="20"
</el-form-item> :disabled="dialogReadonly"
<el-form-item label="里程(km)"> />
<el-input </el-form-item>
v-model="form.mileage" <el-form-item v-if="showRoadEscortFields" label="押运人手机号">
placeholder="请输入里程" <el-input
clearable v-model="form.escortPhone"
maxlength="10" placeholder="请输入押运人手机号"
inputmode="numeric" clearable
:disabled="dialogReadonly" maxlength="20"
@input="handleTaskMileageInput" :disabled="dialogReadonly"
/> />
</el-form-item> </el-form-item>
<el-form-item :label="isRoadTransport ? '计划发货日期' : '预计发货日期'"> <el-form-item label="货物类型" required>
<el-date-picker <el-cascader
v-model="form.estimatedStartTime" v-model="form.cargoTypePath"
type="date" :options="transportCargoTypeOptions"
placeholder="请选择预计发货日期" :props="transportCargoTypeCascaderProps"
format="YYYY-MM-DD" placeholder="请选择到二级"
value-format="YYYY-MM-DD" clearable
:disabled="dialogReadonly" filterable
/> :disabled="dialogReadonly"
</el-form-item> :filter-method="filterBillingCargoType"
<el-form-item :label="isRoadTransport ? '计划完成日期' : '预计完成日期'"> @visible-change="visible => visible && ensureBillingCargoTypeOptions()"
<el-date-picker @change="handleTaskCargoTypeChange"
v-model="form.estimatedEndTime" />
type="date" </el-form-item>
placeholder="请选择预计完成日期" <el-form-item label="货物名称">
format="YYYY-MM-DD" <el-select
value-format="YYYY-MM-DD" v-model="form.cargoName"
:disabled="dialogReadonly" placeholder="请选择或输入货物"
/> filterable
</el-form-item> allow-create
<el-form-item label="单价"> default-first-option
<el-input clearable
v-model="form.unitPrice" :disabled="dialogReadonly || !form.cargoType"
placeholder="请输入单价" :loading="taskCargoLoading"
clearable @visible-change="visible => visible && loadTaskCargoOptionsForForm()"
:disabled="dialogReadonly" @change="handleTaskCargoChange"
@input="value => handleTaskNumberInput('unitPrice', value)" >
> <el-option
<template #append> v-for="item in taskCargoOptions"
<el-select :key="item.id || item.cargoCode || item.cargoName"
v-model="form.priceUnit" :label="formatBillingCargoTypeLabel(item)"
class="business-crud-page__append-select business-crud-page__append-select--wide" :value="formatBillingCargoTypeLabel(item)"
placeholder="单位" />
:disabled="dialogReadonly" </el-select>
@visible-change="visible => visible && loadTaskFeeUnitOptions()" </el-form-item>
> <el-form-item label="规格">
<el-option <el-input
v-for="item in taskFeeUnitOptions" v-model="form.specification"
:key="item.value" placeholder="选择货物自动回填"
:label="item.label" clearable
:value="item.value" :disabled="dialogReadonly"
/> />
</el-select> </el-form-item>
</template> <el-form-item label="型号">
</el-input> <el-input
</el-form-item> v-model="form.model"
<el-form-item label="其他费用合计"> placeholder="选择货物自动回填"
<el-input clearable
v-model="form.otherFeeTotal" :disabled="dialogReadonly"
placeholder="请输入其他费用合计" />
clearable </el-form-item>
:disabled="dialogReadonly" <el-form-item label="数量">
@input="value => handleTaskNumberInput('otherFeeTotal', value)" <el-input
/> v-model="form.quantity"
</el-form-item> placeholder="请输入数量"
<el-form-item label="备注" class="business-crud-page__task-remark"> clearable
<el-input :disabled="dialogReadonly"
v-model="form.taskRemark" @input="value => handleTaskNumberInput('quantity', value)"
type="textarea" >
:rows="2" <template #append>
maxlength="200" <el-select
show-word-limit v-model="form.quantityUnit"
placeholder="请输入备注,200字以内" class="business-crud-page__append-select business-crud-page__append-select--wide"
:disabled="dialogReadonly" placeholder="单位"
/> :disabled="dialogReadonly"
</el-form-item> @visible-change="visible => visible && loadTaskQuantityUnitOptions()"
>
<el-option
v-for="item in taskQuantityUnitOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item label="里程(km)">
<el-input
v-model="form.mileage"
placeholder="请输入里程"
clearable
maxlength="10"
inputmode="numeric"
:disabled="dialogReadonly"
@input="handleTaskMileageInput"
/>
</el-form-item>
<el-form-item :label="isRoadTransport ? '计划发货日期' : '预计发货日期'">
<el-date-picker
v-model="form.estimatedStartTime"
type="date"
placeholder="请选择预计发货日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item :label="isRoadTransport ? '计划完成日期' : '预计完成日期'">
<el-date-picker
v-model="form.estimatedEndTime"
type="date"
placeholder="请选择预计完成日期"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
:disabled="dialogReadonly"
/>
</el-form-item>
<el-form-item label="单价">
<el-input
v-model="form.unitPrice"
placeholder="请输入单价"
clearable
:disabled="dialogReadonly"
@input="value => handleTaskNumberInput('unitPrice', value)"
>
<template #append>
<el-select
v-model="form.priceUnit"
class="business-crud-page__append-select business-crud-page__append-select--wide"
placeholder="单位"
:disabled="dialogReadonly"
@visible-change="visible => visible && loadTaskFeeUnitOptions()"
>
<el-option
v-for="item in taskFeeUnitOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item label="其他费用合计">
<el-input
v-model="form.otherFeeTotal"
placeholder="请输入其他费用合计"
clearable
:disabled="dialogReadonly"
@input="value => handleTaskNumberInput('otherFeeTotal', value)"
/>
</el-form-item>
<el-form-item label="备注" class="business-crud-page__task-remark">
<el-input
v-model="form.taskRemark"
type="textarea"
:rows="2"
maxlength="200"
show-word-limit
placeholder="请输入备注,200字以内"
:disabled="dialogReadonly"
/>
</el-form-item>
</template> </template>
</el-form> </el-form>
</div> </div>
@@ -2285,7 +2285,7 @@
</template> </template>
<template v-else> <template v-else>
<el-link type="primary" v-if="showDetailButton(row)" @click="openDetail(row)" <el-link type="primary" v-if="showDetailButton(row)" @click="openDetail(row)"
>详情</el-link >详情</el-link
> >
<el-link <el-link
type="primary" type="primary"
@@ -2376,8 +2376,8 @@
><strong>{{ ><strong>{{
detailRow.departureName || detailRow.departureAddress || '-' detailRow.departureName || detailRow.departureAddress || '-'
}}</strong }}</strong
><b class="end"></b ><b class="end"></b
><strong>{{ detailRow.arrivalName || detailRow.arrivalAddress || '-' }}</strong> ><strong>{{ detailRow.arrivalName || detailRow.arrivalAddress || '-' }}</strong>
</div> </div>
<div class="business-crud-page__waybill-route-text"> <div class="business-crud-page__waybill-route-text">
{{ detailRow.departureAddress || '-' }}  {{ detailRow.arrivalAddress || '-' }} {{ detailRow.departureAddress || '-' }}  {{ detailRow.arrivalAddress || '-' }}
@@ -2417,7 +2417,7 @@
<el-table-column prop="deviceCode" label="设备编码" min-width="130" /> <el-table-column prop="deviceCode" label="设备编码" min-width="130" />
<el-table-column prop="brand" label="品牌" min-width="110" /> <el-table-column prop="brand" label="品牌" min-width="110" />
<el-table-column label="规格型号" min-width="140" <el-table-column label="规格型号" min-width="140"
><template #default="{ row }">{{ ><template #default="{ row }">{{
[row.specification, row.model].filter(Boolean).join('/') || '-' [row.specification, row.model].filter(Boolean).join('/') || '-'
}}</template></el-table-column }}</template></el-table-column
> >
@@ -2439,13 +2439,13 @@
> >
<span>司机</span <span>司机</span
><strong ><strong
>{{ detailRow.driverName || '-' }} {{ detailRow.driverPhone || '' }}</strong >{{ detailRow.driverName || '-' }} {{ detailRow.driverPhone || '' }}</strong
> >
</div> </div>
<div class="business-crud-page__waybill-detail-field"> <div class="business-crud-page__waybill-detail-field">
<span>{{ <span>{{
waybillIsRoadTransport(detailRow) ? '车牌号' : '航班号/船次号/班列号' waybillIsRoadTransport(detailRow) ? '车牌号' : '航班号/船次号/班列号'
}}</span }}</span
><strong>{{ detailRow.vehicleNo || '-' }}</strong> ><strong>{{ detailRow.vehicleNo || '-' }}</strong>
</div> </div>
<div <div
@@ -2460,8 +2460,8 @@
> >
<span>押运人</span <span>押运人</span
><strong ><strong
>{{ detailRow.escortName || '-' }} {{ detailRow.escortPhone || '' }}</strong >{{ detailRow.escortName || '-' }} {{ detailRow.escortPhone || '' }}</strong
> >
</div> </div>
<div <div
v-if="!waybillIsRoadTransport(detailRow)" v-if="!waybillIsRoadTransport(detailRow)"
@@ -2514,7 +2514,7 @@
v-for="(node, index) in waybillDetailProcessNodes" v-for="(node, index) in waybillDetailProcessNodes"
:key="node.key || index" :key="node.key || index"
:timestamp="node.time || ''" :timestamp="node.time || ''"
>{{ node.name || node.nodeName || node.label }}</el-timeline-item >{{ node.name || node.nodeName || node.label }}</el-timeline-item
> >
</el-timeline> </el-timeline>
<el-empty v-else description="暂无打卡详情" :image-size="50" /> <el-empty v-else description="暂无打卡详情" :image-size="50" />
@@ -2550,7 +2550,7 @@
<template #extra> <template #extra>
<div class="business-crud-page__waybill-track-actions"> <div class="business-crud-page__waybill-track-actions">
<el-button plain @click="handleWaybillTrackAction('playback')" <el-button plain @click="handleWaybillTrackAction('playback')"
>轨迹回放</el-button >轨迹回放</el-button
> >
<el-button plain @click="handleWaybillTrackAction('locate')">实时定位</el-button> <el-button plain @click="handleWaybillTrackAction('locate')">实时定位</el-button>
</div> </div>
@@ -2924,7 +2924,7 @@
<el-button type="primary">添加附件</el-button> <el-button type="primary">添加附件</el-button>
</el-upload> </el-upload>
<span class="business-crud-page__import-file-tip" <span class="business-crud-page__import-file-tip"
>请上传计划明细表仅支持 Excel 格式</span >请上传计划明细表仅支持 Excel 格式</span
> >
<el-link type="primary" @click="handleTransportPlanTemplate">下载模板</el-link> <el-link type="primary" @click="handleTransportPlanTemplate">下载模板</el-link>
</el-form-item> </el-form-item>
@@ -3030,7 +3030,7 @@
type="primary" type="primary"
:loading="transportPlanImportLoading" :loading="transportPlanImportLoading"
@click="submitTransportPlanImport" @click="submitTransportPlanImport"
>提交</el-button >提交</el-button
> >
<el-button @click="transportPlanImportBox = false">返回</el-button> <el-button @click="transportPlanImportBox = false">返回</el-button>
</template> </template>
@@ -3835,7 +3835,7 @@
<el-table-column label="操作" width="100" align="center" fixed="right"> <el-table-column label="操作" width="100" align="center" fixed="right">
<template #default="{ $index }"> <template #default="{ $index }">
<el-link type="danger" @click="removeDispatchItemAttachment($index)" <el-link type="danger" @click="removeDispatchItemAttachment($index)"
>删除</el-link >删除</el-link
> >
</template> </template>
</el-table-column> </el-table-column>
@@ -4505,7 +4505,7 @@
<div class="business-crud-page__map-info"> <div class="business-crud-page__map-info">
<span>{{ transportMapStatus }}</span> <span>{{ transportMapStatus }}</span>
<span v-if="transportMapSelected.regionName" <span v-if="transportMapSelected.regionName"
>行政区划{{ transportMapSelected.regionName }}</span >行政区划{{ transportMapSelected.regionName }}</span
> >
</div> </div>
<template #footer> <template #footer>
@@ -5422,9 +5422,9 @@ export default {
this.getDispatchQuantityUnit(row), this.getDispatchQuantityUnit(row),
'total', 'total',
row.quantity || row.quantity ||
row.cargoQuantity || row.cargoQuantity ||
row.goodsQuantity || row.goodsQuantity ||
row.totalQuantity || row.totalQuantity ||
row.totalCargoQuantity row.totalCargoQuantity
); );
}); });
@@ -6206,8 +6206,8 @@ export default {
const taskInfo = this.parseJsonObject(this.detailRow.taskInfoJson); const taskInfo = this.parseJsonObject(this.detailRow.taskInfoJson);
this.waybillRouteChangeRecords = Array.isArray(taskInfo.routeChangeRecords) this.waybillRouteChangeRecords = Array.isArray(taskInfo.routeChangeRecords)
? [...taskInfo.routeChangeRecords].sort((a, b) => ? [...taskInfo.routeChangeRecords].sort((a, b) =>
String(b.changeTime).localeCompare(String(a.changeTime)) String(b.changeTime).localeCompare(String(a.changeTime))
) )
: []; : [];
}, },
openWaybillRouteChangeDialog() { openWaybillRouteChangeDialog() {
@@ -6302,8 +6302,8 @@ export default {
const content = changed const content = changed
? `${row.waybillNo || '运单'}:发货地 ${row.originalDepartureAddress || '-'}${ ? `${row.waybillNo || '运单'}:发货地 ${row.originalDepartureAddress || '-'}${
row.departureAddress || '-' row.departureAddress || '-'
}到货地 ${row.originalArrivalAddress || '-'} ${row.arrivalAddress || '-'}` }到货地 ${row.originalArrivalAddress || '-'} ${row.arrivalAddress || '-'}`
: '调整运输路线顺序'; : '调整运输路线顺序';
const records = [ const records = [
{ {
@@ -8031,21 +8031,21 @@ export default {
const goodsRows = this.isTaskFullMode const goodsRows = this.isTaskFullMode
? this.transportCargoRows.map(item => this.normalizeTransportCargoRow(item)) ? this.transportCargoRows.map(item => this.normalizeTransportCargoRow(item))
: [ : [
{ {
cargoType: row.cargoType, cargoType: row.cargoType,
cargoTypeCode: row.cargoTypeCode, cargoTypeCode: row.cargoTypeCode,
cargoTypePath: row.cargoTypePath, cargoTypePath: row.cargoTypePath,
cargoName: row.cargoName, cargoName: row.cargoName,
specification: row.specification, specification: row.specification,
model: row.model, model: row.model,
quantity: row.quantity, quantity: row.quantity,
quantityUnit: row.quantityUnit, quantityUnit: row.quantityUnit,
mileage: row.mileage, mileage: row.mileage,
unitPrice: row.unitPrice, unitPrice: row.unitPrice,
priceUnit: row.priceUnit, priceUnit: row.priceUnit,
remark: row.taskRemark, remark: row.taskRemark,
}, },
]; ];
if (this.isTaskFullMode) { if (this.isTaskFullMode) {
const firstCargo = goodsRows[0] || {}; const firstCargo = goodsRows[0] || {};
taskInfo.unitPrice = firstCargo.unitPrice || ''; taskInfo.unitPrice = firstCargo.unitPrice || '';
@@ -9398,8 +9398,8 @@ export default {
const children = const children =
level === 1 level === 1
? (cargoType.children || []) ? (cargoType.children || [])
.map(item => this.normalizeBillingCargoTypeNode(item, level + 1, path)) .map(item => this.normalizeBillingCargoTypeNode(item, level + 1, path))
.filter(Boolean) .filter(Boolean)
: []; : [];
return { return {
...cargoType, ...cargoType,
@@ -9466,8 +9466,8 @@ export default {
const children = const children =
level === 1 level === 1
? (region.children || []) ? (region.children || [])
.map(item => this.normalizeBillingMatchRegionNode(item, level + 1)) .map(item => this.normalizeBillingMatchRegionNode(item, level + 1))
.filter(Boolean) .filter(Boolean)
: []; : [];
return { return {
...region, ...region,
@@ -11008,8 +11008,8 @@ export default {
mode === 'draft' mode === 'draft'
? '生成草稿成功' ? '生成草稿成功'
: shouldCompletePlan : shouldCompletePlan
? '确认生成成功,运输计划已完成' ? '确认生成成功,运输计划已完成'
: '确认生成成功'; : '确认生成成功';
this.$message.success(message); this.$message.success(message);
this.dispatchBox = false; this.dispatchBox = false;
this.onLoad(this.page, this.query); this.onLoad(this.page, this.query);
+1 -1
View File
@@ -2348,7 +2348,7 @@ export default {
.loading-detail { .loading-detail {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; //gap: 8px;
color: #303133; color: #303133;
.loading-detail__summary { display: flex; align-items: center; flex-wrap: wrap; gap: 24px; padding: 4px 0 16px; } .loading-detail__summary { display: flex; align-items: center; flex-wrap: wrap; gap: 24px; padding: 4px 0 16px; }
.loading-detail__heading { font-size: 20px; font-weight: 600; margin-right: 8px; } .loading-detail__heading { font-size: 20px; font-weight: 600; margin-right: 8px; }
+1 -1
View File
@@ -416,7 +416,7 @@ export default {
.master-list-panel { .master-list-panel {
background: #fff; background: #fff;
.toolbar { .toolbar {
padding: 12px 12px 0; padding: 8px;
} }
} }
.master-card { .master-card {
+84 -115
View File
@@ -80,106 +80,100 @@
</template> </template>
<template #basicInfo-form> <template #basicInfo-form>
<div class="process-config-page__section"> <section-card title="基本信息">
<div class="dialog-section-title">基本信息</div> <el-form
<el-row :gutter="16"> :model="form"
<el-col :span="8"> label-position="right"
<div class="process-config-page__field"> label-width="calc(6em + 24px)"
<span >
class="process-config-page__field-label process-config-page__field-label--required" <el-row :gutter="18">
> <el-col :span="6">
配置名称 <el-form-item label="配置名称" required>
</span>
<el-input
v-model="form.configName"
:disabled="dialogReadonly"
maxlength="100"
placeholder="请输入"
/>
</div>
</el-col>
<el-col :span="8">
<div class="process-config-page__field">
<span
class="process-config-page__field-label process-config-page__field-label--required"
>
项目
</span>
<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>
</div>
</el-col>
<el-col :span="8">
<div class="process-config-page__field">
<span class="process-config-page__field-label">运输完成时限</span>
<div class="process-config-page__finish-days">
<span>默认</span>
<el-input <el-input
v-model="form.defaultFinishDays" v-model="form.configName"
:disabled="dialogReadonly" :disabled="dialogReadonly"
maxlength="3" maxlength="100"
placeholder="请输入" placeholder="请输入"
@input="handleFinishDaysInput"
/> />
<span>天后完成运输</span> </el-form-item>
</div> </el-col>
</div> <el-col :span="6">
</el-col> <el-form-item label="项目" required>
<el-col :span="24"> <el-select
<div class="process-config-page__field"> v-model="selectedProjectId"
<span class="process-config-page__field-label">备注</span> clearable
<el-input filterable
v-model="form.remark" remote
type="textarea" :remote-method="loadProjectOptions"
:rows="4" :loading="projectLoading"
:disabled="dialogReadonly" :disabled="dialogReadonly"
maxlength="500" placeholder="请选择"
show-word-limit style="width: 100%"
placeholder="请输入" @change="handleProjectChange"
/> >
</div> <el-option
</el-col> v-for="item in projectOptions"
</el-row> :key="item.id"
</div> :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>
<template #nodeConfigJson-form> <template #nodeConfigJson-form>
<div class="process-config-page__custom-form"> <div class="process-config-page__custom-form">
<div class="dialog-section-title">现行过程节点</div> <section-card title="现行过程节点">
<div class="process-config-page__timeline" v-if="enabledNodes.length"> <div class="process-config-page__timeline" v-if="enabledNodes.length">
<div class="process-config-page__timeline-line"></div> <div class="process-config-page__timeline-line"></div>
<div <div
v-for="node in enabledNodes" v-for="node in enabledNodes"
:key="node.key" :key="node.key"
class="process-config-page__timeline-item" class="process-config-page__timeline-item"
> >
<span class="process-config-page__timeline-dot"></span> <span class="process-config-page__timeline-dot"></span>
<div class="process-config-page__timeline-name">{{ node.name }}</div> <div class="process-config-page__timeline-name">{{ node.name }}</div>
<div class="process-config-page__timeline-desc"> <div class="process-config-page__timeline-desc">
<div v-for="text in timelineDescriptions(node)" :key="text">{{ text }}</div> <div v-for="text in timelineDescriptions(node)" :key="text">{{ text }}</div>
</div>
</div> </div>
</div> </div>
</div> <el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" />
<el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" /> </section-card>
<div class="dialog-section-title">节点设置</div> <section-card title="节点设置">
<el-table <el-table
class="process-config-page__node-table" class="process-config-page__node-table"
border border
@@ -363,6 +357,7 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</section-card>
</div> </div>
</template> </template>
@@ -1106,32 +1101,6 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.process-config-page { .process-config-page {
&__section {
width: 100%;
}
&__field {
display: flex;
align-items: flex-start;
gap: 10px;
margin-bottom: 16px;
}
&__field-label {
flex: 0 0 150px;
line-height: 32px;
color: #303133;
font-weight: 500;
text-align: right;
white-space: nowrap;
&--required::before {
margin-right: 4px;
color: #f56c6c;
content: '*';
}
}
&__node-value { &__node-value {
white-space: normal; white-space: normal;
word-break: break-all; word-break: break-all;
+5 -5
View File
@@ -1908,7 +1908,7 @@ export default {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
column-gap: 72px; column-gap: 72px;
row-gap: 0; row-gap: 0;
margin-bottom: 16px; margin-bottom: 12px;
background: #fff; background: #fff;
border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px;
padding: 14px 16px 4px; padding: 14px 16px 4px;
@@ -1934,7 +1934,7 @@ export default {
&__table { &__table {
width: 100%; width: 100%;
margin-bottom: 16px; margin-bottom: 12px;
background: #fff; background: #fff;
border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px;
padding: 12px; padding: 12px;
@@ -1952,7 +1952,7 @@ export default {
} }
&__textarea-list { &__textarea-list {
margin-bottom: 16px; margin-bottom: 12px;
background: #fff; background: #fff;
border-radius: 0 0 6px 6px; border-radius: 0 0 6px 6px;
padding: 14px 16px 4px; padding: 14px 16px 4px;
@@ -1975,7 +1975,7 @@ export default {
} }
&__material-card { &__material-card {
margin-bottom: 16px; margin-bottom: 12px;
background: #fff; background: #fff;
border-radius: 6px; border-radius: 6px;
padding: 14px 16px; padding: 14px 16px;
@@ -2016,7 +2016,7 @@ export default {
margin: 0 0 16px; margin: 0 0 16px;
background: #fff; background: #fff;
border-radius: 6px; border-radius: 6px;
padding: 12px; padding: 12px 0;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
} }
+3 -3
View File
@@ -200,7 +200,7 @@ export default {
prop: 'oldData', prop: 'oldData',
type: 'textarea', type: 'textarea',
span: 24, span: 24,
minRows: 3, minRows: 2,
hide: true, hide: true,
}, },
{ {
@@ -208,7 +208,7 @@ export default {
prop: 'newData', prop: 'newData',
type: 'textarea', type: 'textarea',
span: 24, span: 24,
minRows: 3, minRows: 2,
hide: true, hide: true,
}, },
{ {
@@ -216,7 +216,7 @@ export default {
prop: 'recordResult', prop: 'recordResult',
type: 'textarea', type: 'textarea',
span: 24, span: 24,
minRows: 3, minRows: 2,
hide: true, hide: true,
}, },
{ {
+1 -1
View File
@@ -153,7 +153,7 @@ const option = reactive({
url: 'link', url: 'link',
}, },
hide: true, hide: true,
minRows: 4, minRows: 2,
span: 24, span: 24,
}, },
], ],
+1 -1
View File
@@ -155,7 +155,7 @@ export default {
url: 'link', url: 'link',
}, },
hide: true, hide: true,
minRows: 4, minRows: 2,
span: 24, span: 24,
}, },
+18 -6
View File
@@ -21,12 +21,24 @@
<el-tag>{{ row.suspensionState === 1 ? '激活' : '挂起' }}</el-tag> <el-tag>{{ row.suspensionState === 1 ? '激活' : '挂起' }}</el-tag>
</template> </template>
</avue-crud> </avue-crud>
<el-dialog title="流程删除" append-to-body v-model="followBox" width="20%"> <el-dialog
<el-form :model="form" ref="form" label-width="auto"> title="流程删除"
<el-form-item label="删除理由"> append-to-body
<el-input v-model="deleteReason" placeholder="请输入删除理由" /> v-model="followBox"
</el-form-item> width="400px"
</el-form> class="dialog-form--carded"
>
<section-card title="删除理由">
<el-form :model="form" ref="form" label-position="right" label-width="calc(6em + 24px)">
<el-row :gutter="18">
<el-col :span="24">
<el-form-item label="删除理由">
<el-input v-model="deleteReason" placeholder="请输入删除理由" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</section-card>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="followBox = false"> </el-button> <el-button @click="followBox = false"> </el-button>
+26 -14
View File
@@ -81,20 +81,32 @@
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
<el-dialog title="流程变更" append-to-body v-model="stateBox" width="20%"> <el-dialog
<el-form :model="form" ref="form" label-width="auto"> title="流程变更"
<el-form-item label="流程状态"> append-to-body
<el-select v-model="flowState" placeholder="请选择" value=""> v-model="stateBox"
<el-option width="400px"
v-for="item in stateOptions" class="dialog-form--carded"
:key="item.value" >
:label="item.label" <section-card title="流程状态">
:value="item.value" <el-form :model="form" ref="form" label-position="right" label-width="calc(6em + 24px)">
> <el-row :gutter="18">
</el-option> <el-col :span="24">
</el-select> <el-form-item label="流程状态">
</el-form-item> <el-select v-model="flowState" placeholder="请选择" value="">
</el-form> <el-option
v-for="item in stateOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</section-card>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="stateBox = false"> </el-button> <el-button @click="stateBox = false"> </el-button>
+81 -43
View File
@@ -61,38 +61,60 @@
</el-drawer> </el-drawer>
<!-- 手动锁定用户 --> <!-- 手动锁定用户 -->
<el-dialog title="锁定用户" append-to-body v-model="lockUserBox" width="500px"> <el-dialog
<el-form :model="lockUserForm" label-width="auto" :rules="lockUserRules" ref="lockUserFormRef"> title="锁定用户"
<el-form-item label="用户账号"> append-to-body
<el-input :model-value="lockUserForm.account" disabled /> v-model="lockUserBox"
</el-form-item> width="520px"
<el-form-item label="锁定原因" prop="lockReason"> class="dialog-form--carded"
<el-input >
v-model="lockUserForm.lockReason" <section-card title="锁定信息">
type="textarea" <el-form
:rows="3" :model="lockUserForm"
placeholder="请输入锁定原因" label-position="right"
/> label-width="calc(6em + 24px)"
</el-form-item> :rules="lockUserRules"
<el-form-item label="锁定开始" prop="lockBeginTime"> ref="lockUserFormRef"
<el-date-picker >
v-model="lockUserForm.lockBeginTime" <el-row :gutter="18">
type="datetime" <el-col :span="24">
placeholder="不填则立即生效" <el-form-item label="用户账号">
value-format="YYYY-MM-DD HH:mm:ss" <el-input :model-value="lockUserForm.account" disabled />
style="width: 100%" </el-form-item>
/> </el-col>
</el-form-item> <el-col :span="24">
<el-form-item label="锁定结束" prop="lockEndTime"> <el-form-item label="锁定原因" prop="lockReason">
<el-date-picker <el-input
v-model="lockUserForm.lockEndTime" v-model="lockUserForm.lockReason"
type="datetime" type="textarea"
placeholder="不填则永久锁定" :rows="3"
value-format="YYYY-MM-DD HH:mm:ss" placeholder="请输入锁定原因"
style="width: 100%" />
/> </el-form-item>
</el-form-item> </el-col>
</el-form> <el-col :span="24">
<el-form-item label="锁定开始" prop="lockBeginTime">
<el-date-picker
v-model="lockUserForm.lockBeginTime"
type="datetime"
placeholder="不填则立即生效"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="锁定结束" prop="lockEndTime">
<el-date-picker
v-model="lockUserForm.lockEndTime"
type="datetime"
placeholder="不填则永久锁定"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</section-card>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="lockUserBox = false"> </el-button> <el-button @click="lockUserBox = false"> </el-button>
@@ -102,17 +124,33 @@
</el-dialog> </el-dialog>
<!-- 解锁原因确认 --> <!-- 解锁原因确认 -->
<el-dialog title="解锁确认" append-to-body v-model="unlockReasonBox" width="450px"> <el-dialog
<el-form :model="unlockReasonForm" label-width="auto"> title="解锁确认"
<el-form-item label="解锁原因"> append-to-body
<el-input v-model="unlockReasonBox"
v-model="unlockReasonForm.unlockReason" width="520px"
type="textarea" class="dialog-form--carded"
:rows="3" >
placeholder="请输入解锁原因(可选)" <section-card title="解锁原因">
/> <el-form
</el-form-item> :model="unlockReasonForm"
</el-form> label-position="right"
label-width="calc(6em + 24px)"
>
<el-row :gutter="18">
<el-col :span="24">
<el-form-item label="解锁原因">
<el-input
v-model="unlockReasonForm.unlockReason"
type="textarea"
:rows="3"
placeholder="请输入解锁原因(可选)"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</section-card>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="unlockReasonBox = false"> </el-button> <el-button @click="unlockReasonBox = false"> </el-button>
+46 -28
View File
@@ -126,37 +126,55 @@
<el-dialog <el-dialog
:title="title" :title="title"
v-model="box" v-model="box"
width="50%" width="560px"
:before-close="beforeClose" :before-close="beforeClose"
append-to-body append-to-body
class="dialog-form--carded"
> >
<el-form :disabled="view" ref="form" :model="form" label-width="auto"> <section-card title="参数信息">
<!-- 表单字段 --> <el-form
<el-form-item label="参数名:" prop="paramName"> :disabled="view"
<el-input v-model="form.paramName" placeholder="请输入参数名" /> ref="form"
</el-form-item> :model="form"
<el-form-item prop="paramKey"> label-position="right"
<template #label> label-width="calc(6em + 24px)"
<el-tooltip content="参数键为系统内部唯一标识,请勿随意修改" placement="top"> >
<el-icon style="margin-right: 4px; vertical-align: middle; color: #909399; cursor: pointer"><el-icon-question-filled /></el-icon> <el-row :gutter="18">
</el-tooltip> <el-col :span="24">
<span>参数键:</span> <el-form-item label="参数名" prop="paramName">
</template> <el-input v-model="form.paramName" placeholder="请输入参数名" />
<el-input v-model="form.paramKey" placeholder="请输入参数键" /> </el-form-item>
</el-form-item> </el-col>
<el-form-item prop="paramValue"> <el-col :span="24">
<template #label> <el-form-item prop="paramKey">
<el-tooltip content="包含敏感关键词的配置不展示具体数值" placement="top"> <template #label>
<el-icon style="margin-right: 4px; vertical-align: middle; color: #909399; cursor: pointer"><el-icon-question-filled /></el-icon> <el-tooltip content="参数键为系统内部唯一标识,请勿随意修改" placement="top">
</el-tooltip> <el-icon style="margin-right: 4px; vertical-align: middle; color: #909399; cursor: pointer"><el-icon-question-filled /></el-icon>
<span>参数值:</span> </el-tooltip>
</template> <span>参数键</span>
<el-input v-model="form.paramValue" placeholder="请输入参数值" /> </template>
</el-form-item> <el-input v-model="form.paramKey" placeholder="请输入参数键" />
<el-form-item label="备注:" prop="remark"> </el-form-item>
<el-input v-model="form.remark" placeholder="请输入备注" /> </el-col>
</el-form-item> <el-col :span="24">
</el-form> <el-form-item prop="paramValue">
<template #label>
<el-tooltip content="包含敏感关键词的配置不展示具体数值" placement="top">
<el-icon style="margin-right: 4px; vertical-align: middle; color: #909399; cursor: pointer"><el-icon-question-filled /></el-icon>
</el-tooltip>
<span>参数值</span>
</template>
<el-input v-model="form.paramValue" placeholder="请输入参数值" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</section-card>
<!-- 表单按钮 --> <!-- 表单按钮 -->
<template #footer> <template #footer>
<span v-if="!view" class="dialog-footer"> <span v-if="!view" class="dialog-footer">
+1 -1
View File
@@ -216,7 +216,7 @@ export default {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
span: 24, span: 24,
minRows: 3, minRows: 2,
hide: true, hide: true,
type: 'textarea', type: 'textarea',
}, },
+53 -34
View File
@@ -181,27 +181,29 @@
top="5vh" top="5vh"
append-to-body append-to-body
destroy-on-close destroy-on-close
class="user-edit-dialog" class="user-edit-dialog dialog-form--carded"
> >
<template #header> <template #header>
<span class="dialog-title">{{ userDialogMode === 'add' ? '新增用户' : '编辑用户' }}</span> <span class="dialog-title">{{ userDialogMode === 'add' ? '新增用户' : '编辑用户' }}</span>
</template> </template>
<el-form ref="userFormRef" :model="form" :rules="userRules" label-position="right" label-width="120px"> <section-card title="用户信息">
<el-row :gutter="20"> <el-form ref="userFormRef" :model="form" :rules="userRules" label-position="right" label-width="calc(6em + 24px)">
<el-col :span="6"><el-form-item label="账号名" prop="account"><el-input v-model="form.account" /></el-form-item></el-col> <el-row :gutter="18">
<el-col :span="6"><el-form-item label="名" prop="realName"><el-input v-model="form.realName" /></el-form-item></el-col> <el-col :span="6"><el-form-item label="账号名" prop="account"><el-input v-model="form.account" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="手机号" prop="phone"><el-input v-model="form.phone" /></el-form-item></el-col> <el-col :span="6"><el-form-item label="姓名" prop="realName"><el-input v-model="form.realName" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="邮箱"><el-input v-model="form.email" /></el-form-item></el-col> <el-col :span="6"><el-form-item label="手机号" prop="phone"><el-input v-model="form.phone" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="性别"><el-select v-model="form.sex" class="full-width"><el-option label="男" :value="1" /><el-option label="女" :value="2" /><el-option label="未知" :value="3" /></el-select></el-form-item></el-col> <el-col :span="6"><el-form-item label="邮箱"><el-input v-model="form.email" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="岗位" prop="postId"><el-tree-select v-model="form.postId" :data="postList" :props="{ label: 'postName', value: 'id' }" check-strictly class="full-width" /></el-form-item></el-col> <el-col :span="6"><el-form-item label="性别"><el-select v-model="form.sex"><el-option label="男" :value="1" /><el-option label="女" :value="2" /><el-option label="未知" :value="3" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="所属组织" prop="deptId"><el-tree-select v-model="form.deptId" :data="permissionDeptTree" :props="{ label: 'title', value: 'id' }" multiple check-strictly show-checkbox class="full-width" /></el-form-item></el-col> <el-col :span="6"><el-form-item label="岗位" prop="postId"><el-tree-select v-model="form.postId" :data="postList" :props="{ label: 'postName', value: 'id' }" check-strictly /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="工号"><el-input v-model="form.code" /></el-form-item></el-col> <el-col :span="6"><el-form-item label="所属组织" prop="deptId"><el-tree-select v-model="form.deptId" :data="permissionDeptTree" :props="{ label: 'title', value: 'id' }" multiple check-strictly show-checkbox /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="人员类别"><el-select v-model="form.personCategory" class="full-width"><el-option label="内部员工" :value="1" /><el-option label="承运商" :value="2" /></el-select></el-form-item></el-col> <el-col :span="6"><el-form-item label="工号"><el-input v-model="form.code" /></el-form-item></el-col>
<el-col :span="18"><el-form-item label="数据权限范围"><el-radio-group v-model="form.dataScopeRange"><el-radio :value="1">仅所属组织</el-radio><el-radio :value="2">全部组织</el-radio><el-radio :value="3">自定义</el-radio></el-radio-group></el-form-item></el-col> <el-col :span="6"><el-form-item label="人员类别"><el-select v-model="form.personCategory"><el-option label="内部员工" :value="1" /><el-option label="承运商" :value="2" /></el-select></el-form-item></el-col>
<el-col :span="18" :offset="6"><el-form-item label="数据层级范围"><el-radio-group v-model="form.dataLevelRange"><el-radio :value="1">包含下级</el-radio><el-radio :value="2">仅本级</el-radio></el-radio-group></el-form-item></el-col> <el-col :span="18"><el-form-item label="数据权限范围"><el-radio-group v-model="form.dataScopeRange"><el-radio :value="1">仅所属组织</el-radio><el-radio :value="2">全部组织</el-radio><el-radio :value="3">自定义</el-radio></el-radio-group></el-form-item></el-col>
<el-col :span="24"><el-form-item label="备注"><el-input v-model="form.remark" type="textarea" :rows="3" maxlength="200" show-word-limit /></el-form-item></el-col> <el-col :span="18" :offset="6"><el-form-item label="数据层级范围"><el-radio-group v-model="form.dataLevelRange"><el-radio :value="1">包含下级</el-radio><el-radio :value="2">仅本级</el-radio></el-radio-group></el-form-item></el-col>
</el-row> <el-col :span="24"><el-form-item label="备注"><el-input v-model="form.remark" type="textarea" :rows="3" maxlength="200" show-word-limit /></el-form-item></el-col>
</el-form> </el-row>
</el-form>
</section-card>
<el-tabs class="user-permission-tabs"> <el-tabs class="user-permission-tabs">
<el-tab-pane label="已拥有角色"> <el-tab-pane label="已拥有角色">
<el-table :data="formRoleList" border> <el-table :data="formRoleList" border>
@@ -288,23 +290,40 @@
</el-dialog> </el-dialog>
<!-- 管理员修改密码 --> <!-- 管理员修改密码 -->
<el-dialog title="修改密码" append-to-body v-model="passwordBox" width="460px"> <el-dialog
<el-form title="修改密码"
ref="passwordFormRef" append-to-body
:model="passwordForm" v-model="passwordBox"
:rules="passwordRules" width="520px"
label-width="auto" class="dialog-form--carded"
> >
<el-form-item label="账号名"> <section-card title="密码信息">
<el-input v-model="passwordForm.account" disabled /> <el-form
</el-form-item> ref="passwordFormRef"
<el-form-item label="新密码" prop="password"> :model="passwordForm"
<el-input v-model="passwordForm.password" type="password" show-password /> :rules="passwordRules"
</el-form-item> label-position="right"
<el-form-item label="确认密码" prop="password2"> label-width="calc(6em + 24px)"
<el-input v-model="passwordForm.password2" type="password" show-password /> >
</el-form-item> <el-row :gutter="18">
</el-form> <el-col :span="24">
<el-form-item label="账号名">
<el-input v-model="passwordForm.account" disabled />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="新密码" prop="password">
<el-input v-model="passwordForm.password" type="password" show-password />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="确认密码" prop="password2">
<el-input v-model="passwordForm.password2" type="password" show-password />
</el-form-item>
</el-col>
</el-row>
</el-form>
</section-card>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="passwordBox = false"> </el-button> <el-button @click="passwordBox = false"> </el-button>
+1 -1
View File
@@ -217,7 +217,7 @@ export default {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
span: 24, span: 24,
minRows: 3, minRows: 2,
hide: true, hide: true,
type: 'textarea', type: 'textarea',
}, },
+169 -167
View File
@@ -967,179 +967,181 @@
class="score-detail-dialog" class="score-detail-dialog"
@closed="resetScoreDialog" @closed="resetScoreDialog"
> >
<el-form <section-card>
ref="scoreForm" <el-form
:model="currentScore" ref="scoreForm"
label-position="right" :model="currentScore"
label-width="auto" label-position="right"
:disabled="readonly" label-width="auto"
class="score-detail-form" :disabled="readonly"
> class="score-detail-form"
<el-row :gutter="42"> >
<el-col :span="12"> <el-row :gutter="42">
<el-form-item label="评定日期" required> <el-col :span="12">
<el-date-picker <el-form-item label="评定日期" required>
v-model="currentScore.scoreDate"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="拟申请总资金使用额度(万元)" required>
<el-input
v-model="currentScore.applyCreditLimit"
maxlength="18"
@input="value => handleScoreDecimalInput('applyCreditLimit', value)"
/>
</el-form-item>
<el-form-item label="最终得分">
<el-input :model-value="formatScoreValue(currentScore.finalScore)" disabled />
</el-form-item>
<el-form-item label="临时额度申请使用期限">
<div class="score-detail-form__range">
<el-date-picker <el-date-picker
v-model="currentScore.tempCreditStartDate" v-model="currentScore.scoreDate"
type="date" type="date"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
/> />
<span>至</span> </el-form-item>
<el-date-picker <el-form-item label="拟申请总资金使用额度(万元)" required>
v-model="currentScore.tempCreditEndDate" <el-input
type="date" v-model="currentScore.applyCreditLimit"
value-format="YYYY-MM-DD" maxlength="18"
@input="value => handleScoreDecimalInput('applyCreditLimit', value)"
/> />
</div> </el-form-item>
</el-form-item> <el-form-item label="最终得分">
</el-col> <el-input :model-value="formatScoreValue(currentScore.finalScore)" disabled />
<el-col :span="12"> </el-form-item>
<el-form-item label="最大资金使用额度(万元)"> <el-form-item label="临时额度申请使用期限">
<el-input <div class="score-detail-form__range">
:model-value="formatScoreValue(currentScore.maxCreditLimit)" <el-date-picker
disabled v-model="currentScore.tempCreditStartDate"
/> type="date"
</el-form-item> value-format="YYYY-MM-DD"
<el-form-item label="信用等级"> />
<el-input :model-value="formatScoreValue(currentScore.creditLevel)" disabled /> <span>至</span>
</el-form-item> <el-date-picker
<el-form-item label="临时申请额度"> v-model="currentScore.tempCreditEndDate"
<el-input type="date"
v-model="currentScore.tempApplyCreditLimit" value-format="YYYY-MM-DD"
maxlength="18" />
@input="value => handleScoreDecimalInput('tempApplyCreditLimit', value)" </div>
/> </el-form-item>
</el-form-item> </el-col>
</el-col> <el-col :span="12">
<el-col :span="24"> <el-form-item label="最大资金使用额度(万元)">
<el-form-item label="备注"> <el-input
<el-input v-model="currentScore.remark" maxlength="200" /> :model-value="formatScoreValue(currentScore.maxCreditLimit)"
</el-form-item> disabled
</el-col>
<el-col :span="24">
<el-form-item label="评分量化表" required>
<el-select
v-model="currentScore.quantificationId"
filterable
clearable
:loading="scoreQuantificationLoading"
placeholder="请选择评分量化表"
@change="handleScoreQuantificationChange"
>
<el-option
v-for="item in scoreQuantificationOptions"
:key="item.id"
:label="item.name"
:value="String(item.id)"
/> />
</el-select> </el-form-item>
</el-form-item> <el-form-item label="信用等级">
</el-col> <el-input :model-value="formatScoreValue(currentScore.creditLevel)" disabled />
</el-row> </el-form-item>
</el-form> <el-form-item label="临时申请额度">
<el-input
v-model="currentScore.tempApplyCreditLimit"
maxlength="18"
@input="value => handleScoreDecimalInput('tempApplyCreditLimit', value)"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input v-model="currentScore.remark" maxlength="200" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="评分量化表" required>
<el-select
v-model="currentScore.quantificationId"
filterable
clearable
:loading="scoreQuantificationLoading"
placeholder="请选择评分量化表"
@change="handleScoreQuantificationChange"
>
<el-option
v-for="item in scoreQuantificationOptions"
:key="item.id"
:label="item.name"
:value="String(item.id)"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table <el-table
v-if="currentScore.quantificationId" v-if="currentScore.quantificationId"
ref="scoreCategoryTable" ref="scoreCategoryTable"
:data="scoreCategoryRows" :data="scoreCategoryRows"
border border
:show-header="false" :show-header="false"
row-key="categoryCode" row-key="categoryCode"
:expand-row-keys="expandedScoreCategoryKeys" :expand-row-keys="expandedScoreCategoryKeys"
class="score-category-table" class="score-category-table"
@row-click="toggleScoreCategory" @row-click="toggleScoreCategory"
@expand-change="handleScoreCategoryExpandChange" @expand-change="handleScoreCategoryExpandChange"
> >
<el-table-column type="expand" width="1" class-name="score-category-table__expand-column"> <el-table-column type="expand" width="1" class-name="score-category-table__expand-column">
<template #default="{ row }"> <template #default="{ row }">
<el-table <el-table
:data="getScoreCategoryDetails(row.categoryCode)" :data="getScoreCategoryDetails(row.categoryCode)"
border border
class="score-detail-table score-detail-table--inline" class="score-detail-table score-detail-table--inline"
max-height="520" max-height="520"
> >
<el-table-column label="评分项目" prop="itemName" width="150" align="center" /> <el-table-column label="评分项目" prop="itemName" width="150" align="center" />
<el-table-column label="评分标准" min-width="430"> <el-table-column label="评分标准" min-width="430">
<template #default="{ row: detail }"> <template #default="{ row: detail }">
<div class="score-standard-cell"> <div class="score-standard-cell">
<div class="score-standard-cell__label">请选择:</div> <div class="score-standard-cell__label">请选择:</div>
<el-select <el-select
v-model="detail.selectedOption" v-model="detail.selectedOption"
filterable filterable
:disabled="readonly" :disabled="readonly"
@change="scoreOptionChange(detail, $event)" @change="scoreOptionChange(detail, $event)"
>
<el-option
v-for="item in parseScoreOptions(detail.optionsJson)"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</template>
</el-table-column>
<el-table-column label="得分说明" prop="scoreDescription" min-width="160" />
<el-table-column label="自评得分" width="130" align="center">
<template #default="{ row: detail }">
<span>{{ formatScoreValue(getSignedScore(detail, 'selfScore')) }}分</span>
</template>
</el-table-column>
<el-table-column label="复评得分" width="150" align="center">
<template #default="{ row: detail }">
<el-input
v-model="detail.reviewScore"
maxlength="10"
inputmode="numeric"
:disabled="readonly || !hasPermission('customer_type_re_cert')"
@input="value => handleScoreDetailScoreInput(detail, 'reviewScore', value)"
> >
<el-option <template v-if="isMinusScoreDetail(detail) && Number(detail.reviewScore) > 0" #prefix>
v-for="item in parseScoreOptions(detail.optionsJson)" -
:key="item.value" </template>
:label="item.label" <template #suffix>分</template>
:value="item.value" </el-input>
/> </template>
</el-select> </el-table-column>
</div> </el-table>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="得分说明" prop="scoreDescription" min-width="160" /> <el-table-column label="序号" prop="index" width="50" align="center" />
<el-table-column label="自评得分" width="130" align="center"> <el-table-column min-width="560">
<template #default="{ row: detail }"> <template #default="{ row }">
<span>{{ formatScoreValue(getSignedScore(detail, 'selfScore')) }}</span> <span class="score-category-table__name">{{ row.categoryName }}</span>
</template> <span>自评:{{ getSignedScore(row, 'selfScore') }}分</span>
</el-table-column> <span>复评:{{ getSignedScore(row, 'reviewScore') }}分</span>
<el-table-column label="复评得分" width="150" align="center"> </template>
<template #default="{ row: detail }"> </el-table-column>
<el-input <el-table-column width="60" align="center">
v-model="detail.reviewScore" <template #default="{ row }">
maxlength="10" <el-icon
inputmode="numeric" class="score-category-table__arrow"
:disabled="readonly || !hasPermission('customer_type_re_cert')" :class="{ 'is-expanded': isScoreCategoryExpanded(row.categoryCode) }"
@input="value => handleScoreDetailScoreInput(detail, 'reviewScore', value)" >
> <ArrowRight />
<template v-if="isMinusScoreDetail(detail) && Number(detail.reviewScore) > 0" #prefix> </el-icon>
- </template>
</template> </el-table-column>
<template #suffix>分</template> </el-table>
</el-input> </section-card>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="序号" prop="index" width="50" align="center" />
<el-table-column min-width="560">
<template #default="{ row }">
<span class="score-category-table__name">{{ row.categoryName }}</span>
<span>自评:{{ getSignedScore(row, 'selfScore') }}分</span>
<span>复评:{{ getSignedScore(row, 'reviewScore') }}分</span>
</template>
</el-table-column>
<el-table-column width="60" align="center">
<template #default="{ row }">
<el-icon
class="score-category-table__arrow"
:class="{ 'is-expanded': isScoreCategoryExpanded(row.categoryCode) }"
>
<ArrowRight />
</el-icon>
</template>
</el-table-column>
</el-table>
<section-card title="证明材料" class="score-material-card"> <section-card title="证明材料" class="score-material-card">
<template #extra> <template #extra>
@@ -3797,7 +3799,7 @@ export default {
} }
.archive-detail-card { .archive-detail-card {
margin-top: 8px; margin-top: 12px;
} }
.archive-tabs { .archive-tabs {
:deep(.el-tabs__header) { :deep(.el-tabs__header) {
@@ -3849,7 +3851,7 @@ export default {
.score-category-table { .score-category-table {
width: calc(100% - 72px); width: calc(100% - 72px);
margin: 8px 36px 0; margin: 8px 36px 16px;
:deep(.el-table__body td) { :deep(.el-table__body td) {
height: 56px; height: 56px;
+1 -1
View File
@@ -62,7 +62,7 @@ export default ({
}, },
}, },
// server: { // server: {
// port: 2888, // port: 2889,
// proxy: { // proxy: {
// '/api': { // '/api': {
// target: 'http://172.16.203.228:8000', // target: 'http://172.16.203.228:8000',