Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 819a59e6fc | |||
| f663098b4a | |||
| ef417a0290 | |||
| e5a7aca09e | |||
| 4d0cc2d595 | |||
| f6451643e8 | |||
| 8dddb72328 | |||
| fa99cc3eff | |||
| 433c611195 | |||
| 6cf535cc79 | |||
| e683c2cc00 | |||
| 3268f12501 | |||
| f9f8221870 | |||
| 81c98f6ad8 | |||
| 6a4c5d02f4 | |||
| 70856ca44c | |||
| dd857414c9 | |||
| 4383e9956e | |||
| 79f8fbad1d | |||
| 70779fcf63 | |||
| 71dd52c650 | |||
| 7f01b119b5 | |||
| d1c8786043 | |||
| 368e027426 | |||
| c270258b7b | |||
| a9fd78b5b9 | |||
| e799b20428 | |||
| 638d09b19d | |||
| 06dc1c64f6 | |||
| 9b7f8db96b | |||
| 449719dfe1 | |||
| 81b2a3e99b | |||
| ccaca521d3 | |||
| af0675f26b | |||
| 89c4f0d4df | |||
| 08ec2389a5 | |||
| 46d34f489e | |||
| ee84cad033 | |||
| 17df5e8cbe | |||
| 780968b68f | |||
| de8a87af6c | |||
| ff91e8dbd7 | |||
| 90d96e01a4 | |||
| a71d2c9350 | |||
| a1c8e7c1ce | |||
| 6e71c38dad | |||
| d62f8bf320 | |||
| 5a66c89349 | |||
| 0b2e07f1fe | |||
| 1434bbf691 | |||
| c7e67a83b7 | |||
| d48b18c99e | |||
| 72c6abf122 | |||
| e460813480 | |||
| 6eba9d2c2f | |||
| 38ce8fa2bc | |||
| 8002fe3d50 | |||
| c695d72ec8 | |||
| 8ff9f6bb66 | |||
| e76cf70a20 | |||
| 1c7532e0de | |||
| e50d1b8fda | |||
| 76df2b9cd2 |
@@ -3,6 +3,8 @@
|
|||||||
VITE_APP_ENV = 'development'
|
VITE_APP_ENV = 'development'
|
||||||
|
|
||||||
#接口地址
|
#接口地址
|
||||||
|
# 开发环境建议填 [/api]:由下方 vite.config.mjs 的 proxy 同源转发到后端(172.16.203.228:8000),避免跨域(CORS)被浏览器拦截
|
||||||
|
# 如需直连线上绝对地址(如 http://172.16.203.228:8000/api),必须让后端 CORS 把 Allow-Origin 改为具体前端域名,不能用 `*`(配合 credentials 会被浏览器拒绝)
|
||||||
VITE_APP_API=/api
|
VITE_APP_API=/api
|
||||||
|
|
||||||
#调试参数
|
#调试参数
|
||||||
|
|||||||
3
.workbuddy/memory/2025-07-29.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
## 2025-07-29
|
||||||
|
|
||||||
|
- 货物类型管理页面(cargo-type):搜索栏「类型」和「货物类型编码」字段 searchSpan 从 12 分别调整为 6 和 8,收窄 input 宽度使两字段在一排内紧凑展示
|
||||||
77
.workbuddy/memory/2026-07-27.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# 2026-07-27 工作日志
|
||||||
|
|
||||||
|
## 开发环境启动与登录排查
|
||||||
|
|
||||||
|
- 终止了遗留的 2888 端口 dev server 进程,清理端口占用。
|
||||||
|
- 将 `.env.development` 的 `VITE_APP_API` 从 `http://172.16.203.228:8000/api` 改为 `/api`,让前端请求走 Vite 代理。
|
||||||
|
- 将 `vite.config.mjs` 的 `/api` 代理 target 从 `http://localhost` 改为 `http://172.16.203.228:8000`,并去掉 `rewrite`(后端接口本身就在 `/api` 前缀下,不能去掉)。
|
||||||
|
- 修复后发现登录无响应的根因:后端 CORS 返回 `Access-Control-Allow-Origin: *`,与 axios `withCredentials: true` 冲突,浏览器拦截所有跨域请求;走 Vite 代理后同源,CORS 问题消失。
|
||||||
|
- 启动 dev server 于 `http://localhost:2888`。
|
||||||
|
- 使用 agent-browser(系统 Chrome)打开登录页,填入账号 `admin` / 密码 `admin`,成功触发行为验证码弹窗。
|
||||||
|
- 行为验证码(滑块/拼图)需人工在浏览器窗口完成。
|
||||||
|
|
||||||
|
## 货物类型导入模板模拟数据
|
||||||
|
|
||||||
|
- 模板:`/Users/gxwebsoft/Downloads/货物类型导入模板.xlsx`,单 Sheet「货物类型导入模板」,表头 6 列:类型(必填)、上级货物类型、上级货物类型编码、货物类型(必填)、货物类型编码(必填)、备注。一级类型上级字段留空。
|
||||||
|
- 在 `/Users/gxwebsoft/Downloads/货物类型导入模板_模拟数据.xlsx` 生成 5 条模拟数据(2 条一级 + 3 条二级,演示层级)。原模板保持不变。
|
||||||
|
|
||||||
|
## 货物类型模块(/base/cargo-type)按需求完善
|
||||||
|
|
||||||
|
- 需求:新增默认二级;类型/上级/编码在编辑查看禁编辑;一级隐藏上级字段、二级显示;同上级名称唯一 + 编码全局唯一交后端;提交失败展示后端提示。
|
||||||
|
- 抽出 `src/option/base/cargo-type.js`,导出工厂 `getCargoTypeOption(ctx)`,依赖组件的校验/change 通过 `ctx` 闭包访问(`ctx.form`、`ctx.handleTypeLevelChange` 等),避免 Option API 写死 this。
|
||||||
|
- `cargo-type.vue` 改动:import 该 option;新增默认 `typeLevel:2`;`beforeOpen` 设置 `dialogType`(add/edit/view);上级下拉框 `:disabled="dialogType!=='add' || typeLevel!==2"`;列配置加 `editDisabled:true`(类型/编码/上级编码)控制编辑禁用;view 模式 Avue 自动禁用其余字段。
|
||||||
|
- 提交失败处理:axios 拦截器已对非 200 弹 `ElMessage`(后端 msg),故 rowSave/rowUpdate 的 error 仅 `loading()`,不再 console/重复 toast。
|
||||||
|
- 导入失败明细下载已合规:`src/utils/import-excel.js` 的 `handleImportExcel` 已实现 content-type 区分 JSON/Excel、失败下载 `货物类型导入失败明细时间.xlsx`、错误提示;businessName='货物类型'。
|
||||||
|
- 注意:导入/下载模板由后端 `/blade-system/cargo-type/import-cargo-type`、`/export-template` 控制,前端模板列名由后端决定,需后端保证与需求卡字段一致。
|
||||||
|
|
||||||
|
## 货物类型批量导入失败排查(19:12)
|
||||||
|
|
||||||
|
- 失败明细 `货物类型导入失败明细2026-07-27 19_12_24.xlsx`:5 条全部「请选择货物类型级别」。
|
||||||
|
- 根因(数据问题,非前端代码):模拟数据「类型」列误填为业务分类 `普通货物/冷链货物`,但需求卡 REQ-CARGO-007/008 规定「类型」是**货物类型级别**,仅允许填 `一级货物类型`/`二级货物类型`;且编码误用字母(`GOODS-ELEC-001`),违反 REQ-CARGO-006「一级 2 位数字、二级 4 位数字」。
|
||||||
|
- 已重造 `货物类型导入模板_模拟数据.xlsx`:类型改为一级/二级;编码改为纯数字(01/02 一级,0101/0102/0201 二级继承父级前 2 位)。
|
||||||
|
- 风险:二级行依赖一级行已存在,若后端按 DB 校验而非按文件顺序处理,二级行可能报「请选择上级货物类型」,建议先导入 2 条一级、再导入 3 条二级。
|
||||||
|
|
||||||
|
## 货物类型导入失败复查(23:27)
|
||||||
|
|
||||||
|
- 第二版失败明细 `货物类型导入失败明细2026-07-27 19_17_21.xlsx`:类型已正确,但一级报「货物类型编码格式不正确」、二级报「请选择上级货物类型」。
|
||||||
|
- 根因:编码列被存成**数字(int)**,前导零丢失('01'→1、'0101'→101),一级编码非 2 位、二级非 4 位;一级失败未入库 → 二级找不到上级。
|
||||||
|
- 修复:写入时强制 C/E 列 `number_format='@'`(文本)保留前导零;编码 '01'/'02'、'0101'/'0102'/'0201'。
|
||||||
|
- 为消除级联风险,拆成两个文件:货物类型导入_一级.xlsx(2条)、货物类型导入_二级.xlsx(3条),先导入一级再导入二级确保成功。
|
||||||
|
|
||||||
|
## 货物类型导入第三次复查(23:30)
|
||||||
|
|
||||||
|
- 第三版失败明细:一级导入也失败,报「该货物类型编码已存在」(01/02 已被占用)。根因:01/02 极可能是用户此前测试新增功能时手动建的,导入撞车;失败导入不写库,说明编码 pre-exist。
|
||||||
|
- 同期发现 2888 dev server 进程退出(lsof 无监听),导致 Vite 代理对 localhost:2888 全返回 502(含根路径)。已重启 `pnpm dev`(端口 2888,proxy target 172.16.203.228:8000),代理恢复 200。后端直连一直正常。
|
||||||
|
- 改用新编码重造:一级 11/12(电子产品/生鲜食品),二级 1101/1102(父11)、1201(父12),文本格式保留前导零。三份文件(一级/二级/合并)已更新。
|
||||||
|
- 结论:导入功能本身 OK,问题一直是造数(类型值、编码格式、编码冲突)+ dev server 偶发退出。建议导入前确认 dev server 在跑。
|
||||||
|
|
||||||
|
## 导入失败明细标红 + 原因改写(23:50)
|
||||||
|
|
||||||
|
- 需求:导入失败后,失败明细 Excel 中**仅违规那一栏标红**,且「导入失败原因」列改写为清晰格式,如`(第2行:货物类型编码格式不正确,一级2位数字,二级4位数字)`。
|
||||||
|
- 现状:失败明细 Excel 此前是后端生成、前端 `import-excel.js` 直接 `downloadXls` 原样下载,无加工。
|
||||||
|
- 改动:
|
||||||
|
1. `pnpm add exceljs`(4.4.0,运行时依赖;`import('exceljs')` 动态加载,不进主包)。
|
||||||
|
2. `src/utils/import-excel.js`:`openImportDialog` 增加可选 `options.failDetailDecorator`;`handleImportExcel` 在 Excel 响应分支用 exceljs 读取后端失败明细 blob → 调用 decorator 加工(标红+改写原因)→ 再下载。**未传 decorator 的模块保持原行为(向后兼容、通用)**。
|
||||||
|
3. `src/views/base/cargo-type.vue`:新增模块级 `decorateCargoTypeFailDetail(workbook)`,建立「表头列名→列号」映射,按错误文本匹配规则(7 类错误 → 标红列 + 规则说明),遍历数据行标红违规栏并将原因列改写为`(第N行:错误,规则)`;`handleImport` 传入 `{ failDetailDecorator: decorateCargoTypeFailDetail }`。标红填充色 `FFFFC7CE`(淡红),物理行号(表头第1行,数据第2行起)。
|
||||||
|
- 验证:Node + exceljs 跑 decorator 等价逻辑全 PASS(标红列命中、原因格式正确);vite 将 `import('exceljs')` 重写为浏览器版 chunk(/node_modules/.vite/deps/exceljs.js,HTTP 200,1.46MB),浏览器运行时无 polyfill 报错;cargo-type.vue 与 import-excel.js 经 vite 编译均 200。
|
||||||
|
- 注意:decorator 依赖后端失败明细 Excel 的「导入失败原因」列文本与模板列名(类型/上级货物类型/上级货物类型编码/货物类型/货物类型编码/备注/导入失败原因)精确一致;若后端改列名需同步更新 `CARGO_TYPE_FAIL_RULES` 的 col 值。
|
||||||
|
|
||||||
|
## 导入失败明细改为「不标红 + 加列宽」(00:08 次晨)
|
||||||
|
|
||||||
|
- 用户反馈两点:① 不要标红,只写清错误原因即可;② 失败明细 xls 列太挤,需加宽。
|
||||||
|
- 改动(同一对文件):
|
||||||
|
- `src/views/base/cargo-type.vue`:删除 `FAIL_RED_FILL` 常量与所有 `cell.fill` 标红逻辑,仅保留原因列改写为`(第N行:错误,规则)`;新增 `CARGO_TYPE_FAIL_COL_WIDTH` 列宽映射(类型14/上级货物类型16/上级货物类型编码20/货物类型16/货物类型编码16/备注18/导入失败原因60),遍历 colMap 设置 `ws.getColumn(n).width`;原因列额外 `alignment={wrapText:true,vertical:'top'}` 提升可读性。
|
||||||
|
- `src/utils/import-excel.js`:注释由「标红 / 改写原因列」改为中性「改写原因列、调整列宽等加工」。
|
||||||
|
- 验证:Node + exceljs 等价逻辑全 PASS(无红色填充=✅、原因含「第N行」、导入失败原因列宽=60);cargo-type.vue 与 import-excel.js vite 编译均 200,FAIL_RED_FILL 残留=0。
|
||||||
|
|
||||||
|
## 下载模板改为「前端本地生成 + 带示例」(00:11 次晨)
|
||||||
|
|
||||||
|
- 需求:点击「下载模板」给的导入模板要自带一个数据示例(参照可正常导入的 `货物类型导入模板_模拟数据.xlsx`)。
|
||||||
|
- 现状:`handleTemplate` 原调用后端 `/blade-system/cargo-type/export-template` 下载空模板(无示例)。
|
||||||
|
- 改动 `src/views/base/cargo-type.vue` 的 `handleTemplate`:改为 `import('exceljs')` 本地生成模板,不再依赖后端空模板。
|
||||||
|
- 表头严格使用真实模板列名(含 `*` 与括号说明):`*类型` / `上级货物类型(如为一级则不需填写)` / `上级货物类型编码(如为一级则不需填写)` / `*货物类型` / `*货物类型编码` / `备注`(与可正常导入的本地模板一致)。
|
||||||
|
- 示例数据 2 条:一级 `电子产品2/117` + 二级 `手机2/11014`(父117),演示层级,取值与用户确认可导入的模拟数据一致。
|
||||||
|
- 列宽加宽(类型14/上级货物类型24/上级货物类型编码26/货物类型16/货物类型编码16/备注18);编码列(3、5) `numFmt='@'` 文本格式防前导零丢失;表头行 `wrapText` 完整显示长说明。
|
||||||
|
- 下载文件名仍为 `货物类型导入模板.xlsx`。`exportBlob` 仍被 `handleExport` 使用,import 不冗余。
|
||||||
|
- 验证:Node + exceljs 等价逻辑确认表头/示例行/列宽/文本格式正确(稀疏 eachCell 跳过空单元格导致一次断言误报,按列号复核确认数据无误);cargo-type.vue vite 编译 200。
|
||||||
|
- 注意:示例行若被直接导入会创建 `电子产品2/手机2` 两条演示数据;用户应按需删除/替换示例再填自己的数据。
|
||||||
53
.workbuddy/memory/2026-07-28.md
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# 2026-07-28 工作日志
|
||||||
|
|
||||||
|
## 货物类型导入模板美化
|
||||||
|
- 文件:`src/views/base/cargo-type.vue` 的 `handleTemplate()`
|
||||||
|
- 改动(第一次):表头行加主色底色 `#409EFF` + 白色加粗字体 + 居中对齐 + 细边框;行高 42。
|
||||||
|
- 改动(调整后):按用户反馈,表头底色改为统一灰色 `#D9D9D9` + 黑色加粗字体,行高降为 30。
|
||||||
|
- 导入失败明细 `decorateCargoTypeFailDetail` 调整:仅「导入失败原因」列字体红色;错误按 `A./B./C.` 编号,分号(;)隔开,并去掉后端重复的「第N行:」前缀;最终格式示例 `第2行:A.该货物类型编码已存在,请更换唯一编码`。
|
||||||
|
- 验证:Node + exceljs 4.4.0 跑通生成逻辑,确认表头 fill/font/alignment/height、失败原因编号格式与红色字体均正确。
|
||||||
|
|
||||||
|
## 货物类型导入失败明细 - 备注超长与标红强化
|
||||||
|
- 确认需求:除「导入失败原因」列外,其他列一律不标红;已增加 decorator 清除所有非失败原因列红色字体(含类型列,不论对错)。
|
||||||
|
- 失败原因按 A./B./C. 编号、分号(;)隔开;并优化:错误文本已包含规则说明时不重复拼接(避免「备注不能超过200字,备注不能超过200字」)。
|
||||||
|
- 新增兜底:失败明细行若「备注」列文本长度 > 200 且失败原因未含备注错误,自动追加一条「备注不能超过200字」编号项(Node 验证通过)。
|
||||||
|
- 后端根因(已读 /Users/gxwebsoft/JAVA/tms-erp-api-ws/blade-service/blade-system/.../CargoTypeServiceImpl.java):validate() 用 throw 实现,一行多个错误时只抛第一个,备注超长校验(第238行)可能被前置的编码/名称/上级错误挡住,导致失败明细不显示备注原因。彻底方案需后端改收集式校验(列出全部错误),待用户确认是否改 Java。
|
||||||
|
- **最终确认(样式)**:decorator 仅操作 G 列「导入失败原因」——黑色字体(argb `FF000000`)、无背景填充(fill→none);其余列单元格样式/内容不修改。
|
||||||
|
- **列宽修复(关键 bug)**:失败明细列宽之前全部失效,根因是 `CARGO_TYPE_FAIL_COL_WIDTH` 的 key 用了「类型/上级货物类型」等简写,而后端 `CargoTypeImportFailureExcel` 表头带 `*` 与括号说明(如 `*类型`、`上级货物类型(如为一级则不需填写)`),key 对不上导致走默认 18。已把 key 改为与后端表头完全一致,并恢复「给所有列设宽」逻辑。最终宽度:`*类型`16 / `上级货物类型(…)`22 / `上级货物类型编码(…)`26 / `*货物类型`18 / `*货物类型编码`18 / `备注`24 / `导入失败原因`70。Node 验证通过。
|
||||||
|
- **事务性导入(后端改动)**:`CargoTypeServiceImpl.importCargoType` 加 `@Transactional(rollbackFor=Exception.class)`,逐条 validate+save 后若有任一失败则 `TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()` 回滚整批,实现"全部正确才入库,任一错误则一条都不存"。需重新编译部署 tms-erp-api-ws 后端生效。
|
||||||
|
|
||||||
|
## 国标 GB-T 42820-2023 数据 → cargo-type 导入(分析+转换)
|
||||||
|
- 源文件:`/Users/gxwebsoft/Downloads/副本货物类型导入模板_模拟数据(1).xlsx`,单 Sheet,A1 是标题,真实表头在第 2 行。
|
||||||
|
- 源列:一级编码(A,2位)、一级类型(B)、二级编码(C,仅序号)、二级类型(D)、完整国标编码(E,4位)、一级类型/编码(F)、(G空)、(H标注不可靠)。
|
||||||
|
- 关键规则:二级真实编码 = E 列后 2 位,必须**忽略 C 列序号**;E 前 2 位 = A。116 行全为二级明细,唯一一级 19 个(01-99)。无重码、名称≤14字、无备注。
|
||||||
|
- 映射:系统 6 列模板(`*类型`/`上级货物类型(…)`/`上级货物类型编码(…)`/`*货物类型`/`*货物类型编码`/`备注`)。一级行=类型一级、上级空、名称=B、编码=A;二级行=类型二级、上级名称=B、上级编码=A、名称=D、编码=E。
|
||||||
|
- 已生成预览/导入文件(按系统模板表头,编码列设文本格式):`/Users/gxwebsoft/VUE/tms-erp-web-ws/import-cargo-type/货物类型导入_一级.xlsx`(19 条)、`货物类型导入_二级.xlsx`(116 条)。
|
||||||
|
- 用户确认:一级+二级都导、手动页面上传、测试/空环境直接导。导入动作由用户在系统"货物类型-批量导入"完成(两阶段:先一级后二级)。
|
||||||
|
- 后端导入机制补充(读 CargoTypeServiceImpl.importCargoType):逐行 build→validate→save,挂 @Transactional;二级父级解析走 `findParentByCode` 查库。因同事务同连接,前面已 save 的一级对后续二级查询可见 → **单文件(一级行严格在前、二级在后)也能一次性成功**。但整法"全有或全无":任一失败行触发 setRollbackOnly 回滚整批。分两文件主要规避"顺序依赖+全批回滚"两风险。
|
||||||
|
- 已新增单文件版:`/Users/gxwebsoft/VUE/tms-erp-web-ws/import-cargo-type/货物类型导入_单文件(一级在前).xlsx`(一级19条在前+二级116条在后,共135数据行)。
|
||||||
|
- 美化:对 import-cargo-type 下 3 个 xlsx 表头统一加样式(灰底 #D9D9D9 + 黑色加粗居中 + 细边框 #D0D7E2 + 行高30),数据区细边框、编码列文本格式、列宽适配长表头;表头文字保持不变以兼容后端解析。
|
||||||
|
- 重新美化(按原始模板蓝色主题):提取 Downloads/副本货物类型导入模板_模拟数据(1).xlsx 样式(表头 #0070C0 蓝底白字微软雅黑11居中、数据行 #EBF1F8 浅蓝黑字微软雅黑10、边框 #D9D9D9 细线、表头行高24→因我表头更长设为30、数据行高19),应用到 3 个导入文件。注意:原始第1行是标题"GB-T 42820-2023…",但导入文件必须表头在 row1(后端按 row1 读),故不照搬标题行,只复用表头+数据行样式。
|
||||||
|
|
||||||
|
## 模板下载改静态资源 + 导入两遍法加固(本次)
|
||||||
|
- 模板下载:`cargo-type.vue` 的 `handleTemplate()` 不再用 exceljs 本地生成 2 行示例,改为 fetch 工程内置静态文件 `public/cargo-type-import-template.xlsx`(内容=已生成的标准"单文件一级在前"模板,含一级19类+全部二级示例),下载名仍为 `货物类型导入模板.xlsx`。base 用 `import.meta.env.BASE_URL`(当前 `/`)拼路径,无需后端 export-template 接口、离线可用。
|
||||||
|
- 后端加固(`CargoTypeServiceImpl.importCargoType`):由单遍逐行改为两遍法——第一遍先 validate+save 全部一级,第二遍再解析父级并 save 全部二级;父级解析仍走 `findParentByCode` 查库(第一遍已入库,同事务可见)。目的:让"完整导入"不受 Excel 行顺序影响(即使某二级行排在所属一级之前也不会整批失败);事务边界(`@Transactional` + 任一失败 `setRollbackOnly` 整批回滚)与失败明细 Excel(表头=CargoTypeExcel+导入失败原因,与前端 decorator 列宽 key 完全一致)保持不变。
|
||||||
|
- 注意:后端 Java 改动未在本机编译,需在 tms-erp-api-ws 重新编译部署生效;校验文案(请选择货物类型级别/货物类型编码格式不正确/二级编码前2位必须与上级货物类型编码一致/该货物类型编码已存在/该上级下已存在同名货物类型/货物类型名称不能超过50字符/备注不能超过200字)保持不变以匹配前端 `CARGO_TYPE_FAIL_RULES`。
|
||||||
|
|
||||||
|
## 货物类型页面搜索区紧凑化 + 展开/收缩功能
|
||||||
|
- **文件**: `src/views/base/cargo-type.vue` + `src/option/base/cargo-type.js`
|
||||||
|
- **改动**: 搜索区域紧凑化改造——两个搜索字段(类别、货物类型编码)改为单行并排(searchSpan:12);添加展开/收缩功能,默认收缩状态,通过 searchMenuSlot 在查询/重置按钮后追加「展开/收起」切换按钮(带箭头图标动画);option 配置中 searchShow 默认 false、searchMenuSlot 启用、移除 searchIcon。
|
||||||
|
|
||||||
|
## cargo-type 搜索区重构为自定义紧凑单行搜索栏
|
||||||
|
- **文件**: `src/views/base/cargo-type.vue` + `src/option/base/cargo-type.js`
|
||||||
|
- **改动**: 将 Avue 默认搜索表单完全替换为自定义紧凑单行搜索栏(对齐设计稿截图风格):
|
||||||
|
- 左侧:`el-select` 类型下拉(选择类型)+ `el-input` 搜索输入框(搜索分类名称,带搜索图标按钮)
|
||||||
|
- 右侧:添加分类(主色按钮)、批量导入、批量删除操作按钮
|
||||||
|
- 隐藏 Avue 内置搜索(`searchShow: false`),移除 `menu-left` 插槽中的按钮
|
||||||
|
- 新增 `handleCompactSearch` 方法,支持回车/点击/清除/下拉切换触发搜索,keyword 映射为 `cargoName` 参数
|
||||||
|
- 引入 Element Plus 图标组件(Search, Plus)
|
||||||
|
- 样式:flex 单行布局、轻量阴影 `0 2px 8px rgba(0,0,0,0.06)`、select 160px / input 280px 固定宽度
|
||||||
|
|
||||||
|
## cargo-type 操作按钮恢复(导出/模板)
|
||||||
|
- 紧凑搜索栏重构时误删了「下载模板」「批量导出」两个按钮(原在 menu-left 插槽)。
|
||||||
|
- 已重新加回按钮区:添加分类、批量导入、下载模板(`cargo_type_template`+`handleTemplate`)、批量导出(`cargo_type_export`+`handleExport`)、批量删除。
|
||||||
|
- `handleExport` / `handleTemplate` 方法始终未删,仅缺按钮入口,现已恢复。
|
||||||
28
.workbuddy/memory/2026-07-29.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# 2026-07-29 工作日志
|
||||||
|
|
||||||
|
## cargo-type 顶部按钮区优化
|
||||||
|
- **文件**: `src/views/base/cargo-type.vue` + `src/option/base/cargo-type.js`
|
||||||
|
- **改动**:
|
||||||
|
1. 新增按钮文字 `添加分类` → `新增`(与截图一致)
|
||||||
|
2. 为 4 个按钮补齐 Element Plus 图标:批量导入(Upload)、下载模板(Download)、批量导出(Download)、批量删除(Delete),均带 `el-icon--left`
|
||||||
|
3. 图标导入注册:`import { Plus, Upload, Download, Delete }`(移除不再需要的 Search),components 同步注册
|
||||||
|
4. 补充规范样式:`:deep(.basic-container__card) > .el-card__body { padding: 0 }`
|
||||||
|
|
||||||
|
## cargo-type 按钮迁移至 menu-left + 移除紧凑搜索栏(本次)
|
||||||
|
- **用户要求**:功能按钮从自定义紧凑搜索栏迁移到 avue-crud 的 `menu-left` 插槽(表格工具栏右侧),同时删除自定义紧凑搜索栏,恢复 Avue 原生搜索。
|
||||||
|
- **模板改动**:
|
||||||
|
- 删除整个 `.compact-search` 自定义搜索栏 div(含 el-select + el-input + 按钮)
|
||||||
|
- 在 `<avue-crud>` 内新增 `<template #menu-left>` 插槽,放置全部 5 个按钮(新增/批量导入/下载模板/批量导出/批量删除)
|
||||||
|
- **Option 改动**:`searchShow: false` → `searchShow: true`,恢复 Avue 原生搜索表单(类型 radio + 货物类型编码 input)
|
||||||
|
- **清理**:移除 `Search` 图标导入、`handleCompactSearch()` 方法、`.compact-search` 相关样式、隐藏 `.avue-crud__search-btn` 规则
|
||||||
|
- **确认无需改动项**:操作列(220px)、分页组件布局均符合规范
|
||||||
|
|
||||||
|
## cargo-type 导出逻辑修复 + 去重新增按钮(本次)
|
||||||
|
- **导出逻辑**:`buildExportParams()` 移除 `ids` 参数拼接,始终按当前搜索条件导出(不再受勾选行影响)
|
||||||
|
- **去重新增按钮**:Avue 内置 addBtn 由 `validData(permission, false)` 改为 `false`,隐藏内置"新增"按钮;仅保留 `menu-left` 插槽中带图标的"新增"按钮
|
||||||
|
|
||||||
|
## cargo-type 查看/编辑"请求未完成"修复(本次)
|
||||||
|
- **现象**:点击查看/编辑弹窗不打开,提示"请求未完成,请联系管理员"(该文案前端/后端 Java 源码均无字面匹配,疑似网关或全局异常统一包装的报错)。
|
||||||
|
- **根因**:`beforeOpen` 中对 view/edit 调用 `getDetail(this.form.id)` 重新拉取详情,但 `done()` 仅在 `.then` 内调用;该请求一旦失败/超时 → `done()` 不执行 → 弹窗卡死 + 拦截器 toast 报错。且 `getDetail` 本身冗余:列表 `selectCargoTypePage` 已直接返回完整 `CargoTypeVO`(id/typeLevel/parentId/parentCargoName/cargoName/cargoCode/remark 等全字段),Avue 打开弹窗前已把整行填充进 `this.form`。
|
||||||
|
- **修复**:删除 `beforeOpen` 中 view/edit 分支的 `getDetail` 调用,改为直接复用 Avue 已填充的 `this.form`,仅保留 `ensureParentOption(this.form)` + `syncColumnDisplay()` + `done()`;同步移除 `getDetail` 的 import(api 文件中的导出保留勿删)。
|
||||||
|
- **副作用消除**:查看/编辑不再发 detail 请求,彻底规避该接口失败导致的卡死与报错。若后续确需"打开时拉最新数据",需先排查后端 `/blade-system/cargo-type/detail` 为何报错(网关默认只拦 actuator/health,detail 不在拦截名单)。
|
||||||
124
.workbuddy/memory/2026-07-31.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# 2026-07-31 工作记录
|
||||||
|
|
||||||
|
## 货物类型(/base/cargo-type)批量导入「全或无」改造
|
||||||
|
|
||||||
|
- 需求:批量导入时只要任一行报错,整批都不入库,并返回失败明细 Excel。用户在「事务 vs 校验」之间选了"全或无 + 推荐方案"。
|
||||||
|
- 结论(已落地):**全量预校验 + 单事务兜底**,而非纯事务或纯校验二选一。
|
||||||
|
- 后端仓库:`/Users/gxwebsoft/JAVA/tms-erp-api-ws`(BladeX,本仓库 tms-erp-web-ws 是纯前端,无 Java)。
|
||||||
|
- 改动文件:`blade-service/blade-system/.../service/impl/CargoTypeServiceImpl.java`(仅此一文件,未动 Controller/前端)。
|
||||||
|
- 实现要点:
|
||||||
|
- `importCargoType` 拆为两阶段:阶段一 `validateImportAll`(只读,不写库)→ 任一失败直接返回失败明细、整批不入库;阶段二 `saveImportAll` 全部通过后才在 `@Transactional` 内统一写库(兜底防半截入库)。
|
||||||
|
- 补上原缺失的校验:文件内编码全局去重、一级名称去重、二级(同上级)名称去重;二级父级解析同时支持 DB 与"文件内一级映射"(解决"单文件一级在前"场景,二级引用同文件的一级)。
|
||||||
|
- 原代码其实已是 `@Transactional + setRollbackOnly`,但"边校验边写库"且缺文件内去重/父子引用校验;本次重构成更干净的预校验优先。
|
||||||
|
- 前端无需改动:`src/views/base/cargo-type.vue` + `utils/import-excel.js` 已支持失败明细 Excel 下载与 `decorateCargoTypeFailDetail` 装饰。
|
||||||
|
- 验证:本环境无 maven,无法编译;已做静态核对(imports/方法/字段/括号完整,无 TransactionAspectSupport 残留)。需在本地 `mvn -pl blade-service/blade-system compile` 确认。
|
||||||
|
- 遗留小问题(非本次引入,可选优化):后端二级编码前缀报错文案为"货物类型编码前2位必须与上级货物类型编码一致",而前端 `CARGO_TYPE_FAIL_RULES` 匹配的是"二级编码前2位必须与上级货物类型编码一致",二者不完全一致,导致该错误前端不会追加规则说明(仍会显示原因)。可后续对齐文案。
|
||||||
|
|
||||||
|
## cargo-type 分页隐藏「首页/上一页/下一页/尾页」
|
||||||
|
|
||||||
|
- 根因:页面有两套分页——有数据时用 `avue-crud` 自带分页(默认 layout `total, sizes, prev, pager, next, jumper`,原生上一页/下一页来自这里);无数据时用共享组件 `<empty-pagination>`(layout 写死同样带 prev/next)。「首页/尾页」按钮不是 Avue/EP 原生的,而是全局增强器 `src/utils/pagination.js` 的 `setupPaginationEnhancer()`(main.js 第 98 行全局启用)扫描所有 `.el-pagination`,在 `.btn-prev` 前插「首页」、`.btn-next` 后插「尾页」。
|
||||||
|
- 关键机制:增强器只在存在 `.btn-prev/.btn-next` 时才注入首页/尾页。因此去掉分页 layout 里的 prev/next,首页/尾页就不会被注入。
|
||||||
|
- 改动(仅 `src/views/base/cargo-type.vue`,未碰共享组件):① `page` 数据加 `layout: 'total, sizes, pager, jumper'` 处理有数据状态;② 新增 scoped `:deep(.avue-crud__pagination)` 规则隐藏 `.btn-prev/.btn-next/.erp-pagination-first/.erp-pagination-last`,覆盖无数据时的 empty-pagination 状态。
|
||||||
|
- 注意:`empty-pagination` 被 16+ 页面共用,本次未改它的默认 layout,避免影响其它页面。如需其它页面也隐藏,应给该组件加 `layout` prop 而非改默认值。
|
||||||
|
|
||||||
|
## 全站分页统一隐藏「首页/上一页/下一页/尾页」(接上一条)
|
||||||
|
|
||||||
|
- 用户要求全站统一。逐页改不现实(empty-pagination 被 16+ 页共用,还有大量 avue-crud 自带分页),改为**集中两处全局改动**:
|
||||||
|
1. `src/utils/pagination.js`:删除全局增强器对「首页/尾页」按钮的注入(保留「跳转」);同步精简 `updatePaginationButtons`(不再处理 first/last disabled)。
|
||||||
|
2. `src/styles/element-ui.scss`:新增全局规则 `.el-pagination { .btn-prev, .btn-next { display: none !important } }`,统一隐藏原生「上一页/下一页」。
|
||||||
|
- 因此**回退了 cargo-type.vue 之前的两处页面级改动**(`page.layout` 与 scoped 隐藏样式),避免与全局方案两套机制并存;cargo-type 现由全局方案统一接管。
|
||||||
|
- 效果:全站所有 el-pagination(含 avue-crud 自带分页与 empty-pagination)均只保留「总条数/每页条数/页码/跳转」,首页/上一页/下一页/尾页全部隐藏;「跳转」按钮保留。
|
||||||
|
- 风险点:全局 `display:none !important` 会影响所有分页,符合"全站统一"诉求;如后续某页面需恢复导航按钮,需针对该页用更高优先级样式覆盖或单独处理。
|
||||||
|
|
||||||
|
## 全站搜索按钮文案统一
|
||||||
|
|
||||||
|
- **文件**: `src/lang/zh.js`、`src/lang/en.js`
|
||||||
|
- **改动**:
|
||||||
|
- `tagsView.search`: `搜索` → `查询`(中)/ `Search` → `Query`(英)
|
||||||
|
- `crud.filter.resetBtn`: `清空条件` → `重置`
|
||||||
|
- **影响范围**: 全站所有 Avue CRUD 搜索栏按钮自动生效(通过 i18n 全局配置)
|
||||||
|
- **排除**: 地图搜索、日志清空等非 CRUD 场景的按钮文案保持不变
|
||||||
|
|
||||||
|
## 全站操作栏按钮隐藏图标
|
||||||
|
|
||||||
|
- **文件**: `src/styles/element-ui.scss`
|
||||||
|
- **改动**: 新增全局 CSS 规则 `.avue-crud__menu .el-button--text i, .avue-crud__menu .el-button i { display: none !important }`
|
||||||
|
- **效果**: 全站所有 Avue CRUD 操作列(查看/编辑/删除等)按钮前的图标统一隐藏,仅保留文字
|
||||||
|
- **方案选择**: CSS 全局覆盖,无需逐个修改 option 配置文件
|
||||||
|
|
||||||
|
## 全站操作栏按钮紧凑间距
|
||||||
|
|
||||||
|
- **文件**: `src/styles/element-ui.scss`
|
||||||
|
- **改动**: 新增全局规则 `.avue-crud__menu .el-button { margin-left: 4px; margin-right: 0; padding: 0 4px }`
|
||||||
|
- **效果**: 全站 CRUD 操作列按钮统一为 4px 间距 + 4px 内边距,与 cargo-type 一致
|
||||||
|
|
||||||
|
## 全站操作列宽度统一为 160px
|
||||||
|
|
||||||
|
- **目标**: 参考 cargo-type(menuWidth: 160)的紧凑效果,全站统一操作列宽度
|
||||||
|
- **改动**: ① `src/main.js` 全局默认 `menuWidth` 由 220 改为 160;② 批量将 src 下 72 处 option/vue 里显式 `menuWidth: 数字` 统一替换为 `menuWidth: 160`
|
||||||
|
- **影响范围**: 全站所有 Avue CRUD 操作列(含自定义 menu 插槽列,menuWidth 仍控制该列宽度)
|
||||||
|
- **风险**: 原部分页面操作按钮较多(如 tenant/customer-archive 等曾配 380~420),统一 160px 后若按钮数 > 3 可能出现换行/溢出;如某页溢出需单独放宽或精简按钮
|
||||||
|
|
||||||
|
## 全站操作列内容左对齐
|
||||||
|
|
||||||
|
- **文件**: `src/styles/element-ui.scss`
|
||||||
|
- **原因**: cargo-type 用自定义 `#menu` 模板默认左对齐;其他页面用 Avue 内置菜单(viewBtn:true)默认右对齐
|
||||||
|
- **改动**: 新增 `.avue-crud .el-table td .cell.avue-crud__menu { text-align: left }`
|
||||||
|
- **效果**: 全站操作列统一左对齐
|
||||||
|
|
||||||
|
## 顶部工具栏工具全部隐藏
|
||||||
|
|
||||||
|
- **文件**: `src/config/website.js` + `src/page/index/top/index.vue`
|
||||||
|
- **改动**: ① website.js `setting` 新增/关闭 `theme:false`、`debug:false`、`lang:false`、`settingBtn:false`(原 theme/debug 仍为 true);② index.vue 给 `<top-lang>` 加 `v-if="setting.lang"`、`<top-setting>` 加 `v-if="setting.settingBtn"`
|
||||||
|
- **效果**: 顶部工具排仅保留用户头像+姓名下拉(含退出登录);语言切换/设置齿轮/日志/皮肤图标均隐藏
|
||||||
|
- **默认主题**: `src/store/modules/common.js` 第 21 行 `themeName` 默认改为 `theme-d2`(已登录用户若 localStorage 存过旧主题需手动切一次或清存储)
|
||||||
|
|
||||||
|
## 欢迎页(/wel/index)重设计为 TMS-ERP 业务仪表盘
|
||||||
|
|
||||||
|
- **文件**: `src/views/wel/index.vue`(整文件重写,移除 Saber 默认营销内容)
|
||||||
|
- **设计**: 浅色 d2 主题风,纯 SVG/CSS 自绘图表(项目无 echarts,零依赖)
|
||||||
|
- **模块**: ① 问候横幅(用户名+日期+新建运单按钮) ② 4 张核心指标卡(今日运单/在途运输/待办事项/运力车辆,含环比) ③ 运单趋势(SVG柱状,近7日) ④ 货物类型分布(SVG环形donut) ⑤ 运输方式占比(横向条) ⑥ 预警提醒列表 ⑦ 快捷入口网格(跳真实路由)
|
||||||
|
- **数据**: 全 mock,data() 中每项标注对应后端接口(如 /blade-business/waybill/count、/trend、/cargoStat 等),后续替换真实接口即可
|
||||||
|
- **预览**: `npm run build` 通过;dev server `http://localhost:2889/`
|
||||||
|
- **注意**: 快捷入口 path 依据 views 目录结构推断(/business/waybill-manage 等),需与后端菜单 path 一致才能跳转
|
||||||
|
|
||||||
|
## 图标悬停圆形背景效果示例
|
||||||
|
|
||||||
|
- 按用户提供的两张截图(T 恤默认图标 / 铃铛带圆形背景图标),实现了一个悬停时显示浅灰圆形背景的图标按钮效果。
|
||||||
|
- 产物: `/Users/gxwebsoft/VUE/tms-erp-web-ws/icon-hover-demo.html`(含 CSS 核心代码与 Element Plus 用法示例)。
|
||||||
|
|
||||||
|
## 顶栏 T 恤图标悬停效果落地
|
||||||
|
|
||||||
|
- 用户要求把悬停圆形背景效果运用到顶部状态栏的 T 恤图标(实际指向主题图标位置 `<i class="icon-zhuti">`)。
|
||||||
|
- 改动文件: `src/page/index/top/top-theme.vue`
|
||||||
|
- 模板:将 `<i class="icon-zhuti" @click="open">` 替换为内联 SVG T 恤(保留 `@click="open"` 打开主题选择弹窗)。
|
||||||
|
- 样式:新增 scoped `.top-theme-icon`,`::before` 浅灰圆形背景 `#f2f3f5`,默认 `scale(0.6) opacity(0)`,hover/focus 弹性放大到 `scale(1)`,图标 `z-index:1` 压在上层。
|
||||||
|
- 调整:用户反馈 T 恤图标在顶栏中上下不居中,把 `.top-theme-icon` 由 `display:flex; height:100%` 改为 `display:inline-flex; vertical-align:middle; width:32px; height:32px`,使其与右侧头像/用户名在同一水平中线。
|
||||||
|
- 注意:该组件受 `website.setting.theme` 控制(之前曾设为 false 隐藏),若顶栏未显示主题图标,需确认 website.js 中 `setting.theme` 为 true。
|
||||||
|
|
||||||
|
## 顶栏头像触发下拉菜单(hover)
|
||||||
|
|
||||||
|
- **需求**: 鼠标移到头像(top-bar__img)也能触发下拉,行为与点用户名一致。
|
||||||
|
- **文件**: `src/page/index/top/index.vue`
|
||||||
|
- **改动**:
|
||||||
|
1. 把 `<img class="top-bar__img" :src="userInfo.avatar">` 从 el-dropdown 外的同级节点,移入 el-dropdown 触发区(`<span class="el-dropdown-link">`)内。
|
||||||
|
2. 给 `<el-dropdown>` 加 `trigger="hover"`,让头像+姓名整体支持 hover 触发。
|
||||||
|
3. scoped 样式新增 `.top-user__trigger`(inline-flex / padding 4px 8px / hover 浅灰背景 rgba(0,0,0,0.04)),并把 `.top-bar__img` 自身 `margin` 改为 `0 5px 0 0` 配合新容器。
|
||||||
|
- **效果**: 鼠标悬停在头像或姓名任一处都会展开下拉;保留 `:hide-on-click="false"`(菜单内点击不收起,el-tooltip 等仍可交互)。
|
||||||
|
- **注意**: 若用户后续希望「hover 触发」仅作用于头像、不影响姓名点击行为,需把姓名部分移出 el-dropdown 触发区;当前实现是统一行为。
|
||||||
|
|
||||||
|
## 全站 avue-crud 弹窗内部滚动高度统一
|
||||||
|
|
||||||
|
- **需求**:/business/process-config 与 /base/cargo-type 表单弹窗滚动高度不一致(process-config 用 dialogWidth:'96%'+dialogTop:'10px' 且内容很长被撑爆;cargo-type 用 dialogWidth:760 窄窗),要求全站统一。
|
||||||
|
- **关键结论**:@smallwei/avue 3.9.2 的 avue-crud **没有 `dialogHeight` 属性**(源码 avue.js 中无此字符串;dialogTop 默认值为 "0")。逐个 option 设 dialogHeight 不可行,故延续本项目「全局 CSS 统一」范式(见上「全站操作栏按钮」等先例)。
|
||||||
|
- **改动文件**:`src/styles/element-ui.scss`(全局生效,被 common.scss 通过 `@use './element-ui.scss'` 引入)
|
||||||
|
- **新增规则**:`.avue-crud__dialog .el-dialog__body { max-height: calc(100vh - 200px); overflow-y: auto; }`
|
||||||
|
- **效果**:全站所有 Avue CRUD 弹窗(含 process-config、cargo-type)的 body 在 `calc(100vh - 200px)` 内滚动,内容超长时在窗内滚动而非撑爆整窗;矮弹窗不受影响(max-height 仅为上限)。
|
||||||
|
- **验证**:已 `pnpm build` 后台运行验证全站编译。
|
||||||
|
|
||||||
|
## 顶部状态栏标题区加背景条
|
||||||
|
|
||||||
|
- **需求**:给顶部状态栏(`.top-bar__title` 中间区域)加一条背景条,与白色头部区分。
|
||||||
|
- **文件**:`src/styles/top.scss` 的 `.top-bar__title` 规则(原来背景是纯白 `#fff`,看不出边界)
|
||||||
|
- **改动**:`background: rgba(64,158,255,0.12)`(品牌色淡底)+ `border-left: 4px solid #409eff`(左侧主色竖条),沿用项目主色 `#409eff`;文字保持深色 `rgba(0,0,0,0.85)`、搜索框可读。
|
||||||
|
- **注意**:默认 light 主题(go/d2 等白底头部)效果好;dark 主题头部 `#2c3643` 下淡蓝条可能略冲突(原 `#fff` 背景在 dark 下本就冲突,属历史遗留),如需可给 dark 主题单独覆盖。
|
||||||
18
.workbuddy/memory/2026-08-04.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 2026-08-04 工作记录
|
||||||
|
|
||||||
|
## 撰写《AI 辅助编程规范与实战示例》文档
|
||||||
|
- 应业主想了解"如何用 AI 编程"的需求,以 `src/views/base/cargo-type.vue`(货物类型模块)为实例,撰写对外说明文档。
|
||||||
|
- 产出文件:`/Users/gxwebsoft/VUE/tms-erp-web-ws/AI辅助编程规范与实战示例.md`
|
||||||
|
- 文档结构:协作流程总览 → AGENTS.md 规范条款 → cargo-type 模块实例拆解(三级文件分离、校验三处一致、审计字段用姓名、导入失败明细加工、样式规范)→ 人机协作人工兜底项 → 5 条经验 → 给业主的价值建议。
|
||||||
|
- 文档引用了真实代码片段:cargo-type.vue / option / api / utils/import-excel.js,强调需求卡 + AGENTS.md + 复用 utils 三件套作为"单一事实来源"。
|
||||||
|
|
||||||
|
## 生成 Word(.docx) 版本
|
||||||
|
- 用 docx-js(managed node workspace)将《AI 辅助编程规范与实战示例.md》转成 Word 文档:`/Users/gxwebsoft/VUE/tms-erp-web-ws/AI辅助编程规范与实战示例.docx`。
|
||||||
|
- 踩坑:docx-js 会在段落间注入非法空节点 `<0/>`(`<N/>`),导致 XML 不合法;后处理用正则剔除 `<\d+/>` 后重新校验通过。
|
||||||
|
- 生成脚本:`/Users/gxwebsoft/.workbuddy/binaries/node/workspace/gen_doc.js`(含标题/表格/代码块/项目符号样式)。
|
||||||
|
|
||||||
|
## 分页组件:上一页/下一页改为原生箭头图标
|
||||||
|
- 需求:全站不隐藏上一页/下一页,改显示原生箭头图标;首页/尾页保持不注入。
|
||||||
|
- 改动文件:`src/styles/element-ui.scss`(3 处历史遗留规则)、`src/utils/pagination.js`(注释同步)。
|
||||||
|
- 删除的遗留规则:①隐藏原生 `.el-icon` 箭头;②用 `::before` 注入「上一页/下一页」文字;③整体 `display:none` 隐藏 `.btn-prev/.btn-next`。首页/尾页仍由 pagination.js 增强器不注入,且各页面 layout 无 first/last。
|
||||||
|
- 效果:上一页/下一页显示 Element Plus 原生箭头(‹ ›),带边框与页码按钮视觉统一,hover 变主色,禁用态灰显。
|
||||||
63
.workbuddy/memory/2026-08-05.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# 2026-08-05 工作记录
|
||||||
|
|
||||||
|
## 排查:改线上接口后前端"运行不了"(CORS 根因)
|
||||||
|
|
||||||
|
- 现象:用户将 `.env.development` 的 `VITE_APP_API` 改为 `http://172.16.203.228:8000/api`(直连线上/测试后端)后仍运行不了。
|
||||||
|
- 根因:Saber3 的 axios 配了 `withCredentials = true`(`src/axios.js:79`)。该后端(openresty + blade-gateway)对跨域请求返回 `Access-Control-Allow-Origin: *` 且 `Access-Control-Allow-Credentials: true`,浏览器规定 credentials 模式下 Allow-Origin 不能是 `*`,非法组合会被直接拒绝 → 所有接口失败。
|
||||||
|
- 之前用 `/api` 能跑是因为走 Vite 代理,浏览器请求同源 localhost:2888,不触发跨域。
|
||||||
|
- 已改动:
|
||||||
|
1. `.env.development` 的 `VITE_APP_API` 改回 `/api`,并加注释说明两种模式。
|
||||||
|
2. `vite.config.mjs` 的 `server.proxy['/api']` target 改为 `http://172.16.203.228:8000`,并去掉 `rewrite` 去掉 `/api` 的逻辑(保留 `/api` 前缀,对齐 openresty 期望路径)。
|
||||||
|
- 注意:改 `.env` / `vite.config.mjs` 后必须重启 `npm run dev`(Vite 启动时加载环境变量,运行中改动不会热更新)。
|
||||||
|
- 若确需直连绝对地址(如生产/部署):必须让后端 CORS 把 Allow-Origin 改为具体前端域名(blade-gateway 的 CorsConfig 用 `setAllowedOriginPatterns` 或显式域名),不可用 `*` 配合 credentials。
|
||||||
|
|
||||||
|
## 调整:货物类型导入失败原因展示格式
|
||||||
|
|
||||||
|
- 文件:`src/views/base/cargo-type.vue`
|
||||||
|
- 修改 `decorateCargoTypeFailDetail`:
|
||||||
|
- 移除「第N行:」前缀;
|
||||||
|
- 失败原因编号从 `A. B. C.` 改为 `1. 2. 3.`;
|
||||||
|
- 备注超长兜底提示也同步使用数字编号。
|
||||||
|
|
||||||
|
## UI 优化:客商档案弹窗「基本信息」分组(vehicle/customer-archive.vue)
|
||||||
|
|
||||||
|
- 背景:原弹窗「基本信息」是一整块 `el-row` 平铺 20 个字段,信息密度过高。
|
||||||
|
- 方案(与用户确认):采用「分区标题平铺 + 浅色背景块」而非嵌套卡片(契合 AGENTS.md 去卡片化哲学;全局 `.dialog-section-title` 已自带 4px 主色竖条)。
|
||||||
|
- 改动:
|
||||||
|
- 模板:将单一 `el-row` 拆分为 4 个 `.archive-form__group`:工商信息 / 联系信息(3项 span=8) / 财务·信用信息 / 其他信息(备注 span=24);字段顺序重组但全部保留,地址、备注保持 span=24。
|
||||||
|
- 样式:新增 `.archive-form__group`(#fafafa 背景、8px 圆角、16px/20px 内边距、组间距 16px),子标题复用 `.dialog-section-title`(14px/500)。
|
||||||
|
- 校验:@vue/compiler-sfc 解析 0 错误;标签闭合平衡。
|
||||||
|
- 注:此前讨论中提及的「Tab 内容加内边距」「材料区标题竖条」未纳入本次(材料区已用 dialog-section-title);如需可后续追加。
|
||||||
|
|
||||||
|
## 排查:分页「上一页/下一页原生箭头」样式被还原
|
||||||
|
|
||||||
|
- 现象:昨日(08-04)已对 `src/styles/element-ui.scss` 三处历史遗留规则做删除(隐藏 `.el-icon` 箭头、用 `::before` 注入「上一页/下一页」文字、整体 `display:none` 隐藏 `.btn-prev/.btn-next`),今早用户反馈效果被覆盖。
|
||||||
|
- 排查:重新 Grep 确认 `element-ui.scss` 三处原隐藏规则全部恢复成原始状态;而 `src/utils/pagination.js` 的注释("统一展示为原生箭头图标")未被还原,说明只有该样式文件被外部覆盖(疑似 git 还原 / 重新拉取 / 某生成流程),并非逻辑层问题。
|
||||||
|
- 已重新逐条应用三处删除(单条提交,避开并行编辑的缓存冲突),并验证无遗留 `display:none`/`content:'上一页'`;`pagination.js` 无需再改。
|
||||||
|
- 提醒:`element-ui.scss` 若处于版本控制或生成流程中,可能被再次还原;如需长期生效,建议把该改动提交入 git,或排查是否有自动覆盖该文件的脚本。
|
||||||
|
|
||||||
|
## UI 调整:Avue CRUD 弹窗内容区背景改为灰色 #f5f6fa
|
||||||
|
|
||||||
|
- 文件:`src/styles/element-ui.scss` 第 225 行附近 `.avue-crud__dialog .el-dialog__body`
|
||||||
|
- 改动:在原 `max-height`/`overflow-y` 规则中新增 `background: #f5f6fa;`
|
||||||
|
- 范围:**全局生效**(所有 Avue CRUD 弹窗的内容区都会变灰)。起因是用户想在货物类型(cargo-type)新增弹窗用灰底衬托。
|
||||||
|
- 注意:弹窗默认 `append-to-body`,scoped 样式选不到;如需仅货物类型单页变灰,需给 option 加 `dialogCustomClass` 再单独写选择器。用户未要求收窄,暂保持全局。
|
||||||
|
|
||||||
|
## UI 改造:project-apply 弹窗灰底+白卡片布局
|
||||||
|
|
||||||
|
- 文件:`src/views/business/project-apply.vue`
|
||||||
|
- 需求:弹窗背景色 `#f5f6fa`,每个分组区域用白色卡片
|
||||||
|
- 改动:
|
||||||
|
- 弹窗 body(global 选择器):加 `background: #f5f6fa`
|
||||||
|
- `__grid`、`__table`、`__textarea-list`、`__material-head`、`__upload`、`__change-textarea` 统一加白底 + 6px 圆角 + 极淡阴影 + 内边距
|
||||||
|
- 效果:灰蓝底弹窗上浮白色分组卡片,与客商档案弹窗的「灰色分组块+白色内层卡片」方案一致
|
||||||
|
|
||||||
|
## 二次优化:project-apply 分区标题也包进白色卡片
|
||||||
|
|
||||||
|
- 文件:`src/views/business/project-apply.vue`
|
||||||
|
- 需求:把「项目基本信息」这类分区标题也装进白色卡片内(标题+内容合一张白卡)
|
||||||
|
- 改动:
|
||||||
|
- `.dialog-section-title`(排除 material 标题)加白底 + 上圆角 `6px 6px 0 0` + `z-index:1`,紧接内容块
|
||||||
|
- `__grid`/`__table`/`__textarea-list`/`__change-textarea` 圆角改为下圆角 `0 0 6px 6px`,与标题拼接成完整白卡
|
||||||
|
- 材料区(`__material-head`/`__upload`)标题与按钮本就在白卡内,不受影响
|
||||||
|
- 纯 CSS 改动,未动模板结构;用 `:not()` 排除材料标题避免破坏既有布局
|
||||||
16
.workbuddy/memory/MEMORY.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# 项目长期记忆(tms-erp-web-ws / Saber3 客商模块)
|
||||||
|
|
||||||
|
## 设计约定(经用户确认的决策)
|
||||||
|
- 弹窗内多字段表单分组:**「灰色分组块 + 白色内层卡片」双色方案**(用户最终确认)。
|
||||||
|
- 外层 `.archive-form__group`:灰底 `#f0f2f5` + 8px 圆角 + `16px 20px` 内边距,分组标题(`.dialog-section-title`,自带 4px 主色竖条)浮于灰底上。
|
||||||
|
- 内层字段区:直接把分组内唯一的 `> .el-row` 设为白底(`#fff` + 6px 圆角 + 极淡阴影 `0 1px 2px rgba(0,0,0,.04)` + `18px 16px 4px` 内边距),形成「白卡片浮于灰底」的层次,而非逐个输入框强制白底。
|
||||||
|
- 理由:契合 AGENTS.md「去卡片化」哲学(不嵌套 `el-card`),同时用户明确要灰底+白内容对比,全局 `.dialog-section-title` 直接复用即可。
|
||||||
|
- 适用:新增/编辑弹窗中字段超过 ~10 个、需按业务语义分组时。
|
||||||
|
- 联系信息等仅 3 项的分组,可用 `el-col :span="8"` 让三项均分一行,避免 4 列网格留白。
|
||||||
|
|
||||||
|
## 关键文件
|
||||||
|
- 客商档案弹窗:`src/views/vehicle/customer-archive.vue`(手写 `el-form`,非 Avue option 驱动;分组结构见 `.archive-form__group`)。
|
||||||
|
- 全局弹窗分区标题规范:`src/styles/element-ui.scss` 的 `.dialog-section-title`。
|
||||||
|
|
||||||
|
## 环境注意
|
||||||
|
- Vite 代理跨域:Saber3 axios 开 `withCredentials=true`,直连绝对地址后端须让 CORS `Allow-Origin` 为具体域名(不能用 `*`),否则浏览器拒绝。改 `.env`/`vite.config.mjs` 必须重启 dev。
|
||||||
72
AGENTS.md
@@ -1,9 +1,11 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
|
|
||||||
本文件用于指导 Codex (Codex.ai/code) 在 Saber3 代码仓库中工作时的行为规范。
|
本文件用于指导 Codex (Codex.ai/code) 在 Saber3 代码仓库中工作时的行为规范。
|
||||||
|
|
||||||
> 本规范适用于 Saber3 前端工程的所有开发任务,为强制性条款。除非用户显式豁免,任何条目都不得忽视或删减。
|
> 本规范适用于 Saber3 前端工程的所有开发任务,为强制性条款。除非用户显式豁免,任何条目都不得忽视或删减。
|
||||||
>
|
>
|
||||||
> 作为 AI 助手参与本项目开发时,你必须:
|
> 作为 AI 助手参与本项目开发时,你必须:
|
||||||
|
>
|
||||||
> - 每次输出前深度理解 BladeX 微服务架构体系、Saber3 前端工程结构和 Vue 3 技术栈特征
|
> - 每次输出前深度理解 BladeX 微服务架构体系、Saber3 前端工程结构和 Vue 3 技术栈特征
|
||||||
> - 当回答依赖外部知识时,先查询 Vue 3、Element Plus、Avue、Vite 等官方文档
|
> - 当回答依赖外部知识时,先查询 Vue 3、Element Plus、Avue、Vite 等官方文档
|
||||||
> - 若需求含糊,先复述已知信息并列出关键澄清问题
|
> - 若需求含糊,先复述已知信息并列出关键澄清问题
|
||||||
@@ -21,7 +23,7 @@
|
|||||||
### 1.1 技术栈
|
### 1.1 技术栈
|
||||||
|
|
||||||
| 技术 | 版本 | 用途 |
|
| 技术 | 版本 | 用途 |
|
||||||
| ------------------ | -------- | ------------------ |
|
| --------------------- | ------- | ------------------ |
|
||||||
| Vue | ^3.5.13 | 核心框架 |
|
| Vue | ^3.5.13 | 核心框架 |
|
||||||
| Element Plus | ^2.10.1 | UI 组件库 |
|
| Element Plus | ^2.10.1 | UI 组件库 |
|
||||||
| @smallwei/avue | ^3.7.2 | 增强型 CRUD 组件库 |
|
| @smallwei/avue | ^3.7.2 | 增强型 CRUD 组件库 |
|
||||||
@@ -91,27 +93,36 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
|
|||||||
- 命名约定:列表 `getList(current, size, params)`、详情 `getDetail(id)`、新增 `add(row)`、更新 `update(row)`、删除 `remove(ids)`、树形 `getXxxTree()`
|
- 命名约定:列表 `getList(current, size, params)`、详情 `getDetail(id)`、新增 `add(row)`、更新 `update(row)`、删除 `remove(ids)`、树形 `getXxxTree()`
|
||||||
- 后端微服务前缀:`/blade-system/`、`/blade-resource/`、`/blade-flow/`、`/blade-desk/`、`/blade-log/`、`/blade-develop/`
|
- 后端微服务前缀:`/blade-system/`、`/blade-resource/`、`/blade-flow/`、`/blade-desk/`、`/blade-log/`、`/blade-develop/`
|
||||||
|
|
||||||
### 3.4 认证机制
|
### 3.4 批量导入失败文件下载规范
|
||||||
|
|
||||||
|
- 所有批量导入功能如果存在部分数据无法导入、校验失败或后端处理异常,前端必须支持自动下载后端返回的导入失败 Excel。
|
||||||
|
- 失败 Excel 的字段顺序必须与原导入模板保持一致,并在最后一列追加“导入失败原因”。
|
||||||
|
- 前端上传接口需支持 `blob` 响应;Avue 默认上传无法可靠处理文件流时,应使用 `httpRequest` 或独立 API 方法自定义上传。
|
||||||
|
- 前端需根据响应 `content-type` 或 Blob 类型区分 JSON 成功响应与 Excel 文件流:成功时提示并刷新列表,失败文件流时下载失败明细并提示“部分数据导入失败,已下载失败明细”。
|
||||||
|
- 批量导入失败明细文件命名统一包含业务名称、`导入失败明细` 和时间戳,例如 `货物类型导入失败明细YYYY-MM-DD HH:mm:ss.xlsx`。
|
||||||
|
- 批量导入的前端预校验与后端导入校验必须与新增、编辑表单校验保持一致,包括必填、长度、格式、枚举范围、父子级联关系和金额/日期等业务规则;新增、编辑校验调整时,必须同步更新导入校验。
|
||||||
|
|
||||||
|
### 3.5 认证机制
|
||||||
|
|
||||||
- OAuth2:`Basic` 头传递 `clientId:clientSecret`(Base64 编码)
|
- OAuth2:`Basic` 头传递 `clientId:clientSecret`(Base64 编码)
|
||||||
- Token:请求头 `Blade-Auth: bearer {token}`,支持 AES 加密模式
|
- Token:请求头 `Blade-Auth: bearer {token}`,支持 AES 加密模式
|
||||||
- 存储:`saber3-access-token` / `saber3-refresh-token`(通过 `utils/auth.js` 管理)
|
- 存储:`saber3-access-token` / `saber3-refresh-token`(通过 `utils/auth.js` 管理)
|
||||||
- 401 自动刷新 Token,并发请求排队等待;登录密码使用 SM2 国密加密
|
- 401 自动刷新 Token,并发请求排队等待;登录密码使用 SM2 国密加密
|
||||||
|
|
||||||
### 3.5 路由系统
|
### 3.6 路由系统
|
||||||
|
|
||||||
- 静态路由:`router/page/` + `router/views/`
|
- 静态路由:`router/page/` + `router/views/`
|
||||||
- 动态路由:`avue-router.js` 将后端菜单数据转换为 Vue Router 路由
|
- 动态路由:`avue-router.js` 将后端菜单数据转换为 Vue Router 路由
|
||||||
- 多级路由自动扁平化为二级,支持 keep-alive 跨层级缓存
|
- 多级路由自动扁平化为二级,支持 keep-alive 跨层级缓存
|
||||||
- 外部链接自动转换为 iframe 路由,支持 Token 透传
|
- 外部链接自动转换为 iframe 路由,支持 Token 透传
|
||||||
|
|
||||||
### 3.6 权限控制
|
### 3.7 权限控制
|
||||||
|
|
||||||
- 路由守卫:`permission.js` 控制登录态、锁屏、标签页
|
- 路由守卫:`permission.js` 控制登录态、锁屏、标签页
|
||||||
- 按钮权限:`store.getters.permission`,格式 `{module}_{action}`(如 `dict_add`)
|
- 按钮权限:`store.getters.permission`,格式 `{module}_{action}`(如 `dict_add`)
|
||||||
- 管理员判断:`userInfo.authority.includes('admin')`
|
- 管理员判断:`userInfo.authority.includes('admin')`
|
||||||
|
|
||||||
### 3.7 多租户
|
### 3.8 多租户
|
||||||
|
|
||||||
通过 `website.tenantMode` 控制开关,管理组租户编号 `000000`,后端自动通过请求头传递租户信息。
|
通过 `website.tenantMode` 控制开关,管理组租户编号 `000000`,后端自动通过请求头传递租户信息。
|
||||||
|
|
||||||
@@ -124,6 +135,7 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
|
|||||||
项目同时支持 **Options API**(主流,绝大多数现有页面)和 **Composition API**(新组件可选)。
|
项目同时支持 **Options API**(主流,绝大多数现有页面)和 **Composition API**(新组件可选)。
|
||||||
|
|
||||||
**选择原则**:
|
**选择原则**:
|
||||||
|
|
||||||
- 修改现有页面:保持该页面原有风格,不混用
|
- 修改现有页面:保持该页面原有风格,不混用
|
||||||
- 新建 CRUD 页面:调用 `avue-design` Skill 生成,或参考现有页面手动编写
|
- 新建 CRUD 页面:调用 `avue-design` Skill 生成,或参考现有页面手动编写
|
||||||
- 新建复杂交互页面:可使用 Composition API + `<script setup>`
|
- 新建复杂交互页面:可使用 Composition API + `<script setup>`
|
||||||
@@ -132,7 +144,7 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
|
|||||||
### 4.2 命名规范
|
### 4.2 命名规范
|
||||||
|
|
||||||
| 类型 | 命名方式 | 示例 |
|
| 类型 | 命名方式 | 示例 |
|
||||||
| -------------- | -------------------------- | ----------------------------- |
|
| ----------------------- | -------------------------- | --------------------------- |
|
||||||
| 页面文件 | kebab-case | `notice.vue` |
|
| 页面文件 | kebab-case | `notice.vue` |
|
||||||
| 组件文件 | kebab-case 目录 + main.vue | `basic-container/main.vue` |
|
| 组件文件 | kebab-case 目录 + main.vue | `basic-container/main.vue` |
|
||||||
| API / Option / 工具文件 | camelCase | `dict.js`、`dictbiz.js` |
|
| API / Option / 工具文件 | camelCase | `dict.js`、`dictbiz.js` |
|
||||||
@@ -148,6 +160,23 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
|
|||||||
|
|
||||||
- 全局 SCSS 变量通过 `styles/variables.scss` 定义,Vite 自动注入所有组件
|
- 全局 SCSS 变量通过 `styles/variables.scss` 定义,Vite 自动注入所有组件
|
||||||
- 编写样式优先使用已有变量和 mixin(`styles/mixin.scss`),而非硬编码值
|
- 编写样式优先使用已有变量和 mixin(`styles/mixin.scss`),而非硬编码值
|
||||||
|
- 系统主色调统一使用 `#409eff`,涉及主题变量、Element Plus 主题覆盖、按钮/链接/选中态等品牌色场景均应保持一致
|
||||||
|
- 各页面搜索栏多行展示时,行与行之间的垂直间距统一为 `8px`
|
||||||
|
- 搜索组件 label 宽度统一不小于 `160px`,label 文本不得换行。
|
||||||
|
- 搜索组件内部 padding 统一为上、左右 `12px`,底部 `4px`。
|
||||||
|
- 搜索组件需展示轻量阴影,统一使用 `0 2px 8px rgba(0, 0, 0, 0.06)`,不得被局部卡片去样式规则覆盖。
|
||||||
|
- 表格线条颜色需统一使用 `#EFF1F7`,包括表格外边框、单元格分割线和固定列边线。
|
||||||
|
- 表格偶数行需统一使用 `#FAFAFA` 背景色,固定列单元格必须与对应行背景保持一致。
|
||||||
|
- 表格操作列同时展示“查看、编辑、删除”等三个按钮时,操作列宽度统一不小于 `220px`;操作列最大按钮数量超过 3 个时,操作列宽度统一加宽到不小于 `320px`;最大按钮数量超过 4 个时,仍按 `320px` 保持列宽,并从第 5 个按钮开始换行展示,禁止出现按钮裁切或显示不全。
|
||||||
|
- 表格操作列按钮统一仅展示文字,禁止配置 `icon` / `:icon` 或在操作按钮、操作下拉项中嵌入图标;顶部工具栏按钮不受此条限制。
|
||||||
|
- 纯文字操作入口统一使用 `<el-link>`,禁止使用带 `text` 属性的 `<el-button>`;提交、确认、上传等具有明确命令语义或需要加载状态的按钮可继续使用 `<el-button>`。
|
||||||
|
- `.avue-crud__header` 顶部间距统一为 `12px`。
|
||||||
|
- 分页组件整体靠右展示,必须展示接口返回的数据总条数,`X条/页` 的页容量选择器必须放在总条数右侧。
|
||||||
|
- `.basic-container__card` 的直接子级 `.el-card__body` 内边距统一去除,保持 `padding: 0`
|
||||||
|
- 所有 CRUD 页面搜索栏需与下方表格拆分为独立区域,两者垂直间距统一为 `8px`。
|
||||||
|
- 所有 CRUD 页面搜索栏操作按钮(搜索、清空等)需在搜索表单下方独占一行并放置在最右侧;搜索条件超过一行时必须显示“展开/折叠”,默认折叠且仅展示一行搜索条件;一行布局默认展示 4 个筛选项,Avue 配置统一使用 `searchIndex: 4`。
|
||||||
|
- 所有 CRUD 页面中新增、批量导入等顶部按钮组行不需要背景色,应保持透明背景。
|
||||||
|
- 所有 `.basic-container__card` 内的 Avue 内层 `el-card` 需去卡片化,仅保留外层容器卡片样式,禁止出现二级卡片边框、阴影或额外内边距。
|
||||||
|
|
||||||
### 4.5 全局注册组件
|
### 4.5 全局注册组件
|
||||||
|
|
||||||
@@ -165,8 +194,15 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
|
|||||||
|
|
||||||
### 4.8 表单布局规范
|
### 4.8 表单布局规范
|
||||||
|
|
||||||
- 新增/编辑弹窗中的表单项,若 `label` 文案超过 4 个字,`label` 必须单独占一行展示,表单控件另起一行,避免长标签挤压输入控件或换行错位。
|
- 新增、编辑弹窗中的表单 `label` 默认必须位于控件左侧,Avue 配置统一使用 `labelPosition: 'right'` 与 `labelWidth: 'auto'`,Element Plus 表单统一使用 `label-position="right"` 与 `label-width="auto"`。
|
||||||
- 使用 Avue 配置、Element Plus 表单或自定义弹窗表单时均需遵守该规则;可通过 `label-position="top"`、自定义 `formslot`、局部样式或单项布局调整实现。
|
- 新增、编辑弹窗中的表单 `label` 宽度必须以当前视觉列内最长 `label` 为准;多列表单需按列分别计算 label 宽度,禁止用整张表单的最长 label 统一挤压所有列。
|
||||||
|
- 所有新增、编辑弹窗中的表单 `label` 文本必须右对齐,确保同一列内控件起始位置一致。
|
||||||
|
- 新增、编辑弹窗标题左侧必须展示 `4px` 宽的主色竖条,竖条与标题文本间距统一为 `8px`。
|
||||||
|
- 复杂布局弹窗中的自定义分区标题、明细表格标题、步骤区标题等承担弹窗内容标题作用时,也必须沿用 `4px` 主色竖条与 `8px` 标题间距;可使用全局 `.dialog-section-title` 或等效局部样式实现。
|
||||||
|
- 新增、编辑弹窗中的表单项上下间距统一为 `16px`,弹窗内表单布局不得叠加 `.el-col` 与 `.el-form-item` 的额外下边距。
|
||||||
|
- 所有新增、编辑弹窗中的备注字段(如果有)必须单独占一整行展示,禁止与其他字段并列;Avue 配置可使用 `span: 24` 或等效布局实现。
|
||||||
|
- 新增、编辑弹窗底部按钮顺序统一为“取消、提交”,取消按钮在左,提交按钮在右。
|
||||||
|
- 使用 Avue 配置、Element Plus 表单或自定义弹窗表单时均需遵守该规则;若局部组件因特殊结构无法自动对齐,应通过 `src/utils/dialog-form-label.js` 的全局增强、局部样式或 `formslot` 保证 `label` 左侧展示、按列统一宽度、文本右对齐。
|
||||||
|
|
||||||
### 4.9 审计字段展示规范
|
### 4.9 审计字段展示规范
|
||||||
|
|
||||||
@@ -175,6 +211,24 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
|
|||||||
- “更新人”列统一使用 `prop: 'updateUserName'`,并通过 `src/utils/audit.js` 中的 `formatUpdateUserName(row)` 做兼容兜底。
|
- “更新人”列统一使用 `prop: 'updateUserName'`,并通过 `src/utils/audit.js` 中的 `formatUpdateUserName(row)` 做兼容兜底。
|
||||||
- 表单提交仍保留后端审计字段机制,前端不得手动提交或覆盖 `createUser`、`updateUser`。
|
- 表单提交仍保留后端审计字段机制,前端不得手动提交或覆盖 `createUser`、`updateUser`。
|
||||||
|
|
||||||
|
### 4.10 表格排序规范
|
||||||
|
|
||||||
|
- 表格的排序默认按照创建时间降序;分页列表应由后端默认按 `create_time DESC` 返回,前端不得在无明确业务要求时覆盖为其它默认排序。
|
||||||
|
|
||||||
|
### 4.11 搜索顺序规范
|
||||||
|
|
||||||
|
- 当用户已明确列出筛选字段时,搜索栏必须严格按照用户给出的字段清单和顺序展示;不得自行新增、保留、推断或迁移未列出的筛选项。
|
||||||
|
- 新增/编辑表单字段、表格列字段和搜索筛选字段必须分开理解;除非用户明确要求同步,禁止把表单字段或表格字段擅自加入搜索栏。
|
||||||
|
- Avue 搜索栏的字段展示顺序按 `searchOrder` **倒序** 渲染,配置时数值越大越靠前。
|
||||||
|
|
||||||
|
### 4.12 日期区间搜索规范
|
||||||
|
|
||||||
|
- 当同一业务维度的筛选条件是开始/结束日期或时间,并且接口按区间查询时,前端搜索栏必须合并为一个 `searchRange: true` 的区间字段展示。
|
||||||
|
- 区间字段在页面层统一归一化为后端所需的起止参数,禁止同时保留两个独立的“开始/结束”搜索项。
|
||||||
|
- 若用户已明确要求展示区间样式,必须严格按区间控件实现,不得退回为两个普通日期控件。
|
||||||
|
- 修改搜索项顺序时必须同步调整 `searchOrder`,不要依赖 `column` 数组前后位置来控制搜索栏顺序。
|
||||||
|
- `searchIndex: 4` 仅控制首屏展示数量,不影响 `searchOrder` 的优先级。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. 新功能开发流程
|
## 5. 新功能开发流程
|
||||||
@@ -226,7 +280,7 @@ pnpm run serve # 预览构建产物
|
|||||||
项目采用 **Gitmoji** 风格,中文描述:
|
项目采用 **Gitmoji** 风格,中文描述:
|
||||||
|
|
||||||
| Emoji | 代码 | 场景 |
|
| Emoji | 代码 | 场景 |
|
||||||
| ---------- | ------------ | ---------------- |
|
| ---------- | ------------ | ------------------ |
|
||||||
| :sparkles: | `:sparkles:` | 新增功能、优化增强 |
|
| :sparkles: | `:sparkles:` | 新增功能、优化增强 |
|
||||||
| :bug: | `:bug:` | 修复 Bug |
|
| :bug: | `:bug:` | 修复 Bug |
|
||||||
| :zap: | `:zap:` | 性能优化、问题修复 |
|
| :zap: | `:zap:` | 性能优化、问题修复 |
|
||||||
|
|||||||
BIN
AI辅助编程规范与实战示例.docx
Normal file
225
AI辅助编程规范与实战示例.md
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
# AI 辅助编程规范与实战示例——以「货物类型模块」为例
|
||||||
|
|
||||||
|
> 文档目的:向业主说明我们团队如何用 AI 协作完成前端开发,包含协作流程、工程规范、以及一个可直接对照代码的真实模块示例,便于业主了解我们的工作方式、质量保障手段与可复用的经验。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、背景:我们为什么用 AI 编程
|
||||||
|
|
||||||
|
本项目(Saber3 企业级后台)是一个模块多、表单多、校验规则多、样式规范严苛的大型 Vue 3 工程。传统人工开发存在两个痛点:
|
||||||
|
|
||||||
|
1. **重复劳动多**:每个 CRUD 模块的列表、搜索、新增、编辑、导入、导出结构高度相似,但样式细节(表格线色、偶数行底色、操作列宽度、弹窗竖条等)又极易被写错。
|
||||||
|
2. **规范易漂移**:数十个模块由不同人开发,若没有统一约束,代码风格、校验口径、审计字段展示会逐渐不一致。
|
||||||
|
|
||||||
|
我们引入 AI 编程的核心思路不是"让 AI 自由发挥",而是**把人类沉淀的工程规范喂给 AI,让 AI 在规范的边界内批量、稳定地产出代码,再由人工做业务与视觉复核**。这样既提效,又保住质量底线。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、我们的 AI 协作流程(总览)
|
||||||
|
|
||||||
|
```
|
||||||
|
需求澄清 ──> 需求卡(单一事实来源)──> AGENTS.md(工程规范)──> AI 生成代码
|
||||||
|
│ │
|
||||||
|
└──────────────── 人工复核 / 验收 ──────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
四个关键阶段:
|
||||||
|
|
||||||
|
| 阶段 | 产物 | 负责人 | 说明 |
|
||||||
|
| ------- | --------------------------- | ------- | -------------------------------- |
|
||||||
|
| 1. 需求澄清 | 模块需求卡(.md) | 产品/前端 | 用 `模块需求卡生成规范.md` 统一格式,拆成 REQ 编号项 |
|
||||||
|
| 2. 规范约束 | AGENTS.md | 架构/前端 | 把技术栈、风格、样式、校验、审计等写成"对 AI 的强制条款" |
|
||||||
|
| 3. 代码生成 | view / option / api / utils | AI + 前端 | AI 按 AGENTS.md 生成,前端实时纠偏 |
|
||||||
|
| 4. 复核验收 | 可运行模块 | 前端/测试 | 校验业务规则、视觉规范、边界异常 |
|
||||||
|
|
||||||
|
**核心原则:需求卡和 AGENTS.md 是 AI 与人对齐的"单一事实来源",不靠口头交代。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、工程规范如何约束 AI(AGENTS.md 核心条款节选)
|
||||||
|
|
||||||
|
我们维护了一份 `AGENTS.md`,作为 AI 每次动手前的"必读规范"。与本示例强相关的条款有:
|
||||||
|
|
||||||
|
### 3.1 文件同构结构
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── views/base/cargo-type.vue # 页面(模板 + 交互逻辑)
|
||||||
|
├── option/base/cargo-type.js # Avue 表格/表单配置(与 views 同构路径)
|
||||||
|
└── api/base/cargo-type.js # 接口层(按业务模块组织)
|
||||||
|
```
|
||||||
|
|
||||||
|
> 规范要点:Avue 配置独立存放于 `src/option/`,与 `views` 和 `api` 保持同构的模块路径映射。AI 生成时不会把配置写死在页面里。
|
||||||
|
|
||||||
|
### 3.2 样式规范(极易被写错,故用规范强制)
|
||||||
|
|
||||||
|
- 表格线条颜色统一 `#EFF1F7`;偶数行背景 `#FAFAFA`,固定列须与行背景一致;
|
||||||
|
- 操作列同时展示"查看/编辑/删除"时宽度不小于 `220px`;
|
||||||
|
- `.avue-crud__header` 顶部间距 `12px`;
|
||||||
|
- `.basic-container__card` 内层 `el-card` 去卡片化(`padding: 0`);
|
||||||
|
- 主色统一 `#409eff`。
|
||||||
|
|
||||||
|
### 3.3 表单校验规范
|
||||||
|
|
||||||
|
- 金额类非负、经纬度范围、备注类 ≤200 字(前端阻止提交并提示);
|
||||||
|
- 新增、导入、编辑三处的校验口径必须一致;
|
||||||
|
- 审计字段(创建人/更新人)**禁止直接展示用户 ID**,须绑定后端返回的姓名字段(`createUserName`)。
|
||||||
|
|
||||||
|
### 3.4 批量导入失败明细规范(本项目重点)
|
||||||
|
|
||||||
|
- 部分数据导入失败时,前端必须自动下载后端返回的失败 Excel;
|
||||||
|
- 失败 Excel 字段顺序须与原模板一致,最后追加"导入失败原因"列;
|
||||||
|
- 前端需根据 `content-type` 区分"JSON 成功响应"与"Excel 文件流";
|
||||||
|
- 失败明细文件命名含业务名、导入失败明细、时间戳。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、实例拆解:货物类型模块
|
||||||
|
|
||||||
|
### 4.1 模块能力一览
|
||||||
|
|
||||||
|
货物类型是一个**两级层级**的主数据模块:一级货物类型(2 位编码)+ 二级货物类型(4 位编码,前 2 位须与上级一致)。功能包括:列表、条件查询、新增、编辑、查看、删除、批量删除、**批量导入 + 模板下载 + 失败明细加工**、批量导出。
|
||||||
|
|
||||||
|
### 4.2 文件同构结构(真实存在)
|
||||||
|
|
||||||
|
```
|
||||||
|
src/views/base/cargo-type.vue # 589 行,页面 + 交互
|
||||||
|
src/option/base/cargo-type.js # 189 行,Avue 列配置 + 校验器
|
||||||
|
src/api/base/cargo-type.js # 74 行,7 个接口方法
|
||||||
|
src/utils/import-excel.js # 109 行,通用导入弹窗(被本模块复用)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 AI 按规范落地的关键代码点
|
||||||
|
|
||||||
|
下面每一条都对应前述规范条款,可直接对照源码。
|
||||||
|
|
||||||
|
**① 三级文件分离(对应 3.1)**
|
||||||
|
|
||||||
|
页面只负责交互,配置与接口独立:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// src/views/base/cargo-type.vue
|
||||||
|
import { getList, getNextCode, getParentOptions, remove, submit } from '@/api/base/cargo-type';
|
||||||
|
import { getCargoTypeOption } from '@/option/base/cargo-type';
|
||||||
|
```
|
||||||
|
|
||||||
|
**② 表单校验三处一致(对应 3.3)**
|
||||||
|
|
||||||
|
前端表单(option)与 JS 内 `validateRow` 共用同一套规则口径,避免"表单能过、导入却崩":
|
||||||
|
|
||||||
|
```js
|
||||||
|
// src/views/base/cargo-type.vue —— 提交前的统一校验
|
||||||
|
validateRow(row) {
|
||||||
|
const pattern = row.typeLevel === 1 ? /^\d{2}$/ : /^\d{4}$/;
|
||||||
|
if (!pattern.test(row.cargoCode)) { this.$message.warning('货物类型编码格式不正确'); return false; }
|
||||||
|
if (row.typeLevel === 2 && !row.cargoCode.startsWith(row.parentCargoCode)) {
|
||||||
|
this.$message.warning('二级编码前2位必须与上级货物类型编码一致'); return false;
|
||||||
|
}
|
||||||
|
if (row.remark.length > 200) { this.$message.warning('备注不能超过200字'); return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
// src/option/base/cargo-type.js —— 弹窗表单的同源校验器
|
||||||
|
{ validator: (rule, value, callback) => {
|
||||||
|
const form = ctx.form || {};
|
||||||
|
const pattern = form.typeLevel === 1 ? /^\d{2}$/ : /^\d{4}$/;
|
||||||
|
// 同样的规则:格式 + 二级前缀一致性
|
||||||
|
}, trigger: 'blur' }
|
||||||
|
```
|
||||||
|
|
||||||
|
**③ 审计字段用姓名不用 ID(对应 3.3)**
|
||||||
|
|
||||||
|
```vue
|
||||||
|
|
||||||
|
<template #createUserName="{ row }">
|
||||||
|
{{ row.createUserName || row.createUser || '' }}
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
列表直接绑定 `createUserName`,避免出现一串无意义的用户 ID。
|
||||||
|
|
||||||
|
**④ 导入失败明细加工(对应 3.4,本项目 AI 协作的亮点)**
|
||||||
|
|
||||||
|
后端只返回原始失败原因文本,AI 被要求生成一个**可独立测试的小函数** `decorateCargoTypeFailDetail`,把原因按 A./B./C. 编号、追加规则说明、仅"导入失败原因"列标红、自动加宽列:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// src/views/base/cargo-type.vue
|
||||||
|
export const decorateCargoTypeFailDetail = async workbook => {
|
||||||
|
// 1. 映射表头列号
|
||||||
|
// 2. 清理非原因列的多余红色字体
|
||||||
|
// 3. 把每行原因拆条、编号、拼接规则说明
|
||||||
|
// 4. 仅操作"导入失败原因"列样式(黑字、无填充、自动换行)
|
||||||
|
// 5. 按 CARGO_TYPE_FAIL_COL_WIDTH 加宽各列
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
该函数通过通用导入工具 `import-excel.js` 的 `failDetailDecorator` 钩子注入,做到**模块零耦合复用**:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// 复用通用导入弹窗,仅传入本模块的加工函数
|
||||||
|
handleImport() {
|
||||||
|
openImportDialog(this, '货物类型', undefined, {
|
||||||
|
failDetailDecorator: decorateCargoTypeFailDetail,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**⑤ 样式规范落地(对应 3.2)**
|
||||||
|
|
||||||
|
```scss
|
||||||
|
/* src/views/base/cargo-type.vue <style> */
|
||||||
|
:deep(.el-table) {
|
||||||
|
--el-table-border-color: #eff1f7; /* 表格线条统一色 */
|
||||||
|
}
|
||||||
|
:deep(.el-table__body tr:nth-child(even) > td.el-table__cell) {
|
||||||
|
background: #fafafa; /* 偶数行底色,固定列同色 */
|
||||||
|
}
|
||||||
|
:deep(.basic-container__card) > .el-card__body { padding: 0; } /* 去卡片化 */
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 人机协作中,AI 不擅长、需要人工兜底的部分
|
||||||
|
|
||||||
|
诚实地说,AI 不是万能的。本模块在协作中由人工重点把控的有:
|
||||||
|
|
||||||
|
1. **业务规则澄清**:一级/二级层级关系、编码前缀约束这类"业务语义",需要产品/前端先讲清,AI 才能写出正确校验。
|
||||||
|
2. **视觉细节微调**:表格行高、表头高度、间距的最终眼检,依赖人工在浏览器里确认。
|
||||||
|
3. **前后端字段契约**:`CargoTypeVO` 是否返回 `createUserName`、失败 Excel 的表头文案,必须与后端对齐,AI 无法替你确认。
|
||||||
|
4. **破坏性操作确认**:删除/批量删除的二次确认文案与风险,由人工定稿。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、经验沉淀(可复用的 5 条)
|
||||||
|
|
||||||
|
1. **把规范写成 `AGENTS.md`,比口头交代可靠 10 倍。** AI 每次都会读,规范不会因人离职而丢失。
|
||||||
|
2. **需求卡是 AI 与人对齐的单一事实来源。** 用统一格式(REQ 编号 + 功能点/异常边界/反例)避免"我以为你要的是……"。
|
||||||
|
3. **把重复能力抽成 utils。** 如 `import-excel.js`,新模块导入直接复用,AI 只需写"本模块特有的加工函数"。
|
||||||
|
4. **校验三处一致**:前端表单、前端导入、后端校验口径对齐,且一处改、三处同步改。
|
||||||
|
5. **让 AI 生成"小而纯"的函数**(如失败明细加工函数),比让它改一整个 600 行页面更可控、更易测、更易复核。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、给业主的价值与建议
|
||||||
|
|
||||||
|
| 维度 | 传统方式 | 我们的 AI 协作方式 |
|
||||||
|
| ------- | --------- | ---------------- |
|
||||||
|
| 单模块开发周期 | 长,易返工 | 短,规范内一次成型 |
|
||||||
|
| 多模块一致性 | 易漂移 | AGENTS.md 强制统一 |
|
||||||
|
| 规范传承 | 靠老人带 | 沉淀为文件,新人/AI 即取即用 |
|
||||||
|
| 质量风险 | 校验、审计字段易漏 | 规范条款逐项约束 |
|
||||||
|
|
||||||
|
**建议**:业主要求交付的不只是代码,更是"可持续维护的规范资产"。我们交付的每个模块背后都有需求卡 + AGENTS.md + 复用 utils 三件套,后续无论是换人维护还是扩展新模块,成本都显著更低。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*附:本示例涉及的全部源码路径*
|
||||||
|
|
||||||
|
- `src/views/base/cargo-type.vue`
|
||||||
|
- `src/option/base/cargo-type.js`
|
||||||
|
- `src/api/base/cargo-type.js`
|
||||||
|
- `src/utils/import-excel.js`
|
||||||
|
- `AGENTS.md`(工程规范总纲)
|
||||||
|
- `模块需求卡生成规范.md`(需求卡格式规范)
|
||||||
142
icon-hover-demo.html
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>图标悬停圆形背景效果</title>
|
||||||
|
<style>
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
background: #f5f7fa;
|
||||||
|
padding: 40px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
h1 { font-size: 18px; margin: 0 0 24px; }
|
||||||
|
h2 { font-size: 14px; margin: 32px 0 12px; color: #666; }
|
||||||
|
.card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
max-width: 600px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0,0,0,0.06);
|
||||||
|
}
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24px;
|
||||||
|
padding: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 核心样式:图标按钮悬停圆形背景 */
|
||||||
|
.icon-hover-btn {
|
||||||
|
position: relative;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: transparent;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
.icon-hover-btn::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f2f3f5;
|
||||||
|
transform: scale(0.6);
|
||||||
|
opacity: 0;
|
||||||
|
transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
.icon-hover-btn:hover::before,
|
||||||
|
.icon-hover-btn:focus-visible::before {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.icon-hover-btn svg {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-block {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.6;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre;
|
||||||
|
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>图标悬停圆形背景效果</h1>
|
||||||
|
<div class="card">
|
||||||
|
<p>把鼠标移到下面的 T 恤图标上,就会出现类似“铃铛”示例的浅灰圆形背景。</p>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<button class="icon-hover-btn" aria-label="T恤">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M7 3l3 3h4l3-3 4 4-3 2v11a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V9L3 7l4-4z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span style="color:#999;font-size:13px;">↑ hover 查看效果</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>CSS 核心代码(可复制)</h2>
|
||||||
|
<pre class="code-block">.icon-hover-btn {
|
||||||
|
position: relative;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: transparent;
|
||||||
|
color: #333;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
.icon-hover-btn::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f2f3f5;
|
||||||
|
transform: scale(0.6);
|
||||||
|
opacity: 0;
|
||||||
|
transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
|
||||||
|
opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
.icon-hover-btn:hover::before,
|
||||||
|
.icon-hover-btn:focus-visible::before {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.icon-hover-btn svg {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<h2>Element Plus 用法示例</h2>
|
||||||
|
<pre class="code-block"><el-button class="icon-hover-btn" link>
|
||||||
|
<el-icon size="22"><Upload /></el-icon>
|
||||||
|
</el-button></pre>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
import-cargo-type/货物类型导入_一级.xlsx
Normal file
BIN
import-cargo-type/货物类型导入_二级.xlsx
Normal file
BIN
import-cargo-type/货物类型导入_单文件(一级在前).xlsx
Normal file
@@ -13,14 +13,14 @@
|
|||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||||
<meta name="format-detection" content="telephone=no" />
|
<meta name="format-detection" content="telephone=no" />
|
||||||
<link rel="icon" href="/favicon.png" />
|
|
||||||
<link rel="stylesheet" href="/iconfont/index.css" />
|
<link rel="stylesheet" href="/iconfont/index.css" />
|
||||||
<link rel="stylesheet" href="/iconfont/avue/iconfont.css" />
|
<link rel="stylesheet" href="/iconfont/avue/iconfont.css" />
|
||||||
<link rel="stylesheet" href="/iconfont/saber/iconfont.css" />
|
<link rel="stylesheet" href="/iconfont/saber/iconfont.css" />
|
||||||
<link rel="stylesheet" href="/iconfont/common/iconfont.css" />
|
<link rel="stylesheet" href="/iconfont/common/iconfont.css" />
|
||||||
<link rel="stylesheet" href="/css/loading.css" />
|
<link rel="stylesheet" href="/css/loading.css" />
|
||||||
<link rel="stylesheet" href="/css/saber.css" />
|
<link rel="stylesheet" href="/css/saber.css" />
|
||||||
<title>TMS物流运输管理系统</title>
|
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||||
|
<title>运输板块数字化管理平台</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
15
package.json
@@ -9,36 +9,41 @@
|
|||||||
"serve": "vite preview --host"
|
"serve": "vite preview --host"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"element-plus": "^2.14.2",
|
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@smallwei/avue": "~3.9.2",
|
"@open-file-viewer/core": "^0.1.27",
|
||||||
"avue-plugin-ueditor": "^1.0.4",
|
"@open-file-viewer/vue": "^0.1.27",
|
||||||
"@saber/nf-design-base-elp": "^1.3.0",
|
"@saber/nf-design-base-elp": "^1.3.0",
|
||||||
"@saber/nf-form-design-elp": "^1.6.1",
|
"@saber/nf-form-design-elp": "^1.6.1",
|
||||||
"@saber/nf-form-elp": "^1.6.3",
|
"@saber/nf-form-elp": "^1.6.3",
|
||||||
|
"@smallwei/avue": "~3.9.2",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
|
"avue-plugin-ueditor": "^1.0.4",
|
||||||
"axios": "^1.13.5",
|
"axios": "^1.13.5",
|
||||||
"codemirror": "^5.65.21",
|
"codemirror": "^5.65.21",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"dayjs": "^1.10.6",
|
"dayjs": "^1.10.6",
|
||||||
"disable-devtool": "^0.3.8",
|
"disable-devtool": "^0.3.8",
|
||||||
|
"element-plus": "^2.14.2",
|
||||||
|
"exceljs": "^4.4.0",
|
||||||
"highlight.js": "^11.9.0",
|
"highlight.js": "^11.9.0",
|
||||||
"js-base64": "^3.7.4",
|
"js-base64": "^3.7.4",
|
||||||
"js-cookie": "^3.0.0",
|
"js-cookie": "^3.0.0",
|
||||||
"js-md5": "^0.7.3",
|
"js-md5": "^0.7.3",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
"pdfjs-dist": "^6.1.200",
|
||||||
"sm-crypto": "^0.4.0",
|
"sm-crypto": "^0.4.0",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^11.4.2",
|
"vue-i18n": "^11.4.2",
|
||||||
"vue-router": "^4.3.2",
|
"vue-router": "^4.3.2",
|
||||||
"vue3-clipboard": "^1.0.0",
|
"vue3-clipboard": "^1.0.0",
|
||||||
"vuex": "^4.1.0"
|
"vuex": "^4.1.0",
|
||||||
|
"xlsx": "0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.2.4",
|
"@vitejs/plugin-vue": "^5.2.4",
|
||||||
"@vue/compiler-sfc": "^3.4.27",
|
"@vue/compiler-sfc": "^3.4.27",
|
||||||
"sass": "^1.85.1",
|
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
|
"sass": "^1.85.1",
|
||||||
"terser": "^5.31.1",
|
"terser": "^5.31.1",
|
||||||
"unplugin-auto-import": "^0.11.2",
|
"unplugin-auto-import": "^0.11.2",
|
||||||
"vite": "^5.4.19",
|
"vite": "^5.4.19",
|
||||||
|
|||||||
1244
pnpm-lock.yaml
generated
BIN
public/cargo-type-import-template.xlsx
Normal file
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
BIN
public/favicon.ico
Normal file
|
After Width: | Height: | Size: 794 B |
|
Before Width: | Height: | Size: 450 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 243 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 113 KiB |
73
src/api/base/cargo-type.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import request from '@/axios';
|
||||||
|
|
||||||
|
export const getList = (current, size, params) => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-system/cargo-type/list',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
current,
|
||||||
|
size,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDetail = id => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-system/cargo-type/detail',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const remove = ids => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-system/cargo-type/remove',
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
ids,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const submit = row => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-system/cargo-type/submit',
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const importCargoType = file => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
return request({
|
||||||
|
url: '/blade-system/cargo-type/import-cargo-type',
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 60000,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getParentOptions = keyword => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-system/cargo-type/parent-options',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
keyword,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getNextCode = parentCargoCode => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-system/cargo-type/next-code',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
parentCargoCode,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -39,14 +39,3 @@ export const remove = ids => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSourceOptions = (addressType, keyword) => {
|
|
||||||
return request({
|
|
||||||
url: '/blade-transport/common-address/source-options',
|
|
||||||
method: 'get',
|
|
||||||
params: {
|
|
||||||
addressType,
|
|
||||||
keyword,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
8
src/api/business/common-cargo.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { createCrudApi } from './common';
|
||||||
|
|
||||||
|
const api = createCrudApi('/blade-transport/common-cargo');
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const remove = api.remove;
|
||||||
8
src/api/business/common-route.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { createCrudApi } from './common';
|
||||||
|
|
||||||
|
const api = createCrudApi('/blade-transport/common-route');
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const remove = api.remove;
|
||||||
113
src/api/business/common.js
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import request from '@/axios';
|
||||||
|
|
||||||
|
export const createCrudApi = baseUrl => ({
|
||||||
|
getList(current, size, params) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/list`,
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
current,
|
||||||
|
size,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getDetail(id) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/detail`,
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
submit(row) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/submit`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
remove(ids) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/remove`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
ids,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
copy(id) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/copy`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enable(id) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/enable`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
disable(id) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/disable`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
cancel(id) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/cancel`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
complete(id) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/complete`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
dispatch(payload) {
|
||||||
|
const data = payload && typeof payload === 'object' ? payload : { id: payload };
|
||||||
|
const id = data.id || payload;
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/dispatch`,
|
||||||
|
method: 'post',
|
||||||
|
params: id ? { id } : undefined,
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
reassign(id) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/reassign`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
batchComplete(ids) {
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/batch-complete`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
ids,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
78
src/api/business/contract-manage.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { createCrudApi } from './common';
|
||||||
|
import request from '@/axios';
|
||||||
|
|
||||||
|
const baseUrl = '/blade-transport/contract-manage';
|
||||||
|
const api = createCrudApi(baseUrl);
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const remove = api.remove;
|
||||||
|
export const copy = api.copy;
|
||||||
|
|
||||||
|
export const saveDraft = row =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/save-draft`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const toTemporary = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/to-temporary`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const submitFormal = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/submit-formal`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const approve = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/approve`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const reject = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/reject`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const withdraw = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/withdraw`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const startChange = (id, reason) =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/start-change`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
changeContent: reason,
|
||||||
|
changeReason: reason,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const terminate = (id, reason) =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/terminate`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id, reason },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const expireStats = params =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/expire-stats`,
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
91
src/api/business/loading-manage.js
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import request from '@/axios';
|
||||||
|
|
||||||
|
const baseUrl = '/blade-transport/loading-manage';
|
||||||
|
|
||||||
|
export const exportUrl = `${baseUrl}/export-loading-manage`;
|
||||||
|
|
||||||
|
export const getList = (current, size, params) =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/list`,
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
...params,
|
||||||
|
current,
|
||||||
|
size,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getDetail = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/detail`,
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const saveDraft = row =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/save-draft`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const submit = row =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/submit`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const remove = ids =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/remove`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
ids,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const copy = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/copy`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const reassign = row =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/reassign`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const cancel = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/cancel`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const complete = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/complete`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const batchComplete = ids =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/batch-complete`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
ids,
|
||||||
|
},
|
||||||
|
});
|
||||||
11
src/api/business/process-config.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { createCrudApi } from './common';
|
||||||
|
|
||||||
|
const api = createCrudApi('/blade-transport/process-config');
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const remove = api.remove;
|
||||||
|
export const copy = api.copy;
|
||||||
|
export const enable = api.enable;
|
||||||
|
export const disable = api.disable;
|
||||||
77
src/api/business/project-apply.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import { createCrudApi } from './common';
|
||||||
|
import request from '@/axios';
|
||||||
|
|
||||||
|
const baseUrl = '/blade-transport/project-apply';
|
||||||
|
const api = createCrudApi(baseUrl);
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const remove = api.remove;
|
||||||
|
|
||||||
|
export const saveDraft = row =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/save-draft`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const submitApproval = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/submit-approval`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const approve = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/approve`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const reject = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/reject`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const withdraw = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/withdraw`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const voidProject = (id, reason) =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/void`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id, reason },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const saveChange = row =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/save-change`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const submitChange = row =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/submit-change`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const startChange = (id, reason) =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/start-change`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
changeContent: reason,
|
||||||
|
changeReason: reason,
|
||||||
|
},
|
||||||
|
});
|
||||||
11
src/api/business/shipping-template.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { createCrudApi } from './common';
|
||||||
|
import request from '@/axios';
|
||||||
|
|
||||||
|
const api = createCrudApi('/blade-transport/shipping-template');
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const remove = api.remove;
|
||||||
|
export const copy = api.copy;
|
||||||
|
export const nextCode = () => request({ url: '/blade-transport/shipping-template/next-code', method: 'get' });
|
||||||
45
src/api/business/temporary-credit-limit.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { createCrudApi } from './common';
|
||||||
|
import request from '@/axios';
|
||||||
|
|
||||||
|
const baseUrl = '/blade-transport/temporary-credit-limit';
|
||||||
|
const api = createCrudApi(baseUrl);
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const remove = api.remove;
|
||||||
|
|
||||||
|
export const saveDraft = row =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/save-draft`,
|
||||||
|
method: 'post',
|
||||||
|
data: row,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const submitApproval = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/submit-approval`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const approve = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/approve`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const reject = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/reject`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const withdraw = id =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/withdraw`,
|
||||||
|
method: 'post',
|
||||||
|
params: { id },
|
||||||
|
});
|
||||||
38
src/api/business/transport-plan.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { createCrudApi } from './common';
|
||||||
|
import request from '@/axios';
|
||||||
|
|
||||||
|
const baseUrl = '/blade-transport/transport-plan';
|
||||||
|
const api = createCrudApi(baseUrl);
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const dispatch = api.dispatch;
|
||||||
|
export const remove = api.remove;
|
||||||
|
export const copy = api.copy;
|
||||||
|
export const cancel = api.cancel;
|
||||||
|
export const complete = api.complete;
|
||||||
|
|
||||||
|
export const importTransportPlan = ({
|
||||||
|
file,
|
||||||
|
projectId,
|
||||||
|
projectName,
|
||||||
|
customerName,
|
||||||
|
contractId,
|
||||||
|
contractName,
|
||||||
|
}) => {
|
||||||
|
const data = new FormData();
|
||||||
|
data.append('file', file);
|
||||||
|
data.append('projectId', projectId || '');
|
||||||
|
data.append('projectName', projectName || '');
|
||||||
|
data.append('customerName', customerName || '');
|
||||||
|
data.append('contractId', contractId || '');
|
||||||
|
data.append('contractName', contractName || '');
|
||||||
|
return request({
|
||||||
|
url: `${baseUrl}/import-transport-plan`,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 60000,
|
||||||
|
});
|
||||||
|
};
|
||||||
32
src/api/business/waybill-manage.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import request from '@/axios';
|
||||||
|
import { createCrudApi } from './common';
|
||||||
|
|
||||||
|
const baseUrl = '/blade-transport/waybill-manage';
|
||||||
|
const api = createCrudApi(baseUrl);
|
||||||
|
|
||||||
|
export const getList = api.getList;
|
||||||
|
export const getDetail = api.getDetail;
|
||||||
|
export const submit = api.submit;
|
||||||
|
export const remove = api.remove;
|
||||||
|
export const copy = api.copy;
|
||||||
|
export const cancel = api.cancel;
|
||||||
|
export const reassign = api.reassign;
|
||||||
|
export const complete = api.complete;
|
||||||
|
export const batchComplete = api.batchComplete;
|
||||||
|
export const roadLoading = ids =>
|
||||||
|
request({
|
||||||
|
url: `${baseUrl}/road-loading`,
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
ids,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const getImportBatches = params => request({ url: `${baseUrl}/import-batch/list`, method: 'get', params });
|
||||||
|
export const getImportDetails = params => request({ url: `${baseUrl}/import-batch/details`, method: 'get', params });
|
||||||
|
export const removeImportBatches = ids => request({ url: `${baseUrl}/import-batch/remove`, method: 'post', params: { ids } });
|
||||||
|
export const getImportOptions = () => request({ url: `${baseUrl}/import-batch/options`, method: 'get' });
|
||||||
|
export const getImportContracts = projectId => request({ url: `${baseUrl}/import-batch/contracts`, method: 'get', params: { projectId } });
|
||||||
|
export const exportImportTemplate = () => request({ url: `${baseUrl}/import-batch/export-template`, method: 'get', responseType: 'blob' });
|
||||||
|
export const saveImportDraft = data => request({ url: `${baseUrl}/import-batch/draft`, method: 'post', data });
|
||||||
|
export const confirmImport = data => request({ url: `${baseUrl}/import-batch/confirm`, method: 'post', data });
|
||||||
@@ -1,15 +1,47 @@
|
|||||||
import request from '@/axios';
|
import request from '@/axios';
|
||||||
|
import { ElLoading, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 文件流返回
|
* 文件流返回
|
||||||
* @param url 接口地址
|
* @param url 接口地址
|
||||||
* @param params 接口参数
|
* @param params 接口参数
|
||||||
*/
|
*/
|
||||||
export const exportBlob = (url, params) => {
|
export const exportBlob = (url, params, options = {}) => {
|
||||||
|
const { feedback = false, loadingText = '导出中', successText = '导出完成' } = options;
|
||||||
|
const loading = feedback
|
||||||
|
? ElLoading.service({
|
||||||
|
lock: true,
|
||||||
|
text: loadingText,
|
||||||
|
background: 'rgba(255, 255, 255, 0.7)',
|
||||||
|
})
|
||||||
|
: null;
|
||||||
return request({
|
return request({
|
||||||
url: url,
|
url: url,
|
||||||
params: params,
|
params: params,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (feedback) {
|
||||||
|
ElMessage.success(successText);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
if (loading) {
|
||||||
|
loading.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const importBlob = (url, file) => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
return request({
|
||||||
|
url,
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
responseType: 'blob',
|
||||||
|
timeout: 60000,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,3 +58,23 @@ export const getExpiryStat = params => {
|
|||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const recognitionIDCard = url => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-file/file/recognitionIDCard',
|
||||||
|
method: 'get',
|
||||||
|
timeout: 60000,
|
||||||
|
params: {
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const recognitionTransportCertificates = certificates => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-file/file/recognitionTransportCertificates',
|
||||||
|
method: 'post',
|
||||||
|
timeout: 60000,
|
||||||
|
data: certificates,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -58,3 +58,12 @@ export const getExpiryStat = params => {
|
|||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const recognitionTransportCertificates = objectKeys => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-file/file/recognitionTransportCertificates',
|
||||||
|
method: 'post',
|
||||||
|
timeout: 60000,
|
||||||
|
data: objectKeys,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export default {
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.basic-container {
|
.basic-container {
|
||||||
padding: 10px 6px;
|
padding: 0 6px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
&--block {
|
&--block {
|
||||||
@@ -48,6 +48,11 @@ export default {
|
|||||||
|
|
||||||
&__card {
|
&__card {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
> .el-card__body {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<div class="cron-config-area">
|
<div class="cron-config-area">
|
||||||
<!-- 每天模式 -->
|
<!-- 每天模式 -->
|
||||||
<div v-if="cronMode === 'daily'" class="mode-content">
|
<div v-if="cronMode === 'daily'" class="mode-content">
|
||||||
<el-form :model="dailyConfig" label-width="100px" size="default">
|
<el-form :model="dailyConfig" label-width="auto" size="default">
|
||||||
<el-form-item label="执行时间">
|
<el-form-item label="执行时间">
|
||||||
<el-time-picker
|
<el-time-picker
|
||||||
v-model="dailyConfig.time"
|
v-model="dailyConfig.time"
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<!-- 每周模式 -->
|
<!-- 每周模式 -->
|
||||||
<div v-if="cronMode === 'weekly'" class="mode-content">
|
<div v-if="cronMode === 'weekly'" class="mode-content">
|
||||||
<el-form :model="weeklyConfig" label-width="100px" size="default">
|
<el-form :model="weeklyConfig" label-width="auto" size="default">
|
||||||
<el-form-item label="星期选择">
|
<el-form-item label="星期选择">
|
||||||
<el-checkbox-group v-model="weeklyConfig.weekDays" @change="generateCron" :disabled="disabled">
|
<el-checkbox-group v-model="weeklyConfig.weekDays" @change="generateCron" :disabled="disabled">
|
||||||
<el-checkbox label="1">周一</el-checkbox>
|
<el-checkbox label="1">周一</el-checkbox>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
<!-- 每月模式 -->
|
<!-- 每月模式 -->
|
||||||
<div v-if="cronMode === 'monthly'" class="mode-content">
|
<div v-if="cronMode === 'monthly'" class="mode-content">
|
||||||
<el-form :model="monthlyConfig" label-width="100px" size="default">
|
<el-form :model="monthlyConfig" label-width="auto" size="default">
|
||||||
<el-form-item label="日期选择">
|
<el-form-item label="日期选择">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="monthlyConfig.days"
|
v-model="monthlyConfig.days"
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
<!-- 自定义模式 -->
|
<!-- 自定义模式 -->
|
||||||
<div v-if="cronMode === 'custom'" class="mode-content">
|
<div v-if="cronMode === 'custom'" class="mode-content">
|
||||||
<el-form :model="customConfig" label-width="100px" size="default">
|
<el-form :model="customConfig" label-width="auto" size="default">
|
||||||
<el-form-item label="秒">
|
<el-form-item label="秒">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="customConfig.second"
|
v-model="customConfig.second"
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cron-result">
|
<div class="cron-result">
|
||||||
<el-form label-width="120px">
|
<el-form label-width="auto">
|
||||||
<el-form-item label="Cron 表达式">
|
<el-form-item label="Cron 表达式">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="cronExpression"
|
v-model="cronExpression"
|
||||||
@@ -567,7 +567,7 @@ export default {
|
|||||||
font-family: 'Courier New', monospace;
|
font-family: 'Courier New', monospace;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-checkbox) {
|
:deep(.el-checkbox) {
|
||||||
|
|||||||
69
src/components/empty-pagination/main.vue
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="shouldShow" class="empty-pagination avue-crud__pagination">
|
||||||
|
<el-pagination
|
||||||
|
background
|
||||||
|
:current-page="page.currentPage"
|
||||||
|
:page-size="pageSize"
|
||||||
|
:page-sizes="pageSizes"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'EmptyPagination',
|
||||||
|
props: {
|
||||||
|
page: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
alwaysShow: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['size-change', 'current-change', 'load'],
|
||||||
|
computed: {
|
||||||
|
shouldShow() {
|
||||||
|
return this.alwaysShow || this.isEmptyTotal;
|
||||||
|
},
|
||||||
|
isEmptyTotal() {
|
||||||
|
return Number(this.page.total || 0) === 0;
|
||||||
|
},
|
||||||
|
pageSize() {
|
||||||
|
return this.page.pageSize || 10;
|
||||||
|
},
|
||||||
|
pageSizes() {
|
||||||
|
return this.page.pageSizes || [10, 20, 50, 100];
|
||||||
|
},
|
||||||
|
total() {
|
||||||
|
return Number(this.page.total || 0);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSizeChange(pageSize) {
|
||||||
|
this.page.currentPage = 1;
|
||||||
|
this.page.pageSize = pageSize;
|
||||||
|
this.$emit('size-change', pageSize);
|
||||||
|
this.$emit('load');
|
||||||
|
},
|
||||||
|
handleCurrentChange(currentPage) {
|
||||||
|
this.page.currentPage = currentPage;
|
||||||
|
this.$emit('current-change', currentPage);
|
||||||
|
this.$emit('load');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.empty-pagination {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
139
src/components/image-upload-field/main.vue
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<el-form-item v-if="mode === 'form'" :label="label" :prop="prop">
|
||||||
|
<el-upload
|
||||||
|
:class="[`${classPrefix}-uploader`, { [`${classPrefix}-uploader--large`]: large }]"
|
||||||
|
action="/api/blade-resource/oss/endpoint/put-file"
|
||||||
|
name="file"
|
||||||
|
:headers="uploadHeaders"
|
||||||
|
:show-file-list="false"
|
||||||
|
:disabled="readonly"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
:on-progress="handleProgress"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
>
|
||||||
|
<img v-if="value" :src="value" :class="`${classPrefix}-uploader__image`" />
|
||||||
|
<div v-else :class="`${classPrefix}-uploader__empty`">{{ emptyText }}</div>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-else :prop="prop" :class="`${classPrefix}-upload-item`">
|
||||||
|
<div :class="[`${classPrefix}-upload-card`, { [`${classPrefix}-upload-card--large`]: large }]">
|
||||||
|
<div v-if="label" :class="`${classPrefix}-upload-card__head`">
|
||||||
|
<span :class="`${classPrefix}-upload-card__label`">{{ label }}</span>
|
||||||
|
<span :class="`${classPrefix}-upload-card__action`">{{ actionText }}</span>
|
||||||
|
</div>
|
||||||
|
<el-upload
|
||||||
|
:class="`${classPrefix}-upload-card__uploader`"
|
||||||
|
action="/api/blade-resource/oss/endpoint/put-file"
|
||||||
|
name="file"
|
||||||
|
:headers="uploadHeaders"
|
||||||
|
:show-file-list="false"
|
||||||
|
:disabled="readonly"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
:on-progress="handleProgress"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
>
|
||||||
|
<img v-if="value" :src="value" :class="`${classPrefix}-upload-card__image`" />
|
||||||
|
<div v-else :class="`${classPrefix}-upload-card__empty`">{{ emptyText }}</div>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ElLoading } from 'element-plus';
|
||||||
|
import { getUploadHeaders } from '@/utils/upload';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ImageUploadField',
|
||||||
|
props: {
|
||||||
|
label: String,
|
||||||
|
prop: String,
|
||||||
|
value: String,
|
||||||
|
readonly: Boolean,
|
||||||
|
headers: Object,
|
||||||
|
large: Boolean,
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'form',
|
||||||
|
},
|
||||||
|
classPrefix: {
|
||||||
|
type: String,
|
||||||
|
default: 'driver',
|
||||||
|
},
|
||||||
|
emptyText: {
|
||||||
|
type: String,
|
||||||
|
default: '上传证件图片',
|
||||||
|
},
|
||||||
|
actionText: {
|
||||||
|
type: String,
|
||||||
|
default: '点击上传',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
uploadHeaders() {
|
||||||
|
return getUploadHeaders(this.headers || {});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['success'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
uploadLoading: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
this.closeUploadLoading();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showUploadLoading() {
|
||||||
|
if (this.uploadLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.uploadLoading = ElLoading.service({
|
||||||
|
lock: true,
|
||||||
|
text: '上传中',
|
||||||
|
background: 'rgba(255, 255, 255, 0.7)',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
closeUploadLoading() {
|
||||||
|
if (!this.uploadLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.uploadLoading.close();
|
||||||
|
this.uploadLoading = null;
|
||||||
|
},
|
||||||
|
handleProgress() {
|
||||||
|
this.showUploadLoading();
|
||||||
|
},
|
||||||
|
handleSuccess(res) {
|
||||||
|
this.closeUploadLoading();
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
this.$message.success('上传完成');
|
||||||
|
this.$emit('success', res.data.link || res.data.url || res.data.domain || '', res.data);
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg || '上传失败');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleError() {
|
||||||
|
this.closeUploadLoading();
|
||||||
|
this.$message.error('上传失败');
|
||||||
|
},
|
||||||
|
beforeUpload(file) {
|
||||||
|
const validType = ['image/jpeg', 'image/png', 'image/jpg', 'image/bmp'].includes(file.type);
|
||||||
|
const validSize = file.size / 1024 / 1024 < 5;
|
||||||
|
if (!validType) {
|
||||||
|
this.$message.error('仅支持 JPG、PNG、BMP 图片');
|
||||||
|
}
|
||||||
|
if (!validSize) {
|
||||||
|
this.$message.error('图片大小不能超过 5MB');
|
||||||
|
}
|
||||||
|
const valid = validType && validSize;
|
||||||
|
if (valid) {
|
||||||
|
this.showUploadLoading();
|
||||||
|
}
|
||||||
|
return valid;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
:show-close="false"
|
:show-close="false"
|
||||||
width="20%"
|
width="20%"
|
||||||
>
|
>
|
||||||
<el-form :model="form" ref="form" label-width="80px">
|
<el-form :model="form" ref="form" label-width="auto">
|
||||||
<el-form-item v-if="tenantMode" label="租户编号">
|
<el-form-item v-if="tenantMode" label="租户编号">
|
||||||
<el-input v-model="form.tenantId" placeholder="请输入租户编号"></el-input>
|
<el-input v-model="form.tenantId" placeholder="请输入租户编号"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
365
src/components/vehicle-attachment-upload/main.vue
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
<template>
|
||||||
|
<div class="vehicle-attachment-upload">
|
||||||
|
<el-upload
|
||||||
|
:action="uploadAction"
|
||||||
|
name="file"
|
||||||
|
:headers="uploadHeaders"
|
||||||
|
:file-list="fileList"
|
||||||
|
:accept="acceptText"
|
||||||
|
:multiple="multiple"
|
||||||
|
:limit="limit"
|
||||||
|
:disabled="readonly"
|
||||||
|
:show-file-list="showFileList"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
:on-remove="handleRemove"
|
||||||
|
:on-preview="handlePreview"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
>
|
||||||
|
<el-button v-if="!readonly" type="primary" plain :icon="buttonIcon">
|
||||||
|
{{ buttonText }}
|
||||||
|
</el-button>
|
||||||
|
<template #tip>
|
||||||
|
<div v-if="showTip && tipText && !readonly" class="el-upload__tip">
|
||||||
|
{{ tipText }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
<span v-if="readonly && fileList.length === 0" class="vehicle-attachment-upload__empty">
|
||||||
|
-
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="previewVisible"
|
||||||
|
:title="previewFile.name || '附件预览'"
|
||||||
|
append-to-body
|
||||||
|
destroy-on-close
|
||||||
|
width="90%"
|
||||||
|
top="4vh"
|
||||||
|
class="vehicle-attachment-upload__viewer-dialog"
|
||||||
|
>
|
||||||
|
<open-file-viewer
|
||||||
|
v-if="previewVisible && previewSource"
|
||||||
|
:file="previewSource"
|
||||||
|
:file-name="previewFile.name"
|
||||||
|
:mime-type="previewFile.mimeType"
|
||||||
|
width="100%"
|
||||||
|
height="72vh"
|
||||||
|
fit="contain"
|
||||||
|
theme="auto"
|
||||||
|
locale="zh-CN"
|
||||||
|
:toolbar="viewerToolbar"
|
||||||
|
:plugins="viewerPlugins"
|
||||||
|
@unsupported="handleUnsupported"
|
||||||
|
@error="handleViewerError"
|
||||||
|
/>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { OpenFileViewer } from '@open-file-viewer/vue';
|
||||||
|
import {
|
||||||
|
fallbackPlugin,
|
||||||
|
imagePlugin,
|
||||||
|
officePlugin,
|
||||||
|
pdfPlugin,
|
||||||
|
textPlugin,
|
||||||
|
} from '@open-file-viewer/core';
|
||||||
|
import '@open-file-viewer/core/style.css';
|
||||||
|
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
||||||
|
import { baseUrl } from '@/config/env';
|
||||||
|
import { getUploadHeaders } from '@/utils/upload';
|
||||||
|
|
||||||
|
const MIME_MAP = {
|
||||||
|
jpg: 'image/jpeg',
|
||||||
|
jpeg: 'image/jpeg',
|
||||||
|
png: 'image/png',
|
||||||
|
gif: 'image/gif',
|
||||||
|
bmp: 'image/bmp',
|
||||||
|
webp: 'image/webp',
|
||||||
|
pdf: 'application/pdf',
|
||||||
|
doc: 'application/msword',
|
||||||
|
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
xls: 'application/vnd.ms-excel',
|
||||||
|
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
ppt: 'application/vnd.ms-powerpoint',
|
||||||
|
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
|
txt: 'text/plain',
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewerPlugins = [
|
||||||
|
imagePlugin(),
|
||||||
|
pdfPlugin({
|
||||||
|
workerSrc: pdfWorkerSrc,
|
||||||
|
useFetchData: true,
|
||||||
|
}),
|
||||||
|
officePlugin({
|
||||||
|
pdf: {
|
||||||
|
workerSrc: pdfWorkerSrc,
|
||||||
|
useFetchData: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
textPlugin(),
|
||||||
|
fallbackPlugin(),
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'VehicleAttachmentUpload',
|
||||||
|
components: {
|
||||||
|
OpenFileViewer,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: [Array, String, Object],
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
accept: {
|
||||||
|
type: [String, Array],
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
fileTypes: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
default: 20,
|
||||||
|
},
|
||||||
|
maxSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
type: String,
|
||||||
|
default: '上传附件',
|
||||||
|
},
|
||||||
|
buttonIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'el-icon-upload',
|
||||||
|
},
|
||||||
|
tip: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
showTip: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
showFileList: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue', 'change', 'success'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fileList: [],
|
||||||
|
previewVisible: false,
|
||||||
|
previewFile: {},
|
||||||
|
previewSource: '',
|
||||||
|
viewerToolbar: {
|
||||||
|
download: true,
|
||||||
|
fullscreen: true,
|
||||||
|
print: true,
|
||||||
|
rotate: true,
|
||||||
|
zoom: true,
|
||||||
|
},
|
||||||
|
viewerPlugins,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
uploadAction() {
|
||||||
|
return this.action || `${baseUrl}/blade-resource/oss/endpoint/put-file`;
|
||||||
|
},
|
||||||
|
uploadHeaders() {
|
||||||
|
return getUploadHeaders();
|
||||||
|
},
|
||||||
|
acceptedList() {
|
||||||
|
const types = this.fileTypes.length ? this.fileTypes : this.accept;
|
||||||
|
if (Array.isArray(types)) {
|
||||||
|
return types.map(item => String(item).trim()).filter(Boolean);
|
||||||
|
}
|
||||||
|
return String(types || '')
|
||||||
|
.split(',')
|
||||||
|
.map(item => item.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
},
|
||||||
|
acceptText() {
|
||||||
|
return this.acceptedList.join(',');
|
||||||
|
},
|
||||||
|
tipText() {
|
||||||
|
if (this.tip) return this.tip;
|
||||||
|
const typeText = this.acceptText || '所有类型';
|
||||||
|
const sizeText = this.maxSize > 0 ? `,单文件不超过 ${this.maxSize}MB` : '';
|
||||||
|
return `支持上传 ${typeText}${sizeText}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
modelValue: {
|
||||||
|
handler(value) {
|
||||||
|
this.fileList = this.toUploadList(value);
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toUploadList(value) {
|
||||||
|
const list = this.parseValue(value);
|
||||||
|
return list.map((item, index) => {
|
||||||
|
const url = this.getFileUrl(item);
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
uid: item.uid || `${url || item.name || 'file'}-${index}`,
|
||||||
|
name: item.name || this.getFileName(url) || '附件',
|
||||||
|
url,
|
||||||
|
status: 'success',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
parseValue(value) {
|
||||||
|
if (!value) return [];
|
||||||
|
if (Array.isArray(value)) return value.filter(Boolean);
|
||||||
|
if (typeof value === 'object') return [value];
|
||||||
|
try {
|
||||||
|
const list = JSON.parse(value);
|
||||||
|
return Array.isArray(list) ? list : [];
|
||||||
|
} catch (error) {
|
||||||
|
return String(value)
|
||||||
|
.split(',')
|
||||||
|
.map(item => item.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(item => ({
|
||||||
|
name: this.getFileName(item),
|
||||||
|
url: item,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getFileUrl(file) {
|
||||||
|
return file.url || file.link || file.src || file.domain || '';
|
||||||
|
},
|
||||||
|
getFileName(url) {
|
||||||
|
if (!url) return '';
|
||||||
|
const path = String(url).split('?')[0];
|
||||||
|
return decodeURIComponent(path.substring(path.lastIndexOf('/') + 1));
|
||||||
|
},
|
||||||
|
getExtension(file) {
|
||||||
|
const name = String(file.name || this.getFileUrl(file) || '').split('?')[0];
|
||||||
|
const index = name.lastIndexOf('.');
|
||||||
|
return index >= 0 ? name.substring(index + 1).toLowerCase() : '';
|
||||||
|
},
|
||||||
|
beforeUpload(file) {
|
||||||
|
if (!this.validFileType(file)) {
|
||||||
|
this.$message.warning('文件类型不符合上传要求');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.maxSize > 0 && file.size / 1024 / 1024 > this.maxSize) {
|
||||||
|
this.$message.warning(`单文件大小不能超过 ${this.maxSize}MB`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
validFileType(file) {
|
||||||
|
if (!this.acceptedList.length) return true;
|
||||||
|
const fileName = String(file.name || '').toLowerCase();
|
||||||
|
const mimeType = String(file.type || '').toLowerCase();
|
||||||
|
return this.acceptedList.some(type => {
|
||||||
|
const value = String(type).toLowerCase();
|
||||||
|
if (value === '*/*') return true;
|
||||||
|
if (value.startsWith('.')) return fileName.endsWith(value);
|
||||||
|
if (value.endsWith('/*')) return mimeType.startsWith(value.slice(0, -1));
|
||||||
|
if (value.includes('/')) return mimeType === value;
|
||||||
|
return fileName.endsWith(`.${value}`);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleSuccess(response, file, files) {
|
||||||
|
if (!response || response.success === false || (response.code && response.code !== 200)) {
|
||||||
|
this.$message.error((response && response.msg) || '上传失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.emitUploadFiles(this.multiple ? files : [file]);
|
||||||
|
this.$emit('success', this.normalizeUploadFile(file));
|
||||||
|
this.$message.success('上传成功');
|
||||||
|
},
|
||||||
|
handleError() {
|
||||||
|
this.$message.error('上传失败');
|
||||||
|
},
|
||||||
|
handleRemove(file, files) {
|
||||||
|
if (this.readonly) return false;
|
||||||
|
this.emitUploadFiles(files);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
emitUploadFiles(files) {
|
||||||
|
const list = files
|
||||||
|
.filter(file => file.status === 'success' || this.getFileUrl(file))
|
||||||
|
.map(this.normalizeUploadFile)
|
||||||
|
.filter(item => item.url);
|
||||||
|
this.$emit('update:modelValue', list);
|
||||||
|
this.$emit('change', list);
|
||||||
|
},
|
||||||
|
normalizeUploadFile(file) {
|
||||||
|
const data = (file.response && file.response.data) || file.data || file;
|
||||||
|
const url = data.link || data.url || data.domain || file.url || '';
|
||||||
|
const name = data.name || data.originalName || file.name || this.getFileName(url) || '附件';
|
||||||
|
const extension = this.getExtension({ name, url });
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
uid: file.uid || data.uid,
|
||||||
|
name,
|
||||||
|
url,
|
||||||
|
link: data.link || url,
|
||||||
|
size: data.size || data.attachSize || file.size || '',
|
||||||
|
extension,
|
||||||
|
mimeType: data.mimeType || data.contentType || file.raw?.type || MIME_MAP[extension] || '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
handlePreview(file) {
|
||||||
|
const previewFile = this.normalizeUploadFile(file);
|
||||||
|
if (!previewFile.url) {
|
||||||
|
this.$message.warning('附件地址为空,无法预览');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.previewFile = previewFile;
|
||||||
|
this.previewSource = previewFile.url;
|
||||||
|
this.previewVisible = true;
|
||||||
|
},
|
||||||
|
handleUnsupported() {
|
||||||
|
this.$message.warning('当前文件暂不支持在线预览');
|
||||||
|
},
|
||||||
|
handleViewerError() {
|
||||||
|
this.$message.error('附件预览失败');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.vehicle-attachment-upload {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
:deep(.el-upload-list__item-name) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__empty {
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.vehicle-attachment-upload__viewer-dialog .el-dialog__body) {
|
||||||
|
padding: 12px 16px 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -5,7 +5,7 @@ export default {
|
|||||||
title: '运输板块数字化管理平台',
|
title: '运输板块数字化管理平台',
|
||||||
logo: 'X',
|
logo: 'X',
|
||||||
key: 'saber', //配置主键,目前用于存储
|
key: 'saber', //配置主键,目前用于存储
|
||||||
indexTitle: 'TMS物流运输管理系统',
|
indexTitle: '运输板块数字化管理平台',
|
||||||
clientId: 'saber3', // 客户端id
|
clientId: 'saber3', // 客户端id
|
||||||
clientSecret: 'saber3_secret', // 客户端密钥
|
clientSecret: 'saber3_secret', // 客户端密钥
|
||||||
tenantMode: true, // 是否开启租户模式
|
tenantMode: true, // 是否开启租户模式
|
||||||
@@ -23,15 +23,17 @@ export default {
|
|||||||
//配置首页不可关闭
|
//配置首页不可关闭
|
||||||
setting: {
|
setting: {
|
||||||
sidebar: 'vertical',
|
sidebar: 'vertical',
|
||||||
tag: true,
|
tag: false,
|
||||||
debug: true,
|
debug: false,
|
||||||
collapse: true,
|
collapse: true,
|
||||||
search: true,
|
search: false,
|
||||||
color: true,
|
color: false,
|
||||||
lock: true,
|
lock: false,
|
||||||
screenshot: true,
|
screenshot: true,
|
||||||
fullscreen: true,
|
fullscreen: false,
|
||||||
theme: true,
|
theme: true,
|
||||||
|
lang: false,
|
||||||
|
settingBtn: false,
|
||||||
menu: true,
|
menu: true,
|
||||||
},
|
},
|
||||||
//首页配置
|
//首页配置
|
||||||
@@ -53,7 +55,7 @@ export default {
|
|||||||
//水印配置
|
//水印配置
|
||||||
watermark: {
|
watermark: {
|
||||||
mode: false,
|
mode: false,
|
||||||
text: 'TMS物流运输管理系统',
|
text: '运输板块数字化管理平台',
|
||||||
},
|
},
|
||||||
//oauth2配置
|
//oauth2配置
|
||||||
oauth2: {
|
oauth2: {
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export const option = {
|
|||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
grid: true,
|
grid: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
menuWidth: 250,
|
menuWidth: 160,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '数据源',
|
label: '数据源',
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export default {
|
|||||||
color: 'color',
|
color: 'color',
|
||||||
},
|
},
|
||||||
tagsView: {
|
tagsView: {
|
||||||
search: 'Search',
|
search: 'Query',
|
||||||
menu: 'menu',
|
menu: 'menu',
|
||||||
clearCache: 'Clear Cache',
|
clearCache: 'Clear Cache',
|
||||||
closeOthers: 'Close Others',
|
closeOthers: 'Close Others',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export default {
|
export default {
|
||||||
title: 'TMS物流运输管理系统',
|
title: '运输板块数字化管理平台',
|
||||||
confirmTip: '提示',
|
confirmTip: '提示',
|
||||||
logoutTip: '退出系统, 是否继续?',
|
logoutTip: '退出系统, 是否继续?',
|
||||||
submitText: '确定',
|
submitText: '确定',
|
||||||
@@ -28,18 +28,18 @@ export default {
|
|||||||
a: '全部',
|
a: '全部',
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
printBtn: '打 印',
|
printBtn: '打印',
|
||||||
mockBtn: '模 拟',
|
mockBtn: '模拟',
|
||||||
submitBtn: '提 交',
|
submitBtn: '提交',
|
||||||
emptyBtn: '清 空',
|
emptyBtn: '清空',
|
||||||
},
|
},
|
||||||
crud: {
|
crud: {
|
||||||
filter: {
|
filter: {
|
||||||
addBtn: '新增条件',
|
addBtn: '新增条件',
|
||||||
clearBtn: '清空数据',
|
clearBtn: '清空数据',
|
||||||
resetBtn: '清空条件',
|
resetBtn: '重置',
|
||||||
cancelBtn: '取 消',
|
cancelBtn: '取消',
|
||||||
submitBtn: '确 定',
|
submitBtn: '确定',
|
||||||
},
|
},
|
||||||
column: {
|
column: {
|
||||||
name: '列名',
|
name: '列名',
|
||||||
@@ -52,34 +52,34 @@ export default {
|
|||||||
},
|
},
|
||||||
tipStartTitle: '当前表格已选择',
|
tipStartTitle: '当前表格已选择',
|
||||||
tipEndTitle: '项',
|
tipEndTitle: '项',
|
||||||
editTitle: '编 辑',
|
editTitle: '编辑',
|
||||||
copyTitle: '复 制',
|
copyTitle: '复制',
|
||||||
addTitle: '新 增',
|
addTitle: '新增',
|
||||||
viewTitle: '查 看',
|
viewTitle: '查看',
|
||||||
filterTitle: '过滤条件',
|
filterTitle: '过滤条件',
|
||||||
showTitle: '列显隐',
|
showTitle: '列显隐',
|
||||||
menu: '操作',
|
menu: '操作',
|
||||||
addBtn: '新 增',
|
addBtn: '新增',
|
||||||
show: '显 示',
|
show: '显示',
|
||||||
hide: '隐 藏',
|
hide: '隐藏',
|
||||||
open: '展 开',
|
open: '展开',
|
||||||
shrink: '收 缩',
|
shrink: '收起',
|
||||||
printBtn: '打 印',
|
printBtn: '打印',
|
||||||
excelBtn: '导 出',
|
excelBtn: '导出',
|
||||||
updateBtn: '修 改',
|
updateBtn: '修改',
|
||||||
cancelBtn: '取 消',
|
cancelBtn: '取消',
|
||||||
searchBtn: '搜 索',
|
searchBtn: '搜索',
|
||||||
emptyBtn: '清 空',
|
emptyBtn: '重置',
|
||||||
menuBtn: '功 能',
|
menuBtn: '功能',
|
||||||
saveBtn: '保 存',
|
saveBtn: '保存',
|
||||||
viewBtn: '查 看',
|
viewBtn: '查看',
|
||||||
editBtn: '编 辑',
|
editBtn: '编辑',
|
||||||
copyBtn: '复 制',
|
copyBtn: '复制',
|
||||||
delBtn: '删 除',
|
delBtn: '删除',
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
title: '登录 ',
|
title: '登录 ',
|
||||||
info: 'TMS物流运输管理系统',
|
info: '运输板块数字化管理平台',
|
||||||
tenantId: '请输入租户ID',
|
tenantId: '请输入租户ID',
|
||||||
name: '请输入姓名',
|
name: '请输入姓名',
|
||||||
username: '请输入账号',
|
username: '请输入账号',
|
||||||
@@ -128,7 +128,7 @@ export default {
|
|||||||
color: '换色',
|
color: '换色',
|
||||||
},
|
},
|
||||||
tagsView: {
|
tagsView: {
|
||||||
search: '搜索',
|
search: '查询',
|
||||||
menu: '更多',
|
menu: '更多',
|
||||||
clearCache: '清除缓存',
|
clearCache: '清除缓存',
|
||||||
closeOthers: '关闭其它',
|
closeOthers: '关闭其它',
|
||||||
|
|||||||
26
src/main.js
@@ -13,6 +13,8 @@ import '@smallwei/avue/lib/index.css';
|
|||||||
import avueUeditor from 'avue-plugin-ueditor';
|
import avueUeditor from 'avue-plugin-ueditor';
|
||||||
import crudCommon from '@/mixins/crud.js';
|
import crudCommon from '@/mixins/crud.js';
|
||||||
import { getScreen, findColumn } from './utils/util';
|
import { getScreen, findColumn } from './utils/util';
|
||||||
|
import { setupPaginationEnhancer } from './utils/pagination';
|
||||||
|
import { setupDialogFormLabelAlign } from './utils/dialog-form-label';
|
||||||
import './permission';
|
import './permission';
|
||||||
import error from './error';
|
import error from './error';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
@@ -27,6 +29,8 @@ import codeEditor from './components/code-editor/main.vue';
|
|||||||
import cronEditor from './components/cron-editor/main.vue';
|
import cronEditor from './components/cron-editor/main.vue';
|
||||||
import basicBlock from './components/basic-block/main.vue';
|
import basicBlock from './components/basic-block/main.vue';
|
||||||
import basicContainer from './components/basic-container/main.vue';
|
import basicContainer from './components/basic-container/main.vue';
|
||||||
|
import emptyPagination from './components/empty-pagination/main.vue';
|
||||||
|
import vehicleAttachmentUpload from './components/vehicle-attachment-upload/main.vue';
|
||||||
import thirdRegister from './components/third-register/main.vue';
|
import thirdRegister from './components/third-register/main.vue';
|
||||||
import flowDesign from './components/flow-design/main.vue';
|
import flowDesign from './components/flow-design/main.vue';
|
||||||
import flowDesignStep from './components/flow-design-step/main.vue';
|
import flowDesignStep from './components/flow-design-step/main.vue';
|
||||||
@@ -45,6 +49,8 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|||||||
}
|
}
|
||||||
app.component('basicContainer', basicContainer);
|
app.component('basicContainer', basicContainer);
|
||||||
app.component('basicBlock', basicBlock);
|
app.component('basicBlock', basicBlock);
|
||||||
|
app.component('emptyPagination', emptyPagination);
|
||||||
|
app.component('vehicleAttachmentUpload', vehicleAttachmentUpload);
|
||||||
app.component('highlight', highlight);
|
app.component('highlight', highlight);
|
||||||
app.component('codeEditor', codeEditor);
|
app.component('codeEditor', codeEditor);
|
||||||
app.component('cronEditor', cronEditor);
|
app.component('cronEditor', cronEditor);
|
||||||
@@ -70,6 +76,24 @@ app.use(ElementPlus, {
|
|||||||
app.use(Avue, {
|
app.use(Avue, {
|
||||||
axios,
|
axios,
|
||||||
calcHeight: 10,
|
calcHeight: 10,
|
||||||
|
crudOption: {
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchLabelWidth: 160,
|
||||||
|
searchMenuSpan: 24,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
|
menuWidth: 160,
|
||||||
|
viewBtnIcon: ' ',
|
||||||
|
editBtnIcon: ' ',
|
||||||
|
copyBtnIcon: ' ',
|
||||||
|
delBtnIcon: ' ',
|
||||||
|
saveBtnIcon: ' ',
|
||||||
|
updateBtnIcon: ' ',
|
||||||
|
cancelBtnIcon: ' ',
|
||||||
|
mockBtnIcon: ' ',
|
||||||
|
},
|
||||||
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
locale: language,
|
locale: language,
|
||||||
i18n: (key, options) => i18n.global.t(key, options),
|
i18n: (key, options) => i18n.global.t(key, options),
|
||||||
});
|
});
|
||||||
@@ -79,3 +103,5 @@ app.use(VueClipboard, {
|
|||||||
appendToBody: true, // 这可以帮助解决一些更复杂的使用场景下的问题
|
appendToBody: true, // 这可以帮助解决一些更复杂的使用场景下的问题
|
||||||
});
|
});
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
|
setupPaginationEnhancer();
|
||||||
|
setupDialogFormLabelAlign();
|
||||||
|
|||||||
190
src/option/base/cargo-type.js
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
const typeLevelDic = [
|
||||||
|
{ label: '一级货物类型', value: 1 },
|
||||||
|
{ label: '二级货物类型', value: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const validateCargoName = (rule, value, callback) => {
|
||||||
|
const v = String(value || '').trim();
|
||||||
|
if (!v) {
|
||||||
|
callback(new Error('请输入货物类型名称'));
|
||||||
|
} else if (v.length > 50) {
|
||||||
|
callback(new Error('货物类型名称不能超过50字符'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateRemark = (rule, value, callback) => {
|
||||||
|
if (String(value || '').length > 200) {
|
||||||
|
callback(new Error('备注不能超过200字'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getCargoTypeOption = ctx => ({
|
||||||
|
height: 'auto',
|
||||||
|
calcHeight: 22,
|
||||||
|
dialogWidth: 760,
|
||||||
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
|
searchShow: true,
|
||||||
|
searchIcon: true,
|
||||||
|
searchLabelWidth: 50,
|
||||||
|
searchMenuSpan: 10,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
|
border: true,
|
||||||
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
indexWidth: 70,
|
||||||
|
viewBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
selection: true,
|
||||||
|
dialogClickModal: false,
|
||||||
|
menuWidth: 160,
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '类型',
|
||||||
|
prop: 'typeLevel',
|
||||||
|
type: 'radio',
|
||||||
|
dataType: 'number',
|
||||||
|
dicData: typeLevelDic,
|
||||||
|
search: true,
|
||||||
|
searchSpan: 6,
|
||||||
|
value: 2,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
minWidth: 120,
|
||||||
|
editDisabled: true,
|
||||||
|
rules: [{ required: true, message: '请选择货物类型级别', trigger: 'change' }],
|
||||||
|
change: ({ value }) => ctx.handleTypeLevelChange(value),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物类型',
|
||||||
|
prop: 'cargoName',
|
||||||
|
minWidth: 150,
|
||||||
|
maxlength: 50,
|
||||||
|
showWordLimit: true,
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
rules: [{ validator: validateCargoName, trigger: 'blur' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物类型编码',
|
||||||
|
prop: 'cargoCode',
|
||||||
|
minWidth: 140,
|
||||||
|
search: true,
|
||||||
|
searchSpan: 6,
|
||||||
|
maxlength: 4,
|
||||||
|
editDisabled: true,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
const form = ctx.form || {};
|
||||||
|
const code = String(value || '').trim();
|
||||||
|
const pattern = form.typeLevel === 1 ? /^\d{2}$/ : /^\d{4}$/;
|
||||||
|
if (!code) {
|
||||||
|
callback(new Error('请输入货物类型编码'));
|
||||||
|
} else if (!pattern.test(code)) {
|
||||||
|
callback(new Error('货物类型编码格式不正确'));
|
||||||
|
} else if (
|
||||||
|
form.typeLevel === 2 &&
|
||||||
|
form.parentCargoCode &&
|
||||||
|
!code.startsWith(form.parentCargoCode)
|
||||||
|
) {
|
||||||
|
callback(new Error('二级编码前2位必须与上级货物类型编码一致'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
change: ({ value }) => ctx.handleCargoCodeChange(value),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '上级货物类型',
|
||||||
|
prop: 'parentId',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
span: 12,
|
||||||
|
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '上级货物类型',
|
||||||
|
prop: 'parentCargoName',
|
||||||
|
slot: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
display: false,
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
minWidth: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '上级货物编码',
|
||||||
|
prop: 'parentCargoCode',
|
||||||
|
slot: true,
|
||||||
|
readonly: true,
|
||||||
|
editDisabled: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
display: false,
|
||||||
|
span: 12,
|
||||||
|
minWidth: 160,
|
||||||
|
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '创建人',
|
||||||
|
prop: 'createUserName',
|
||||||
|
slot: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
display: false,
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
minWidth: 180,
|
||||||
|
maxlength: 200,
|
||||||
|
showWordLimit: true,
|
||||||
|
overHidden: true,
|
||||||
|
showOverflowTooltip: true,
|
||||||
|
rules: [{ validator: validateRemark, trigger: 'blur' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '更新时间',
|
||||||
|
prop: 'updateTime',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
display: false,
|
||||||
|
sortable: true,
|
||||||
|
minWidth: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '创建时间',
|
||||||
|
prop: 'createTime',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
display: false,
|
||||||
|
sortable: true,
|
||||||
|
minWidth: 160,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
@@ -5,13 +5,18 @@ export const addressTypeOptions = [
|
|||||||
{ label: '空港机场', value: '空港机场' },
|
{ label: '空港机场', value: '空港机场' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const createOption = ({ validateLongitude, validateLatitude }) => ({
|
export const createOption = () => ({
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 980,
|
dialogWidth: 980,
|
||||||
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
@@ -22,14 +27,66 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
|
|||||||
delBtn: false,
|
delBtn: false,
|
||||||
addBtn: false,
|
addBtn: false,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
column: [
|
column: [
|
||||||
|
{
|
||||||
|
label: '类型',
|
||||||
|
prop: 'addressType',
|
||||||
|
type: 'select',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
span: 24,
|
||||||
|
dicData: addressTypeOptions,
|
||||||
|
rules: [{ required: true, message: '请选择类型', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '港口',
|
||||||
|
prop: 'portId',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
span: 12,
|
||||||
|
rules: [{ required: true, message: '请选择港口', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '码头',
|
||||||
|
prop: 'terminalId',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
span: 12,
|
||||||
|
rules: [{ required: true, message: '请选择码头', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '车站名称',
|
||||||
|
prop: 'stationId',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
span: 24,
|
||||||
|
rules: [{ required: true, message: '请选择车站名称', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '机场标准名称',
|
||||||
|
prop: 'airportId',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
span: 24,
|
||||||
|
rules: [{ required: true, message: '请选择机场标准名称', trigger: 'change' }],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '地址名称',
|
label: '地址名称',
|
||||||
prop: 'addressName',
|
prop: 'addressName',
|
||||||
search: true,
|
search: true,
|
||||||
|
span: 24,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
rules: [{ required: true, message: '请输入地址名称', trigger: 'blur' }],
|
maxlength: 100,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请输入地址名称', trigger: 'blur' },
|
||||||
|
{ max: 100, message: '地址名称不能超过100个字', trigger: 'blur' },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '地址编号',
|
label: '地址编号',
|
||||||
@@ -38,21 +95,6 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
|
|||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: '类型',
|
|
||||||
prop: 'addressType',
|
|
||||||
type: 'select',
|
|
||||||
search: true,
|
|
||||||
dicData: addressTypeOptions,
|
|
||||||
rules: [{ required: true, message: '请选择类型', trigger: 'change' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '来源主数据',
|
|
||||||
prop: 'sourceId',
|
|
||||||
formslot: true,
|
|
||||||
hide: true,
|
|
||||||
span: 24,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: '站点编码',
|
label: '站点编码',
|
||||||
prop: 'siteCodeDisplay',
|
prop: 'siteCodeDisplay',
|
||||||
@@ -69,6 +111,14 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
|
|||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '行政区划',
|
||||||
|
prop: 'regionName',
|
||||||
|
search: true,
|
||||||
|
display: false,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: [{ required: true, message: '请选择行政区划', trigger: 'change' }],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '详细地址',
|
label: '详细地址',
|
||||||
prop: 'detailAddress',
|
prop: 'detailAddress',
|
||||||
@@ -78,29 +128,10 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
|
|||||||
minRows: 3,
|
minRows: 3,
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 220,
|
minWidth: 220,
|
||||||
rules: [{ required: true, message: '请输入详细地址', trigger: 'blur' }],
|
rules: [
|
||||||
},
|
{ required: true, message: '请输入详细地址', trigger: 'blur' },
|
||||||
{
|
{ max: 255, message: '详细地址不能超过255个字', trigger: 'blur' },
|
||||||
label: '经度',
|
],
|
||||||
prop: 'longitude',
|
|
||||||
type: 'number',
|
|
||||||
precision: 6,
|
|
||||||
minWidth: 120,
|
|
||||||
rules: [{ validator: validateLongitude, trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '纬度',
|
|
||||||
prop: 'latitude',
|
|
||||||
type: 'number',
|
|
||||||
precision: 6,
|
|
||||||
minWidth: 120,
|
|
||||||
rules: [{ validator: validateLatitude, trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '行政区划',
|
|
||||||
prop: 'regionName',
|
|
||||||
search: true,
|
|
||||||
minWidth: 150,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '组织',
|
label: '组织',
|
||||||
@@ -123,12 +154,16 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
|
|||||||
prop: 'contactName',
|
prop: 'contactName',
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 110,
|
minWidth: 110,
|
||||||
|
maxlength: 50,
|
||||||
|
rules: [{ max: 50, message: '联系人不能超过50个字', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '联系方式',
|
label: '联系方式',
|
||||||
prop: 'contactPhone',
|
prop: 'contactPhone',
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 130,
|
minWidth: 130,
|
||||||
|
maxlength: 20,
|
||||||
|
rules: [{ max: 20, message: '联系方式不能超过20个字', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '备注',
|
label: '备注',
|
||||||
|
|||||||
193
src/option/business/common-cargo.js
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
import {
|
||||||
|
auditColumns,
|
||||||
|
createCrudOption,
|
||||||
|
packageOptions,
|
||||||
|
priceUnitOptions,
|
||||||
|
textRule,
|
||||||
|
} from './common';
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '常用货物',
|
||||||
|
permission: 'common_cargo',
|
||||||
|
exportUrl: '/blade-transport/common-cargo/export-common-cargo',
|
||||||
|
exportName: '常用货物',
|
||||||
|
importUrl: '/blade-transport/common-cargo/import-common-cargo',
|
||||||
|
templateUrl: '/blade-transport/common-cargo/export-template',
|
||||||
|
enableAllDept: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = createCrudOption([
|
||||||
|
{
|
||||||
|
label: '一级货物类型',
|
||||||
|
prop: 'firstCargoTypeName',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
minWidth: 150,
|
||||||
|
editDisabled: true,
|
||||||
|
rules: [{ required: true, message: '请选择一级货物类型', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '一级货物类型编码',
|
||||||
|
prop: 'firstCargoTypeCode',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '二级货物类型',
|
||||||
|
prop: 'secondCargoTypeName',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
minWidth: 150,
|
||||||
|
editDisabled: true,
|
||||||
|
rules: [{ required: true, message: '请选择二级货物类型', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '二级货物类型编码',
|
||||||
|
prop: 'secondCargoTypeCode',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物名称',
|
||||||
|
prop: 'cargoName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('货物名称', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物编号',
|
||||||
|
prop: 'cargoCode',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
minWidth: 120,
|
||||||
|
maxlength: 20,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请输入货物编号', trigger: 'blur' },
|
||||||
|
{ max: 20, message: '货物编号不能超过20个字符', trigger: 'blur' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '组织',
|
||||||
|
prop: 'deptName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 5,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '品牌',
|
||||||
|
prop: 'brand',
|
||||||
|
search: false,
|
||||||
|
minWidth: 120,
|
||||||
|
rules: textRule('品牌', 50),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '包装',
|
||||||
|
prop: 'packageType',
|
||||||
|
type: 'select',
|
||||||
|
dicData: packageOptions,
|
||||||
|
minWidth: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货值',
|
||||||
|
prop: 'cargoValue',
|
||||||
|
formslot: true,
|
||||||
|
minWidth: 120,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (value === undefined || value === null || value === '') {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!/^\d+(\.\d{1,2})?$/.test(String(value))) {
|
||||||
|
callback(new Error('货值只能输入数字,最多保留2位小数'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '计价单位',
|
||||||
|
prop: 'priceUnit',
|
||||||
|
type: 'select',
|
||||||
|
dicData: priceUnitOptions,
|
||||||
|
display: false,
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '规格',
|
||||||
|
prop: 'specification',
|
||||||
|
minWidth: 120,
|
||||||
|
rules: textRule('规格', 50),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '型号',
|
||||||
|
prop: 'model',
|
||||||
|
minWidth: 120,
|
||||||
|
rules: textRule('型号', 50),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '说明',
|
||||||
|
prop: 'descriptionOne',
|
||||||
|
minWidth: 160,
|
||||||
|
rules: textRule('说明', 100),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '数据来源',
|
||||||
|
prop: 'dataSource',
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
maxlength: 200,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: textRule('备注', 200),
|
||||||
|
},
|
||||||
|
...auditColumns,
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const excelOption = {
|
||||||
|
submitBtn: false,
|
||||||
|
emptyBtn: false,
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '导入模板',
|
||||||
|
prop: 'excelTemplate',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Excel文件',
|
||||||
|
prop: 'excelFile',
|
||||||
|
type: 'upload',
|
||||||
|
drag: true,
|
||||||
|
loadText: '模板上传中,请稍等',
|
||||||
|
span: 24,
|
||||||
|
propsHttp: {
|
||||||
|
res: 'data',
|
||||||
|
},
|
||||||
|
tip: '请上传 .xls,.xlsx 标准格式文件',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
145
src/option/business/common-route.js
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import { auditColumns, createCrudOption, phoneRule, textRule } from './common';
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '常用线路',
|
||||||
|
permission: 'common_route',
|
||||||
|
exportUrl: '/blade-transport/common-route/export-common-route',
|
||||||
|
exportName: '常用线路',
|
||||||
|
enableAllDept: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = createCrudOption([
|
||||||
|
{
|
||||||
|
label: '线路名称',
|
||||||
|
prop: 'routeName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
span: 24,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('线路名称', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '线路编号',
|
||||||
|
prop: 'routeCode',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货地',
|
||||||
|
prop: 'departureName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货地址',
|
||||||
|
prop: 'departureAddress',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
span: 24,
|
||||||
|
minWidth: 220,
|
||||||
|
rules: textRule('发货地址', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货经度',
|
||||||
|
prop: 'departureLongitude',
|
||||||
|
type: 'number',
|
||||||
|
precision: 6,
|
||||||
|
minWidth: 120,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货纬度',
|
||||||
|
prop: 'departureLatitude',
|
||||||
|
type: 'number',
|
||||||
|
precision: 6,
|
||||||
|
minWidth: 120,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货联系人',
|
||||||
|
prop: 'departureContact',
|
||||||
|
minWidth: 120,
|
||||||
|
rules: textRule('发货联系人', 50),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货联系方式',
|
||||||
|
prop: 'departurePhone',
|
||||||
|
minWidth: 140,
|
||||||
|
rules: [phoneRule('发货联系方式'), ...textRule('发货联系方式', 50)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货地',
|
||||||
|
prop: 'arrivalName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 5,
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货地址',
|
||||||
|
prop: 'arrivalAddress',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 6,
|
||||||
|
span: 24,
|
||||||
|
minWidth: 220,
|
||||||
|
rules: textRule('收货地址', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货经度',
|
||||||
|
prop: 'arrivalLongitude',
|
||||||
|
type: 'number',
|
||||||
|
precision: 6,
|
||||||
|
minWidth: 120,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货纬度',
|
||||||
|
prop: 'arrivalLatitude',
|
||||||
|
type: 'number',
|
||||||
|
precision: 6,
|
||||||
|
minWidth: 120,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货联系人',
|
||||||
|
prop: 'arrivalContact',
|
||||||
|
minWidth: 120,
|
||||||
|
rules: textRule('收货联系人', 50),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货联系方式',
|
||||||
|
prop: 'arrivalPhone',
|
||||||
|
minWidth: 140,
|
||||||
|
rules: [phoneRule('收货联系方式'), ...textRule('收货联系方式', 50)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '组织',
|
||||||
|
prop: 'deptName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 7,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
maxlength: 500,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: textRule('备注', 500),
|
||||||
|
},
|
||||||
|
...auditColumns,
|
||||||
|
]);
|
||||||
244
src/option/business/common.js
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
export const transportTypeOptions = [
|
||||||
|
{ label: '公路运输', value: '公路运输' },
|
||||||
|
{ label: '铁路运输', value: '铁路运输' },
|
||||||
|
{ label: '水路运输', value: '水路运输' },
|
||||||
|
{ label: '航空运输', value: '航空运输' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const packageOptions = [
|
||||||
|
{ label: '袋装', value: '袋装' },
|
||||||
|
{ label: '散装', value: '散装' },
|
||||||
|
{ label: '桶装', value: '桶装' },
|
||||||
|
{ label: '箱装', value: '箱装' },
|
||||||
|
{ label: '托盘', value: '托盘' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const priceUnitOptions = [
|
||||||
|
{ label: '元/吨', value: '元/吨' },
|
||||||
|
{ label: '元/立方米', value: '元/立方米' },
|
||||||
|
{ label: '元/件', value: '元/件' },
|
||||||
|
{ label: '元/车', value: '元/车' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const templateTypeOptions = [
|
||||||
|
{ label: '运输计划', value: '运输计划' },
|
||||||
|
{ label: '常规运单', value: '常规运单' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const processStatusOptions = [
|
||||||
|
{ label: '草稿', value: 0 },
|
||||||
|
{ label: '启用', value: 1 },
|
||||||
|
{ label: '停用', value: 2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const planStatusOptions = [
|
||||||
|
{ label: '草稿', value: 'draft' },
|
||||||
|
{ label: '待调度', value: 'waiting_dispatch' },
|
||||||
|
{ label: '调度中', value: 'dispatching' },
|
||||||
|
{ label: '已完成', value: 'completed' },
|
||||||
|
{ label: '已取消', value: 'cancelled' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const waybillStatusOptions = [
|
||||||
|
{ label: '草稿', value: 'draft' },
|
||||||
|
{ label: '待执行', value: 'pending' },
|
||||||
|
{ label: '进行中', value: 'processing' },
|
||||||
|
{ label: '已完成', value: 'completed' },
|
||||||
|
{ label: '已取消', value: 'cancelled' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const dataSourceOptions = [
|
||||||
|
{ label: '手工创建', value: '手工创建' },
|
||||||
|
{ label: '批量导入', value: '批量导入' },
|
||||||
|
{ label: '模板生成', value: '模板生成' },
|
||||||
|
{ label: '计划调度', value: '计划调度' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const projectTypeOptions = [
|
||||||
|
{ label: '普通项目', value: '普通项目' },
|
||||||
|
{ label: '重大项目', value: '重大项目' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const projectSourceOptions = [
|
||||||
|
{ label: '商务洽谈', value: '商务洽谈' },
|
||||||
|
{ label: '招投标', value: '招投标' },
|
||||||
|
{ label: '客户委托', value: '客户委托' },
|
||||||
|
{ label: '其它', value: '其它' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const projectApprovalStatusOptions = [
|
||||||
|
{ label: '草稿', value: 'draft' },
|
||||||
|
{ label: '审批中', value: 'reviewing' },
|
||||||
|
{ label: '已撤回', value: 'withdrawn' },
|
||||||
|
{ label: '审批通过', value: 'approved' },
|
||||||
|
{ label: '已驳回', value: 'rejected' },
|
||||||
|
{ label: '变更审批中', value: 'change_reviewing' },
|
||||||
|
{ label: '变更驳回', value: 'change_rejected' },
|
||||||
|
{ label: '变更审批通过', value: 'change_approved' },
|
||||||
|
{ label: '已作废', value: 'voided' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const approvalStatusOptions = [
|
||||||
|
{ label: '草稿', value: 'draft' },
|
||||||
|
{ label: '审批中', value: 'reviewing' },
|
||||||
|
{ label: '已撤回', value: 'withdrawn' },
|
||||||
|
{ label: '审批通过', value: 'approved' },
|
||||||
|
{ label: '已驳回', value: 'rejected' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const effectiveTypeOptions = [
|
||||||
|
{ label: '临时', value: 'temporary' },
|
||||||
|
{ label: '正式', value: 'formal' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const businessTypeOptions = [
|
||||||
|
{ label: '一类规模业务', value: '一类规模业务' },
|
||||||
|
{ label: '二类规模业务', value: '二类规模业务' },
|
||||||
|
{ label: '普通业务', value: '普通业务' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const settlementModeOptions = [
|
||||||
|
{ label: '先票后款', value: '先票后款' },
|
||||||
|
{ label: '先款后票', value: '先款后票' },
|
||||||
|
{ label: '月结', value: '月结' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const contractCategoryOptions = [
|
||||||
|
{ label: '客户合同', value: '客户合同' },
|
||||||
|
{ label: '承运商合同', value: '承运商合同' },
|
||||||
|
{ label: '补充协议', value: '补充协议' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const signTypeOptions = [
|
||||||
|
{ label: '新签', value: '新签' },
|
||||||
|
{ label: '续签', value: '续签' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const contractStageOptions = [
|
||||||
|
{ label: '草稿', value: 'draft' },
|
||||||
|
{ label: '临时合同', value: 'temporary' },
|
||||||
|
{ label: '正式合同', value: 'formal' },
|
||||||
|
{ label: '已终止', value: 'terminated' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const contractApprovalStatusOptions = [
|
||||||
|
{ label: '草稿', value: 'draft' },
|
||||||
|
{ label: '审批中', value: 'reviewing' },
|
||||||
|
{ label: '已驳回', value: 'rejected' },
|
||||||
|
{ label: '审批通过', value: 'approved' },
|
||||||
|
{ label: '变更审批中', value: 'change_reviewing' },
|
||||||
|
{ label: '变更驳回', value: 'change_rejected' },
|
||||||
|
{ label: '变更审批通过', value: 'change_approved' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const nodeOptions = [
|
||||||
|
{ label: '接单', value: '接单' },
|
||||||
|
{ label: '到场', value: '到场' },
|
||||||
|
{ label: '装货', value: '装货' },
|
||||||
|
{ label: '发货', value: '发货' },
|
||||||
|
{ label: '在途', value: '在途' },
|
||||||
|
{ label: '到货', value: '到货' },
|
||||||
|
{ label: '卸货', value: '卸货' },
|
||||||
|
{ label: '签收', value: '签收' },
|
||||||
|
{ label: '回单', value: '回单' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const textRule = (label, max, required = false) => {
|
||||||
|
const rules = [];
|
||||||
|
if (required) {
|
||||||
|
rules.push({ required: true, message: `请输入${label}`, trigger: 'blur' });
|
||||||
|
}
|
||||||
|
if (max) {
|
||||||
|
rules.push({ max, message: `${label}不能超过${max}个字符`, trigger: 'blur' });
|
||||||
|
}
|
||||||
|
return rules;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const selectRule = label => [
|
||||||
|
{ required: true, message: `请选择${label}`, trigger: 'change' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const nonNegativeRule = label => ({
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (value !== undefined && value !== null && value !== '' && Number(value) < 0) {
|
||||||
|
callback(new Error(`${label}不能小于0`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
trigger: 'blur',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const phoneRule = label => ({
|
||||||
|
pattern: /^(1\d{10}|0\d{2,3}-?\d{7,8})$/,
|
||||||
|
message: `${label}格式不正确`,
|
||||||
|
trigger: 'blur',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createCrudOption = columns => ({
|
||||||
|
height: 'auto',
|
||||||
|
calcHeight: 32,
|
||||||
|
dialogWidth: 980,
|
||||||
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
|
searchShow: true,
|
||||||
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
|
border: true,
|
||||||
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
indexWidth: 70,
|
||||||
|
selection: true,
|
||||||
|
addBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
dialogClickModal: false,
|
||||||
|
menuFixed: 'right',
|
||||||
|
menuWidth: 160,
|
||||||
|
column: columns,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const auditColumns = [
|
||||||
|
{
|
||||||
|
label: '创建人',
|
||||||
|
prop: 'createUserName',
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '更新人',
|
||||||
|
prop: 'updateUserName',
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '创建时间',
|
||||||
|
prop: 'createTime',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
minWidth: 160,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '更新时间',
|
||||||
|
prop: 'updateTime',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
minWidth: 160,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
574
src/option/business/contract-manage.js
Normal file
@@ -0,0 +1,574 @@
|
|||||||
|
import {
|
||||||
|
auditColumns,
|
||||||
|
contractApprovalStatusOptions,
|
||||||
|
contractCategoryOptions,
|
||||||
|
contractStageOptions,
|
||||||
|
createCrudOption,
|
||||||
|
effectiveTypeOptions,
|
||||||
|
selectRule,
|
||||||
|
settlementModeOptions,
|
||||||
|
signTypeOptions,
|
||||||
|
textRule,
|
||||||
|
} from './common';
|
||||||
|
|
||||||
|
const listDicFormatter = res => {
|
||||||
|
const data = res?.data || res;
|
||||||
|
if (Array.isArray(data)) return data;
|
||||||
|
if (Array.isArray(data?.records)) return data.records;
|
||||||
|
if (Array.isArray(data?.data)) return data.data;
|
||||||
|
if (Array.isArray(data?.data?.records)) return data.data.records;
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '合同管理',
|
||||||
|
permission: 'contract_manage',
|
||||||
|
exportUrl: '/blade-transport/contract-manage/export-contract-manage',
|
||||||
|
exportName: '合同管理',
|
||||||
|
enableAllDept: false,
|
||||||
|
batchDelete: false,
|
||||||
|
enableContractForm: true,
|
||||||
|
enableProjectSelect: true,
|
||||||
|
enableContractPeriod: true,
|
||||||
|
enableContractFileUpload: true,
|
||||||
|
enableCurrentUserHandler: true,
|
||||||
|
enableBillingPlan: true,
|
||||||
|
enableSettlementRule: true,
|
||||||
|
enableReconciliation: true,
|
||||||
|
enableAttachmentTable: true,
|
||||||
|
enableChangeRecord: true,
|
||||||
|
enableOrganizationSelect: true,
|
||||||
|
enableContractCreateActions: true,
|
||||||
|
actions: ['copy'],
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
statusTextProp: 'approvalStatusName',
|
||||||
|
customMenuActions: true,
|
||||||
|
editLabelStatusMap: {
|
||||||
|
change_rejected: '编辑变更内容',
|
||||||
|
},
|
||||||
|
deleteStatus: ['draft'],
|
||||||
|
deleteStage: ['draft'],
|
||||||
|
editStatus: ['draft', 'rejected', 'change_rejected'],
|
||||||
|
operations: [
|
||||||
|
{
|
||||||
|
action: 'flow',
|
||||||
|
label: '查看流程',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing', 'change_reviewing'],
|
||||||
|
stage: ['temporary', 'formal'],
|
||||||
|
permission: 'contract_manage_view',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'withdraw',
|
||||||
|
label: '撤回',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing'],
|
||||||
|
stage: ['temporary'],
|
||||||
|
permission: 'contract_manage_withdraw',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'submitFormal',
|
||||||
|
label: '重新提交转正',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['rejected'],
|
||||||
|
stage: ['temporary'],
|
||||||
|
permission: 'contract_manage_formal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'startChange',
|
||||||
|
label: '发起变更',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['approved'],
|
||||||
|
stage: ['formal'],
|
||||||
|
permission: 'contract_manage_change',
|
||||||
|
prompt: '请输入变更内容与原因',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'startChange',
|
||||||
|
label: '再次发起变更',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['change_approved'],
|
||||||
|
stage: ['formal'],
|
||||||
|
permission: 'contract_manage_change',
|
||||||
|
prompt: '请输入变更内容与原因',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'attachmentUpload',
|
||||||
|
label: '附件上传',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['approved', 'change_approved'],
|
||||||
|
stage: ['formal'],
|
||||||
|
permission: 'contract_manage_edit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'flow',
|
||||||
|
label: '查看流程',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['approved', 'change_approved'],
|
||||||
|
stage: ['formal', 'terminated'],
|
||||||
|
permission: 'contract_manage_view',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'withdraw',
|
||||||
|
label: '撤回变更',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['change_reviewing'],
|
||||||
|
stage: ['formal'],
|
||||||
|
permission: 'contract_manage_withdraw',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'startChange',
|
||||||
|
label: '重新提交变更',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['change_rejected'],
|
||||||
|
stage: ['formal'],
|
||||||
|
permission: 'contract_manage_change',
|
||||||
|
prompt: '请输入变更内容与原因',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = createCrudOption([
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'basicInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 200,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '合同编号',
|
||||||
|
prop: 'contractNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 6,
|
||||||
|
order: 185,
|
||||||
|
disabled: true,
|
||||||
|
placeholder: '不填写,则系统自动生成',
|
||||||
|
minWidth: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '合同名称',
|
||||||
|
prop: 'contractName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 7,
|
||||||
|
order: 180,
|
||||||
|
minWidth: 180,
|
||||||
|
rules: textRule('合同名称', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '所属项目',
|
||||||
|
prop: 'projectName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 8,
|
||||||
|
searchType: 'select',
|
||||||
|
formslot: true,
|
||||||
|
order: 140,
|
||||||
|
dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
|
||||||
|
dicFormatter: listDicFormatter,
|
||||||
|
props: {
|
||||||
|
label: 'projectName',
|
||||||
|
value: 'projectName',
|
||||||
|
},
|
||||||
|
filterable: true,
|
||||||
|
minWidth: 160,
|
||||||
|
rules: selectRule('所属项目'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '所属项目ID',
|
||||||
|
prop: 'projectId',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '所属组织',
|
||||||
|
prop: 'organizationName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
searchType: 'cascader',
|
||||||
|
formslot: true,
|
||||||
|
order: 120,
|
||||||
|
dicData: [],
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'id',
|
||||||
|
children: 'children',
|
||||||
|
},
|
||||||
|
checkStrictly: true,
|
||||||
|
emitPath: false,
|
||||||
|
showAllLevels: false,
|
||||||
|
filterable: true,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: selectRule('所属组织'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '合同类别',
|
||||||
|
prop: 'contractCategory',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 9,
|
||||||
|
order: 170,
|
||||||
|
dicData: contractCategoryOptions,
|
||||||
|
minWidth: 130,
|
||||||
|
rules: selectRule('合同类别'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '签约类型',
|
||||||
|
prop: 'signType',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
span: 6,
|
||||||
|
row: true,
|
||||||
|
order: 190,
|
||||||
|
dicData: signTypeOptions,
|
||||||
|
minWidth: 120,
|
||||||
|
rules: selectRule('签约类型'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '生效类型',
|
||||||
|
prop: 'effectiveType',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 5,
|
||||||
|
dicData: effectiveTypeOptions,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '甲方',
|
||||||
|
prop: 'partyA',
|
||||||
|
type: 'select',
|
||||||
|
order: 160,
|
||||||
|
dicUrl: '/blade-transport/customer-archive/list?current=1&size=9999&approvalStatus=approved',
|
||||||
|
dicFormatter: listDicFormatter,
|
||||||
|
props: {
|
||||||
|
label: 'fullName',
|
||||||
|
value: 'fullName',
|
||||||
|
},
|
||||||
|
filterable: true,
|
||||||
|
minWidth: 160,
|
||||||
|
rules: selectRule('甲方'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '乙方',
|
||||||
|
prop: 'partyB',
|
||||||
|
type: 'select',
|
||||||
|
order: 150,
|
||||||
|
dicUrl: '/blade-transport/customer-archive/list?current=1&size=9999&approvalStatus=approved',
|
||||||
|
dicFormatter: listDicFormatter,
|
||||||
|
props: {
|
||||||
|
label: 'fullName',
|
||||||
|
value: 'fullName',
|
||||||
|
},
|
||||||
|
filterable: true,
|
||||||
|
minWidth: 160,
|
||||||
|
rules: selectRule('乙方'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '合同期限',
|
||||||
|
prop: 'contractPeriod',
|
||||||
|
formslot: true,
|
||||||
|
order: 130,
|
||||||
|
hide: true,
|
||||||
|
rules: [{ required: true, message: '请选择合同期限', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '开始日期',
|
||||||
|
prop: 'startDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '结束日期',
|
||||||
|
prop: 'endDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '临时效力起',
|
||||||
|
prop: 'temporaryStartDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '临时效力止',
|
||||||
|
prop: 'temporaryEndDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '经办人',
|
||||||
|
prop: 'handlerUserName',
|
||||||
|
order: 110,
|
||||||
|
disabled: true,
|
||||||
|
minWidth: 120,
|
||||||
|
rules: textRule('经办人', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '签订日期',
|
||||||
|
prop: 'signDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
hide: true,
|
||||||
|
order: 100,
|
||||||
|
minWidth: 130,
|
||||||
|
rules: [{ required: true, message: '请选择签订日期', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '结算方式',
|
||||||
|
prop: 'settlementMode',
|
||||||
|
type: 'select',
|
||||||
|
dicData: settlementModeOptions,
|
||||||
|
hide: true,
|
||||||
|
order: 90,
|
||||||
|
minWidth: 120,
|
||||||
|
rules: selectRule('结算方式'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '合同格式',
|
||||||
|
prop: 'contractFormat',
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{ label: '电子合同', value: '电子合同' },
|
||||||
|
{ label: '纸质合同', value: '纸质合同' },
|
||||||
|
],
|
||||||
|
hide: true,
|
||||||
|
order: 80,
|
||||||
|
minWidth: 120,
|
||||||
|
rules: selectRule('合同格式'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '是否需要加盖法人章',
|
||||||
|
prop: 'legalSealFlag',
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{ label: '否', value: 0 },
|
||||||
|
{ label: '是', value: 1 },
|
||||||
|
],
|
||||||
|
value: 0,
|
||||||
|
hide: true,
|
||||||
|
order: 70,
|
||||||
|
minWidth: 100,
|
||||||
|
rules: selectRule('是否需要加盖法人章'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '一式',
|
||||||
|
prop: 'copyCount',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
order: 60,
|
||||||
|
minWidth: 110,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '回款账期',
|
||||||
|
prop: 'paymentDays',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
order: 50,
|
||||||
|
minWidth: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '创建时间',
|
||||||
|
prop: 'createTime',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
minWidth: 160,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '合同阶段',
|
||||||
|
prop: 'contractStage',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
slot: true,
|
||||||
|
dicData: contractStageOptions,
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '审核状态',
|
||||||
|
prop: 'approvalStatus',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
slot: true,
|
||||||
|
dicData: contractApprovalStatusOptions,
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '当前节点',
|
||||||
|
prop: 'currentNode',
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '当前处理人',
|
||||||
|
prop: 'currentProcessor',
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '计费信息',
|
||||||
|
prop: 'billingEnabled',
|
||||||
|
type: 'switch',
|
||||||
|
dicData: [
|
||||||
|
{ label: '关闭', value: 0 },
|
||||||
|
{ label: '开启', value: 1 },
|
||||||
|
],
|
||||||
|
value: 1,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
minWidth: 110,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
order: 40,
|
||||||
|
maxlength: 2000,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: textRule('备注', 2000),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'contractFileTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 30,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '附件',
|
||||||
|
prop: 'contractFileJson',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 20,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'billingInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 10,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'billingPlanJson',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 0,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'settlementRuleTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: -10,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'settlementRuleJson',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: -20,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'reconciliationTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: -30,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'reconciliationJson',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: -40,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'attachmentTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: -50,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'attachmentsJson',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: -60,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'changeRecordTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: -70,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'changeRecordJson',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: -80,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
...auditColumns
|
||||||
|
.filter(column => column.prop !== 'createTime')
|
||||||
|
.map(column => ({ ...column, hide: true })),
|
||||||
|
]);
|
||||||
|
|
||||||
|
option.span = 8;
|
||||||
|
option.dialogWidth = 1480;
|
||||||
36
src/option/business/loading-manage.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { dataSourceOptions } from './common';
|
||||||
|
|
||||||
|
export const transportTypeDict = {
|
||||||
|
dicUrl: '/blade-system/dict-biz/dictionary?code=transport_type',
|
||||||
|
props: {
|
||||||
|
label: 'dictValue',
|
||||||
|
value: 'dictKey',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const carrierTypeOptions = ['承运商', '自运', '网签平台'];
|
||||||
|
|
||||||
|
export const loadingStatusOptions = [
|
||||||
|
{ label: '草稿', value: 'draft' },
|
||||||
|
{ label: '待执行', value: 'pending' },
|
||||||
|
{ label: '进行中', value: 'running' },
|
||||||
|
{ label: '已完成', value: 'completed' },
|
||||||
|
{ label: '已取消', value: 'cancelled' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const loadingStatusMap = loadingStatusOptions.reduce((result, item) => {
|
||||||
|
result[item.value] = item.label;
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
export const loadingManageConfig = {
|
||||||
|
title: '配载管理',
|
||||||
|
permission: 'loading_manage',
|
||||||
|
exportUrl: '/blade-transport/loading-manage/export-loading-manage',
|
||||||
|
exportName: '配载管理',
|
||||||
|
createText: '新建配载',
|
||||||
|
batchCompleteText: '批量完成',
|
||||||
|
statusProp: 'businessStatus',
|
||||||
|
statusTextProp: 'businessStatusName',
|
||||||
|
dataSourceOptions,
|
||||||
|
};
|
||||||
148
src/option/business/process-config.js
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
import {
|
||||||
|
auditColumns,
|
||||||
|
createCrudOption,
|
||||||
|
nodeOptions,
|
||||||
|
processStatusOptions,
|
||||||
|
selectRule,
|
||||||
|
textRule,
|
||||||
|
} from './common';
|
||||||
|
import { applyTableMenuWidth } from '@/utils/table-menu';
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '过程配置',
|
||||||
|
permission: 'process_config',
|
||||||
|
exportUrl: '/blade-transport/process-config/export-process-config',
|
||||||
|
exportName: '过程配置',
|
||||||
|
enableAllDept: false,
|
||||||
|
actions: ['copy', 'enable', 'disable'],
|
||||||
|
statusProp: 'status',
|
||||||
|
statusTextProp: 'statusName',
|
||||||
|
deleteStatus: [0, 2],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = applyTableMenuWidth({
|
||||||
|
...createCrudOption([
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'basicInfo',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配置编号',
|
||||||
|
prop: 'configCode',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配置名称',
|
||||||
|
prop: 'configName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 6,
|
||||||
|
span: 12,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
rules: textRule('配置名称', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目ID集合',
|
||||||
|
prop: 'projectIds',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
rules: textRule('项目ID集合', 1000, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目',
|
||||||
|
prop: 'projectNames',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 5,
|
||||||
|
searchType: 'select',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 2,
|
||||||
|
span: 12,
|
||||||
|
minWidth: 180,
|
||||||
|
dicData: [],
|
||||||
|
filterable: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
rules: textRule('项目', 1000, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '包含过程节点',
|
||||||
|
prop: 'includedNodes',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
type: 'select',
|
||||||
|
multiple: true,
|
||||||
|
dicData: nodeOptions,
|
||||||
|
minWidth: 180,
|
||||||
|
rules: selectRule('包含过程节点'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '默认完成运输天数',
|
||||||
|
prop: 'defaultFinishDays',
|
||||||
|
formslot: true,
|
||||||
|
type: 'number',
|
||||||
|
min: 1,
|
||||||
|
max: 999,
|
||||||
|
span: 12,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '状态',
|
||||||
|
prop: 'status',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
dicData: processStatusOptions,
|
||||||
|
slot: true,
|
||||||
|
minWidth: 100,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '组织',
|
||||||
|
prop: 'deptName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'nodeConfigJson',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
maxlength: 500,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: textRule('备注', 500),
|
||||||
|
},
|
||||||
|
...auditColumns,
|
||||||
|
]),
|
||||||
|
dialogTop: '10px',
|
||||||
|
dialogWidth: '96%',
|
||||||
|
searchSpan: 8,
|
||||||
|
}, 5);
|
||||||
406
src/option/business/project-apply.js
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
import {
|
||||||
|
auditColumns,
|
||||||
|
businessTypeOptions,
|
||||||
|
createCrudOption,
|
||||||
|
effectiveTypeOptions,
|
||||||
|
nonNegativeRule,
|
||||||
|
projectApprovalStatusOptions,
|
||||||
|
projectSourceOptions,
|
||||||
|
projectTypeOptions,
|
||||||
|
selectRule,
|
||||||
|
settlementModeOptions,
|
||||||
|
textRule,
|
||||||
|
} from './common';
|
||||||
|
|
||||||
|
const amountRules = label => [
|
||||||
|
{ required: true, message: `请输入${label}`, trigger: 'blur' },
|
||||||
|
nonNegativeRule(label),
|
||||||
|
];
|
||||||
|
|
||||||
|
const userDicFormatter = res => {
|
||||||
|
const list = Array.isArray(res)
|
||||||
|
? res
|
||||||
|
: Array.isArray(res.data)
|
||||||
|
? res.data
|
||||||
|
: res.data?.records || [];
|
||||||
|
return list.map(user => ({
|
||||||
|
...user,
|
||||||
|
realName: user.realName || user.name || user.account,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '项目管理',
|
||||||
|
permission: 'project_apply',
|
||||||
|
exportUrl: '/blade-transport/project-apply/export-project-apply',
|
||||||
|
exportName: '项目立项',
|
||||||
|
enableAllDept: false,
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
statusTextProp: 'approvalStatusName',
|
||||||
|
deleteStatus: ['draft', 'withdrawn', 'rejected'],
|
||||||
|
editStatus: ['draft', 'withdrawn', 'rejected', 'change_rejected'],
|
||||||
|
operations: [
|
||||||
|
{
|
||||||
|
action: 'submitApproval',
|
||||||
|
label: '提交',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['draft'],
|
||||||
|
permission: 'project_apply_submit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'withdraw',
|
||||||
|
label: '撤回',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing'],
|
||||||
|
permission: 'project_apply_withdraw',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'approve',
|
||||||
|
label: '通过',
|
||||||
|
type: 'success',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing', 'change_reviewing'],
|
||||||
|
permission: 'project_apply_approve',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'reject',
|
||||||
|
label: '审批驳回',
|
||||||
|
type: 'warning',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing', 'change_reviewing'],
|
||||||
|
permission: 'project_apply_reject',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'startChange',
|
||||||
|
label: '变更',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['approved'],
|
||||||
|
permission: 'project_apply_change',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'voidProject',
|
||||||
|
label: '作废',
|
||||||
|
type: 'danger',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['approved', 'change_approved'],
|
||||||
|
permission: 'project_apply_void',
|
||||||
|
prompt: '请输入作废原因',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = createCrudOption([
|
||||||
|
{
|
||||||
|
label: '立项申请单号',
|
||||||
|
prop: 'applyNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 7,
|
||||||
|
minWidth: 160,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目编号',
|
||||||
|
prop: 'projectCode',
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目名称',
|
||||||
|
prop: 'projectName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 6,
|
||||||
|
minWidth: 180,
|
||||||
|
maxlength: 50,
|
||||||
|
rules: textRule('项目名称', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目简称',
|
||||||
|
prop: 'projectShortName',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 140,
|
||||||
|
maxlength: 20,
|
||||||
|
rules: textRule('项目简称', 20, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目类型',
|
||||||
|
prop: 'projectType',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
dicData: projectTypeOptions,
|
||||||
|
minWidth: 120,
|
||||||
|
rules: selectRule('项目类型'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '客户名称',
|
||||||
|
prop: 'customerNames',
|
||||||
|
minWidth: 180,
|
||||||
|
rules: textRule('客户名称', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '下游承运商',
|
||||||
|
prop: 'carrierNames',
|
||||||
|
minWidth: 180,
|
||||||
|
rules: textRule('下游承运商', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '业务部门',
|
||||||
|
prop: 'businessDeptName',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('业务部门', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '承办部门',
|
||||||
|
prop: 'undertakeDeptName',
|
||||||
|
search: true,
|
||||||
|
searchLabel: '承办单位',
|
||||||
|
searchOrder: 5,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('承办部门', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '承办部门ID',
|
||||||
|
prop: 'undertakeDeptId',
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目负责人',
|
||||||
|
prop: 'principalUserName',
|
||||||
|
minWidth: 130,
|
||||||
|
rules: textRule('项目负责人', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目负责人',
|
||||||
|
prop: 'principalUserId',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
filterable: true,
|
||||||
|
dicUrl: '/blade-system/user/user-list',
|
||||||
|
dicFormatter: userDicFormatter,
|
||||||
|
props: {
|
||||||
|
label: 'realName',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目经办人',
|
||||||
|
prop: 'handlerUserName',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 130,
|
||||||
|
rules: textRule('项目经办人', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目由来',
|
||||||
|
prop: 'projectSource',
|
||||||
|
type: 'select',
|
||||||
|
dicData: projectSourceOptions,
|
||||||
|
value: '商务洽谈',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目资金使用额度(万元)',
|
||||||
|
prop: 'fundLimit',
|
||||||
|
type: 'number',
|
||||||
|
precision: 2,
|
||||||
|
hide: true,
|
||||||
|
minWidth: 190,
|
||||||
|
rules: amountRules('项目资金使用额度'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目应收账款额度(万元)',
|
||||||
|
prop: 'receivableLimit',
|
||||||
|
type: 'number',
|
||||||
|
precision: 2,
|
||||||
|
hide: true,
|
||||||
|
minWidth: 200,
|
||||||
|
rules: amountRules('项目应收账款额度'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '应收账款回款期限(天)',
|
||||||
|
prop: 'receivableDays',
|
||||||
|
type: 'number',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 190,
|
||||||
|
rules: [{ required: true, message: '请输入应收账款回款期限', trigger: 'blur' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '回款账期(天)',
|
||||||
|
prop: 'paymentDays',
|
||||||
|
type: 'number',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 140,
|
||||||
|
rules: [{ required: true, message: '请输入回款账期', trigger: 'blur' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物类型',
|
||||||
|
prop: 'cargoType',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '预估货物数量',
|
||||||
|
prop: 'cargoQuantity',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 150,
|
||||||
|
maxlength: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '业务周期开始',
|
||||||
|
prop: 'businessStartDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '业务周期结束',
|
||||||
|
prop: 'businessEndDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运输线路',
|
||||||
|
prop: 'transportRoute',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 180,
|
||||||
|
maxlength: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运输类型',
|
||||||
|
prop: 'transportType',
|
||||||
|
type: 'select',
|
||||||
|
dicUrl: '/blade-system/dict-biz/dictionary?code=transport_type',
|
||||||
|
props: {
|
||||||
|
label: 'dictValue',
|
||||||
|
value: 'dictKey',
|
||||||
|
},
|
||||||
|
hide: true,
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '业务类型',
|
||||||
|
prop: 'businessType',
|
||||||
|
type: 'select',
|
||||||
|
dicData: businessTypeOptions,
|
||||||
|
hide: true,
|
||||||
|
minWidth: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目规模(万元)',
|
||||||
|
prop: 'projectScale',
|
||||||
|
type: 'number',
|
||||||
|
precision: 2,
|
||||||
|
hide: true,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: [nonNegativeRule('项目规模')],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '预计利润(万元)',
|
||||||
|
prop: 'estimatedProfit',
|
||||||
|
type: 'number',
|
||||||
|
precision: 2,
|
||||||
|
hide: true,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: [nonNegativeRule('预计利润')],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '资金需求(万元)',
|
||||||
|
prop: 'fundDemand',
|
||||||
|
type: 'number',
|
||||||
|
precision: 2,
|
||||||
|
hide: true,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: [nonNegativeRule('资金需求')],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '结算方式',
|
||||||
|
prop: 'settlementMode',
|
||||||
|
type: 'select',
|
||||||
|
dicData: settlementModeOptions,
|
||||||
|
hide: true,
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '审批状态',
|
||||||
|
prop: 'approvalStatus',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
slot: true,
|
||||||
|
dicData: projectApprovalStatusOptions,
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '当前节点',
|
||||||
|
prop: 'currentNode',
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '当前处理人',
|
||||||
|
prop: 'currentProcessor',
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '生效类型',
|
||||||
|
prop: 'effectiveType',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
dicData: effectiveTypeOptions,
|
||||||
|
value: 'temporary',
|
||||||
|
minWidth: 110,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '审核通过时间',
|
||||||
|
prop: 'approvedTime',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
minWidth: 170,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目由来说明',
|
||||||
|
prop: 'sourceRemark',
|
||||||
|
type: 'textarea',
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
maxlength: 300,
|
||||||
|
showWordLimit: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目情况说明',
|
||||||
|
prop: 'situationRemark',
|
||||||
|
type: 'textarea',
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
maxlength: 1000,
|
||||||
|
showWordLimit: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目附件JSON',
|
||||||
|
prop: 'attachmentsJson',
|
||||||
|
type: 'textarea',
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
...auditColumns.map(column => ({ ...column, hide: true })),
|
||||||
|
]);
|
||||||
213
src/option/business/shipping-template.js
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
import { auditColumns, createCrudOption, selectRule, textRule, transportTypeOptions } from './common';
|
||||||
|
|
||||||
|
const templateTypeOptions = [
|
||||||
|
{ label: '运输计划', value: '运输计划' },
|
||||||
|
{ label: '运单', value: '运单' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '发货模板',
|
||||||
|
permission: 'shipping_template',
|
||||||
|
exportUrl: '/blade-transport/shipping-template/export-shipping-template',
|
||||||
|
exportName: '发货模板',
|
||||||
|
enableAllDept: false,
|
||||||
|
enableProjectSelect: true,
|
||||||
|
enableAttachmentTable: true,
|
||||||
|
enableTransportPlanForm: true,
|
||||||
|
enableTemplateCodePreview: true,
|
||||||
|
attachmentTitle: '附件',
|
||||||
|
defaultForm: {
|
||||||
|
templateType: '运输计划',
|
||||||
|
},
|
||||||
|
transportFormRequiredFields: [
|
||||||
|
['projectName', '项目'],
|
||||||
|
['contractName', '客户合同'],
|
||||||
|
['transportType', '运输方式'],
|
||||||
|
['departureAddress', '发货地址'],
|
||||||
|
['arrivalAddress', '收货地址'],
|
||||||
|
],
|
||||||
|
actions: ['copy'],
|
||||||
|
operations: [
|
||||||
|
{
|
||||||
|
action: 'createFromTemplate',
|
||||||
|
label: '从模板新建',
|
||||||
|
permission: 'shipping_template_add',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = {
|
||||||
|
...createCrudOption([
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'templateInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 400,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '模板编号',
|
||||||
|
prop: 'templateCode',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
span: 8,
|
||||||
|
order: 390,
|
||||||
|
minWidth: 170,
|
||||||
|
disabled: true,
|
||||||
|
placeholder: '系统自动生成',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '模板名称',
|
||||||
|
prop: 'templateName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
span: 8,
|
||||||
|
order: 380,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('模板名称', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '模板类型',
|
||||||
|
prop: 'templateType',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
span: 8,
|
||||||
|
order: 370,
|
||||||
|
dicData: templateTypeOptions,
|
||||||
|
minWidth: 120,
|
||||||
|
rules: selectRule('模板类型'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 3,
|
||||||
|
span: 24,
|
||||||
|
order: 360,
|
||||||
|
minWidth: 180,
|
||||||
|
maxlength: 200,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: textRule('备注', 200),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'basicInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 350,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目',
|
||||||
|
prop: 'projectName',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
span: 8,
|
||||||
|
order: 340,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('项目', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '客户合同',
|
||||||
|
prop: 'contractName',
|
||||||
|
formslot: true,
|
||||||
|
span: 8,
|
||||||
|
order: 330,
|
||||||
|
minWidth: 160,
|
||||||
|
rules: textRule('客户合同', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运输方式',
|
||||||
|
prop: 'transportType',
|
||||||
|
type: 'select',
|
||||||
|
span: 8,
|
||||||
|
order: 320,
|
||||||
|
dicData: transportTypeOptions,
|
||||||
|
minWidth: 130,
|
||||||
|
rules: selectRule('运输方式'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'shippingInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 310,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货地址',
|
||||||
|
prop: 'departureAddress',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 300,
|
||||||
|
minWidth: 220,
|
||||||
|
rules: textRule('发货地址', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货地址',
|
||||||
|
prop: 'arrivalAddress',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 290,
|
||||||
|
minWidth: 220,
|
||||||
|
rules: textRule('收货地址', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'goodsInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 280,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'goodsJson',
|
||||||
|
type: 'textarea',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 270,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: '0px',
|
||||||
|
className: 'business-crud-page__full-form-item',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'attachmentTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 260,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'attachmentsJson',
|
||||||
|
type: 'textarea',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 250,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: '0px',
|
||||||
|
className: 'business-crud-page__full-form-item',
|
||||||
|
},
|
||||||
|
{ label: '项目ID', prop: 'projectId', hide: true, display: false },
|
||||||
|
{ label: '客户合同ID', prop: 'contractId', hide: true, display: false },
|
||||||
|
{ label: '发货地', prop: 'departureName', hide: true, display: false },
|
||||||
|
{ label: '发货联系人', prop: 'departureContact', hide: true, display: false },
|
||||||
|
{ label: '发货联系方式', prop: 'departurePhone', hide: true, display: false },
|
||||||
|
{ label: '收货地', prop: 'arrivalName', hide: true, display: false },
|
||||||
|
{ label: '收货联系人', prop: 'arrivalContact', hide: true, display: false },
|
||||||
|
{ label: '收货联系方式', prop: 'arrivalPhone', hide: true, display: false },
|
||||||
|
{ label: '所属组织', prop: 'deptName', minWidth: 150, addDisplay: false, editDisplay: false },
|
||||||
|
...auditColumns,
|
||||||
|
]),
|
||||||
|
dialogWidth: '96%',
|
||||||
|
};
|
||||||
265
src/option/business/temporary-credit-limit.js
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
import {
|
||||||
|
approvalStatusOptions,
|
||||||
|
auditColumns,
|
||||||
|
createCrudOption,
|
||||||
|
nonNegativeRule,
|
||||||
|
textRule,
|
||||||
|
} from './common';
|
||||||
|
|
||||||
|
const listDicFormatter = res => {
|
||||||
|
const data = res?.data || res;
|
||||||
|
if (Array.isArray(data)) return data;
|
||||||
|
if (Array.isArray(data?.records)) return data.records;
|
||||||
|
if (Array.isArray(data?.data)) return data.data;
|
||||||
|
if (Array.isArray(data?.data?.records)) return data.data.records;
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const userDicFormatter = res =>
|
||||||
|
listDicFormatter(res).map(user => ({
|
||||||
|
...user,
|
||||||
|
realName: user.realName || user.name || user.account,
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '临时额度管理',
|
||||||
|
permission: 'temporary_credit_limit',
|
||||||
|
exportUrl: '/blade-transport/temporary-credit-limit/export-temporary-credit-limit',
|
||||||
|
exportName: '临时额度申请',
|
||||||
|
enableAllDept: false,
|
||||||
|
enableProjectSelect: true,
|
||||||
|
enableAttachmentTable: true,
|
||||||
|
enableDraftSave: true,
|
||||||
|
saveAsDraft: true,
|
||||||
|
defaultForm: {
|
||||||
|
usedFundLimit: 0,
|
||||||
|
remainingFundLimit: 0,
|
||||||
|
},
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
statusTextProp: 'approvalStatusName',
|
||||||
|
deleteStatus: ['draft', 'withdrawn', 'rejected', '草稿'],
|
||||||
|
editStatus: ['draft', 'withdrawn', 'rejected', '草稿', '已撤回'],
|
||||||
|
ignoreReadonlyEditStatus: ['draft', 'withdrawn', '草稿', '已撤回'],
|
||||||
|
ignoreReadonlyDeleteStatus: ['draft', '草稿'],
|
||||||
|
operations: [
|
||||||
|
{
|
||||||
|
action: 'submitApproval',
|
||||||
|
label: '提交',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['draft', 'withdrawn', 'rejected'],
|
||||||
|
permission: 'temporary_credit_limit_submit',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'flow',
|
||||||
|
label: '流程',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing'],
|
||||||
|
permission: 'temporary_credit_limit_view',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'withdraw',
|
||||||
|
label: '撤回',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing'],
|
||||||
|
permission: 'temporary_credit_limit_withdraw',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'approve',
|
||||||
|
label: '审批通过',
|
||||||
|
type: 'success',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing'],
|
||||||
|
permission: 'temporary_credit_limit_approve',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: 'reject',
|
||||||
|
label: '审批驳回',
|
||||||
|
type: 'warning',
|
||||||
|
statusProp: 'approvalStatus',
|
||||||
|
status: ['reviewing'],
|
||||||
|
permission: 'temporary_credit_limit_reject',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = {
|
||||||
|
...createCrudOption([
|
||||||
|
{
|
||||||
|
label: '申请单号',
|
||||||
|
prop: 'applicationNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 5,
|
||||||
|
minWidth: 160,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目名称',
|
||||||
|
prop: 'projectName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
searchType: 'select',
|
||||||
|
formslot: true,
|
||||||
|
dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
|
||||||
|
dicFormatter: listDicFormatter,
|
||||||
|
props: {
|
||||||
|
label: 'projectName',
|
||||||
|
value: 'projectName',
|
||||||
|
},
|
||||||
|
filterable: true,
|
||||||
|
minWidth: 180,
|
||||||
|
rules: textRule('项目名称', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目ID',
|
||||||
|
prop: 'projectId',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目编号',
|
||||||
|
prop: 'projectCode',
|
||||||
|
hide: true,
|
||||||
|
disabled: true,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('项目编号', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '承办部门',
|
||||||
|
prop: 'undertakeDeptName',
|
||||||
|
hide: true,
|
||||||
|
disabled: true,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('承办部门', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目资金使用额度(万元)',
|
||||||
|
prop: 'projectFundLimit',
|
||||||
|
hide: true,
|
||||||
|
disabled: true,
|
||||||
|
minWidth: 200,
|
||||||
|
rules: [nonNegativeRule('项目资金使用额度')],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '已使用项目资金使用额度(万元)',
|
||||||
|
prop: 'usedFundLimit',
|
||||||
|
hide: true,
|
||||||
|
disabled: true,
|
||||||
|
minWidth: 220,
|
||||||
|
value: 0,
|
||||||
|
rules: [nonNegativeRule('已使用项目资金额度')],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '剩余项目资金使用额度(万元)',
|
||||||
|
prop: 'remainingFundLimit',
|
||||||
|
hide: true,
|
||||||
|
disabled: true,
|
||||||
|
minWidth: 230,
|
||||||
|
value: 0,
|
||||||
|
rules: [nonNegativeRule('剩余项目资金使用额度')],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '申请临时额度(万元)',
|
||||||
|
prop: 'applyLimit',
|
||||||
|
formslot: true,
|
||||||
|
minWidth: 180,
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请输入申请临时额度', trigger: 'blur' },
|
||||||
|
nonNegativeRule('申请临时额度'),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '申请有效期至',
|
||||||
|
prop: 'validUntil',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
minWidth: 140,
|
||||||
|
rules: [{ required: true, message: '请选择申请有效期至', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '申请部门',
|
||||||
|
prop: 'applyDeptName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
searchType: 'select',
|
||||||
|
dicUrl: '/blade-system/dept/select',
|
||||||
|
props: {
|
||||||
|
label: 'deptName',
|
||||||
|
value: 'deptName',
|
||||||
|
},
|
||||||
|
filterable: true,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '申请人',
|
||||||
|
prop: 'applicantName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
searchType: 'select',
|
||||||
|
dicUrl: '/blade-system/user/user-list',
|
||||||
|
dicFormatter: userDicFormatter,
|
||||||
|
props: {
|
||||||
|
label: 'realName',
|
||||||
|
value: 'realName',
|
||||||
|
},
|
||||||
|
filterable: true,
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '审批状态',
|
||||||
|
searchLabel: '状态',
|
||||||
|
prop: 'approvalStatus',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
slot: true,
|
||||||
|
dicData: approvalStatusOptions,
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
fixed: 'right',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '当前节点',
|
||||||
|
prop: 'currentNode',
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '当前处理人',
|
||||||
|
prop: 'currentProcessor',
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
maxlength: 200,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: textRule('备注', 200),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '附件',
|
||||||
|
prop: 'attachmentsJson',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
...auditColumns.map(column => ({ ...column, hide: true })),
|
||||||
|
]),
|
||||||
|
dialogWidth: 1480,
|
||||||
|
index: false,
|
||||||
|
};
|
||||||
549
src/option/business/transport-plan.js
Normal file
@@ -0,0 +1,549 @@
|
|||||||
|
import {
|
||||||
|
auditColumns,
|
||||||
|
createCrudOption,
|
||||||
|
dataSourceOptions,
|
||||||
|
phoneRule,
|
||||||
|
planStatusOptions,
|
||||||
|
selectRule,
|
||||||
|
textRule,
|
||||||
|
} from './common';
|
||||||
|
|
||||||
|
const listDicFormatter = res => {
|
||||||
|
const data = res?.data || res;
|
||||||
|
if (Array.isArray(data)) return data;
|
||||||
|
if (Array.isArray(data?.records)) return data.records;
|
||||||
|
if (Array.isArray(data?.data)) return data.data;
|
||||||
|
if (Array.isArray(data?.data?.records)) return data.data.records;
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const parseGoodsRows = value => {
|
||||||
|
if (!value) return [];
|
||||||
|
if (Array.isArray(value)) return value;
|
||||||
|
if (typeof value === 'object') return [value];
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(value);
|
||||||
|
return Array.isArray(data) ? data : [data];
|
||||||
|
} catch (error) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatGoodsField = (row, propList) => {
|
||||||
|
const values = propList.map(prop => row[prop]).filter(Boolean);
|
||||||
|
if (values.length) return values.join('、');
|
||||||
|
return parseGoodsRows(row.goodsJson)
|
||||||
|
.map(item => propList.map(prop => item?.[prop]).find(Boolean))
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('、');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getGoodsQuantity = item => {
|
||||||
|
const value = item?.quantity ?? item?.cargoQuantity ?? item?.goodsQuantity ?? 0;
|
||||||
|
const number = Number(String(value).replace(/,/g, ''));
|
||||||
|
return Number.isFinite(number) ? number : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatGoodsQuantity = value => {
|
||||||
|
const number = Math.round((value + Number.EPSILON) * 1000) / 1000;
|
||||||
|
return Number.isInteger(number) ? String(number) : String(number).replace(/\.?0+$/, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSecondCargoTypeName = item =>
|
||||||
|
item?.cargoType ||
|
||||||
|
item?.secondCargoTypeName ||
|
||||||
|
item?.secondCargoType ||
|
||||||
|
item?.goodsType ||
|
||||||
|
item?.type ||
|
||||||
|
item?.cargoTypeName ||
|
||||||
|
item?.firstCargoTypeName ||
|
||||||
|
'货物';
|
||||||
|
|
||||||
|
const formatGoodsInfo = row => {
|
||||||
|
const rows = parseGoodsRows(row.goodsJson);
|
||||||
|
if (!rows.length) return row.goodsInfo || '';
|
||||||
|
|
||||||
|
const groups = rows.reduce((result, item = {}) => {
|
||||||
|
const hasGoodsInfo = [
|
||||||
|
item.cargoName,
|
||||||
|
item.goodsName,
|
||||||
|
item.name,
|
||||||
|
item.cargoType,
|
||||||
|
item.secondCargoTypeName,
|
||||||
|
item.goodsType,
|
||||||
|
item.type,
|
||||||
|
item.quantity,
|
||||||
|
item.cargoQuantity,
|
||||||
|
item.goodsQuantity,
|
||||||
|
item.quantityUnit,
|
||||||
|
item.goodsQuantityUnit,
|
||||||
|
item.unit,
|
||||||
|
].some(Boolean);
|
||||||
|
if (!hasGoodsInfo) return result;
|
||||||
|
|
||||||
|
const unit = item.quantityUnit || item.goodsQuantityUnit || item.unit || '';
|
||||||
|
if (!result[unit]) {
|
||||||
|
result[unit] = {
|
||||||
|
typeName: getSecondCargoTypeName(item),
|
||||||
|
count: 0,
|
||||||
|
quantity: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
result[unit].count += 1;
|
||||||
|
result[unit].quantity += getGoodsQuantity(item);
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const text = Object.entries(groups)
|
||||||
|
.map(([unit, group]) => {
|
||||||
|
const quantity = `${formatGoodsQuantity(group.quantity)}${unit}`;
|
||||||
|
return `${group.typeName}等${group.count}中货物 | ${quantity}`;
|
||||||
|
})
|
||||||
|
.join('; ');
|
||||||
|
|
||||||
|
return text || row.goodsInfo || '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDispatchProgress = row =>
|
||||||
|
row.dispatchProgressName || row.dispatchProgress || row.progress || '';
|
||||||
|
|
||||||
|
const auditColumn = prop => ({ ...auditColumns.find(item => item.prop === prop) });
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '运输计划',
|
||||||
|
permission: 'transport_plan',
|
||||||
|
exportUrl: '/blade-transport/transport-plan/export-transport-plan',
|
||||||
|
exportName: '运输计划',
|
||||||
|
enableAllDept: false,
|
||||||
|
enableProjectSelect: true,
|
||||||
|
templateCreateTarget: 'transport-plan',
|
||||||
|
enableAttachmentTable: true,
|
||||||
|
enableTransportPlanForm: true,
|
||||||
|
enableTransportPlanCreateActions: true,
|
||||||
|
enableTransportPlanImport: true,
|
||||||
|
transportPlanImportTitle: '导入发货计划',
|
||||||
|
transportPlanTemplateUrl: '/blade-transport/transport-plan/export-template',
|
||||||
|
attachmentTitle: '附件',
|
||||||
|
searchRangeMap: {
|
||||||
|
planStartDateRange: ['planStartDateStart', 'planStartDateEnd'],
|
||||||
|
planEndDateRange: ['planEndDateStart', 'planEndDateEnd'],
|
||||||
|
},
|
||||||
|
actions: ['copy', 'cancel', 'complete'],
|
||||||
|
statusProp: 'businessStatus',
|
||||||
|
statusTextProp: 'businessStatusName',
|
||||||
|
deleteStatus: ['draft'],
|
||||||
|
editStatus: ['draft', 'waiting_dispatch'],
|
||||||
|
detailButton: true,
|
||||||
|
detailSections: [
|
||||||
|
{
|
||||||
|
title: '基本信息',
|
||||||
|
fields: [
|
||||||
|
['planNo', '计划单号'],
|
||||||
|
['planName', '计划名称'],
|
||||||
|
['projectName', '项目名称'],
|
||||||
|
['customerName', '客户名称'],
|
||||||
|
['transportType', '运输方式'],
|
||||||
|
['businessStatus', '调度状态'],
|
||||||
|
['planStartDate', '计划开始日期'],
|
||||||
|
['planEndDate', '计划结束日期'],
|
||||||
|
['dataSource', '数据来源'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '收发货信息',
|
||||||
|
fields: [
|
||||||
|
['departureName', '发货地'],
|
||||||
|
['departureAddress', '发货地址', 2],
|
||||||
|
['departureContact', '发货联系人'],
|
||||||
|
['departurePhone', '发货联系方式'],
|
||||||
|
['arrivalName', '收货地'],
|
||||||
|
['arrivalAddress', '到货地址', 2],
|
||||||
|
['arrivalContact', '收货联系人'],
|
||||||
|
['arrivalPhone', '收货联系方式'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '其它信息',
|
||||||
|
fields: [
|
||||||
|
['remark', '备注', 2],
|
||||||
|
['updateUserName', '更新人'],
|
||||||
|
['updateTime', '更新时间'],
|
||||||
|
['createTime', '创建时间'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
operations: [
|
||||||
|
{
|
||||||
|
action: 'dispatch',
|
||||||
|
label: '调度',
|
||||||
|
statusProp: 'businessStatus',
|
||||||
|
status: ['waiting_dispatch'],
|
||||||
|
permission: 'transport_plan_edit',
|
||||||
|
confirm: '确定调度该运输计划?',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = {
|
||||||
|
...createCrudOption([
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'basicInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 400,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '计划单号',
|
||||||
|
prop: 'planNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 13,
|
||||||
|
span: 6,
|
||||||
|
order: 370,
|
||||||
|
minWidth: 150,
|
||||||
|
disabled: true,
|
||||||
|
placeholder: '系统自动生成',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '计划名称',
|
||||||
|
prop: 'planName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 12,
|
||||||
|
span: 6,
|
||||||
|
order: 380,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('计划名称', 50, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运输方式',
|
||||||
|
prop: 'transportType',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 10,
|
||||||
|
span: 6,
|
||||||
|
order: 360,
|
||||||
|
dicUrl: '/blade-system/dict-biz/dictionary?code=transport_type',
|
||||||
|
props: {
|
||||||
|
label: 'dictValue',
|
||||||
|
value: 'dictKey',
|
||||||
|
},
|
||||||
|
minWidth: 130,
|
||||||
|
rules: selectRule('运输类型'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物信息',
|
||||||
|
prop: 'goodsInfo',
|
||||||
|
formatter: row => formatGoodsInfo(row),
|
||||||
|
minWidth: 320,
|
||||||
|
className: 'business-crud-page__goods-info-cell',
|
||||||
|
overHidden: false,
|
||||||
|
showOverflowTooltip: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '调度进度',
|
||||||
|
prop: 'dispatchProgress',
|
||||||
|
formatter: row => formatDispatchProgress(row),
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货地址',
|
||||||
|
prop: 'departureAddress',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 7,
|
||||||
|
span: 24,
|
||||||
|
order: 310,
|
||||||
|
minWidth: 220,
|
||||||
|
rules: textRule('发货地址', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '到货地址',
|
||||||
|
prop: 'arrivalAddress',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 6,
|
||||||
|
span: 24,
|
||||||
|
order: 300,
|
||||||
|
minWidth: 220,
|
||||||
|
rules: textRule('收货地址', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目名称',
|
||||||
|
prop: 'projectName',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 11,
|
||||||
|
searchType: 'select',
|
||||||
|
span: 6,
|
||||||
|
order: 400,
|
||||||
|
dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
|
||||||
|
dicFormatter: listDicFormatter,
|
||||||
|
props: {
|
||||||
|
label: 'projectName',
|
||||||
|
value: 'projectName',
|
||||||
|
},
|
||||||
|
filterable: true,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('项目', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '客户名称',
|
||||||
|
prop: 'customerName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 5,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '计划开始日期',
|
||||||
|
prop: 'planStartDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
span: 6,
|
||||||
|
order: 350,
|
||||||
|
minWidth: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '计划结束日期',
|
||||||
|
prop: 'planEndDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
span: 6,
|
||||||
|
order: 340,
|
||||||
|
minWidth: 130,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '数据来源',
|
||||||
|
prop: 'dataSource',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
dicData: dataSourceOptions,
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物类型',
|
||||||
|
prop: 'cargoType',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 8,
|
||||||
|
formatter: row => formatGoodsField(row, ['cargoType', 'goodsType']),
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物名称',
|
||||||
|
prop: 'cargoName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 9,
|
||||||
|
formatter: row => formatGoodsField(row, ['cargoName', 'goodsName']),
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
order: 330,
|
||||||
|
minWidth: 180,
|
||||||
|
maxlength: 200,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: textRule('备注', 200),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...auditColumn('updateUserName'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...auditColumn('createTime'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...auditColumn('updateTime'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '调度状态',
|
||||||
|
prop: 'businessStatus',
|
||||||
|
type: 'select',
|
||||||
|
slot: true,
|
||||||
|
search: true,
|
||||||
|
searchLabel: '状态',
|
||||||
|
searchOrder: 2,
|
||||||
|
dicData: planStatusOptions,
|
||||||
|
minWidth: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'shippingInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 320,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目ID',
|
||||||
|
prop: 'projectId',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '客户合同',
|
||||||
|
prop: 'contractName',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
span: 6,
|
||||||
|
order: 390,
|
||||||
|
minWidth: 160,
|
||||||
|
rules: textRule('客户合同', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '客户合同ID',
|
||||||
|
prop: 'contractId',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货地',
|
||||||
|
prop: 'departureName',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
minWidth: 140,
|
||||||
|
rules: textRule('发货地', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货地',
|
||||||
|
prop: 'arrivalName',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
minWidth: 140,
|
||||||
|
rules: textRule('收货地', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货联系人',
|
||||||
|
prop: 'departureContact',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
rules: textRule('发货联系人', 50),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货联系方式',
|
||||||
|
prop: 'departurePhone',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
rules: [phoneRule('发货联系方式'), ...textRule('发货联系方式', 50)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货联系人',
|
||||||
|
prop: 'arrivalContact',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
rules: textRule('收货联系人', 50),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货联系方式',
|
||||||
|
prop: 'arrivalPhone',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
rules: [phoneRule('收货联系方式'), ...textRule('收货联系方式', 50)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'goodsInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 280,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '计划开始日期',
|
||||||
|
prop: 'planStartDateRange',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
search: true,
|
||||||
|
searchRange: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
hide: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '计划结束日期',
|
||||||
|
prop: 'planEndDateRange',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
search: true,
|
||||||
|
searchRange: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
hide: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '所属组织',
|
||||||
|
prop: 'deptName',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'goodsJson',
|
||||||
|
type: 'textarea',
|
||||||
|
formslot: true,
|
||||||
|
minRows: 5,
|
||||||
|
span: 24,
|
||||||
|
order: 270,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: '0px',
|
||||||
|
className: 'business-crud-page__full-form-item',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'attachmentTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 265,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'attachmentsJson',
|
||||||
|
type: 'textarea',
|
||||||
|
formslot: true,
|
||||||
|
minRows: 3,
|
||||||
|
span: 24,
|
||||||
|
order: 260,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: '0px',
|
||||||
|
className: 'business-crud-page__full-form-item',
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
dialogWidth: '96%',
|
||||||
|
};
|
||||||
722
src/option/business/waybill-manage.js
Normal file
@@ -0,0 +1,722 @@
|
|||||||
|
import {
|
||||||
|
auditColumns,
|
||||||
|
createCrudOption,
|
||||||
|
dataSourceOptions,
|
||||||
|
phoneRule,
|
||||||
|
selectRule,
|
||||||
|
textRule,
|
||||||
|
waybillStatusOptions,
|
||||||
|
} from './common';
|
||||||
|
|
||||||
|
const transportTypeDict = {
|
||||||
|
dicUrl: '/blade-system/dict-biz/dictionary?code=transport_type',
|
||||||
|
props: {
|
||||||
|
label: 'dictValue',
|
||||||
|
value: 'dictKey',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEmpty = value => value === undefined || value === null || value === '';
|
||||||
|
|
||||||
|
const parseJsonArray = value => {
|
||||||
|
if (Array.isArray(value)) return value;
|
||||||
|
if (typeof value !== 'string' || !value.trim()) return [];
|
||||||
|
try {
|
||||||
|
const result = JSON.parse(value);
|
||||||
|
if (Array.isArray(result)) return result;
|
||||||
|
if (Array.isArray(result.records)) return result.records;
|
||||||
|
if (Array.isArray(result.rows)) return result.rows;
|
||||||
|
return [];
|
||||||
|
} catch (error) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFirstValue = (row, props) => {
|
||||||
|
const prop = props.find(item => !isEmpty(row[item]));
|
||||||
|
return prop ? row[prop] : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getGoodsRows = row => parseJsonArray(row.goodsList || row.goodsRows || row.goodsJson);
|
||||||
|
|
||||||
|
const getBillingRows = row => {
|
||||||
|
const freightRows = parseJsonArray(row.freightList || row.freightRows || row.freightJson);
|
||||||
|
if (freightRows.length) return freightRows;
|
||||||
|
return parseJsonArray(row.billingPlanJson).flatMap(item =>
|
||||||
|
Array.isArray(item.rules) ? item.rules : []
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const joinText = list => list.filter(item => !isEmpty(item)).join('/');
|
||||||
|
|
||||||
|
const formatGoodsInfo = row => {
|
||||||
|
const text = getFirstValue(row, ['goodsInfo', 'cargoInfo']);
|
||||||
|
if (text) return text;
|
||||||
|
return getGoodsRows(row)
|
||||||
|
.map(item => {
|
||||||
|
const name = getFirstValue(item, ['cargoName', 'goodsName', 'name']);
|
||||||
|
const type = getFirstValue(item, ['cargoType', 'goodsType', 'typeName']);
|
||||||
|
const quantity = joinText([
|
||||||
|
getFirstValue(item, ['quantity', 'cargoQuantity', 'goodsQuantity']),
|
||||||
|
getFirstValue(item, ['quantityUnit', 'cargoUnit', 'unit']),
|
||||||
|
]);
|
||||||
|
return joinText([name, type, quantity]);
|
||||||
|
})
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('; ');
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatGoodsField = (row, props) => {
|
||||||
|
const value = getFirstValue(row, props);
|
||||||
|
if (value) return value;
|
||||||
|
const goods = getGoodsRows(row).find(item => getFirstValue(item, props));
|
||||||
|
return goods ? getFirstValue(goods, props) : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatTransportMode = row =>
|
||||||
|
getFirstValue(row, ['transportModeName', 'transportMode', 'transportWayName', 'transportWay']);
|
||||||
|
|
||||||
|
const formatUnitPrice = row => {
|
||||||
|
const value = getFirstValue(row, ['unitPrice', 'price']);
|
||||||
|
const unit = getFirstValue(row, ['priceUnit', 'billingUnit', 'unit']);
|
||||||
|
if (!isEmpty(value)) return unit ? `${value}(${unit})` : value;
|
||||||
|
const billing = getBillingRows(row).find(item => !isEmpty(item.unitPrice));
|
||||||
|
if (!billing) return '';
|
||||||
|
const billingUnit = getFirstValue(billing, ['priceUnit', 'billingUnit', 'unit']);
|
||||||
|
return billingUnit ? `${billing.unitPrice}(${billingUnit})` : billing.unitPrice;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatAmount = (row, props) => getFirstValue(row, props);
|
||||||
|
|
||||||
|
const auditColumn = prop => ({ ...auditColumns.find(item => item.prop === prop) });
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
title: '运单管理',
|
||||||
|
permission: 'waybill_manage',
|
||||||
|
exportUrl: '/blade-transport/waybill-manage/export-waybill-manage',
|
||||||
|
exportName: '运单管理',
|
||||||
|
importUrl: '/blade-transport/waybill-manage/import-waybill-manage',
|
||||||
|
enableAllDept: false,
|
||||||
|
enableProjectSelect: true,
|
||||||
|
templateCreateTarget: 'waybill-manage',
|
||||||
|
enableContractSelect: true,
|
||||||
|
enableShippingPlanSelect: true,
|
||||||
|
enableShippingInfoForm: true,
|
||||||
|
enableTaskInfoForm: true,
|
||||||
|
batchDelete: false,
|
||||||
|
actionButtonLikeSearch: true,
|
||||||
|
createText: '新建运单',
|
||||||
|
importText: '导入运单',
|
||||||
|
enableWaybillImport: true,
|
||||||
|
roadLoading: true,
|
||||||
|
roadLoadingText: '公路配载',
|
||||||
|
searchRangeMap: {
|
||||||
|
startDateRange: ['startDateStart', 'startDateEnd'],
|
||||||
|
endDateRange: ['endDateStart', 'endDateEnd'],
|
||||||
|
createTimeRange: ['createTimeStart', 'createTimeEnd'],
|
||||||
|
},
|
||||||
|
actions: ['copy', 'cancel', 'reassign', 'complete', 'batchComplete'],
|
||||||
|
statusProp: 'businessStatus',
|
||||||
|
statusTextProp: 'businessStatusName',
|
||||||
|
deleteStatus: ['draft'],
|
||||||
|
editStatus: ['draft', 'pending'],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const option = {
|
||||||
|
...createCrudOption([
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'basicInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 900,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运单号',
|
||||||
|
prop: 'waybillNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 23,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配载单号',
|
||||||
|
prop: 'loadingNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 5,
|
||||||
|
span: 6,
|
||||||
|
order: 840,
|
||||||
|
minWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '总单号',
|
||||||
|
prop: 'masterNo',
|
||||||
|
search: true,
|
||||||
|
searchLabel: '多联总单',
|
||||||
|
searchOrder: 6,
|
||||||
|
span: 6,
|
||||||
|
order: 830,
|
||||||
|
minWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目',
|
||||||
|
prop: 'projectName',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 22,
|
||||||
|
span: 6,
|
||||||
|
order: 890,
|
||||||
|
minWidth: 150,
|
||||||
|
rules: textRule('项目', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '客户',
|
||||||
|
prop: 'customerName',
|
||||||
|
search: true,
|
||||||
|
searchLabel: '客户名称',
|
||||||
|
searchOrder: 21,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '车牌号/航班号/船号/班列号',
|
||||||
|
prop: 'vehicleNo',
|
||||||
|
search: true,
|
||||||
|
searchLabel: '车/船/航班/班列',
|
||||||
|
searchOrder: 13,
|
||||||
|
minWidth: 210,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '司机',
|
||||||
|
prop: 'driverName',
|
||||||
|
search: true,
|
||||||
|
searchLabel: '司机名称',
|
||||||
|
searchOrder: 14,
|
||||||
|
minWidth: 120,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '联系方式',
|
||||||
|
prop: 'driverPhone',
|
||||||
|
formatter: row => getFirstValue(row, ['driverPhone', 'driverMobile', 'driverTel']),
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运输方式',
|
||||||
|
prop: 'transportMode',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
formatter: row => formatTransportMode(row),
|
||||||
|
...transportTypeDict,
|
||||||
|
minWidth: 130,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运输类型',
|
||||||
|
prop: 'transportType',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 20,
|
||||||
|
span: 6,
|
||||||
|
order: 850,
|
||||||
|
...transportTypeDict,
|
||||||
|
minWidth: 130,
|
||||||
|
rules: selectRule('运输类型'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '过程节点',
|
||||||
|
prop: 'currentProcessNode',
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '承运类型',
|
||||||
|
prop: 'carrierType',
|
||||||
|
formatter: row => getFirstValue(row, ['carrierTypeName', 'carrierType']),
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '承运商',
|
||||||
|
prop: 'carrierName',
|
||||||
|
search: true,
|
||||||
|
searchLabel: '承运商名称',
|
||||||
|
searchOrder: 15,
|
||||||
|
minWidth: 150,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物信息',
|
||||||
|
prop: 'goodsInfo',
|
||||||
|
formatter: row => formatGoodsInfo(row),
|
||||||
|
minWidth: 260,
|
||||||
|
overHidden: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货地址',
|
||||||
|
prop: 'departureAddress',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 17,
|
||||||
|
span: 24,
|
||||||
|
order: 790,
|
||||||
|
minWidth: 220,
|
||||||
|
rules: textRule('发货地址', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '到货地址',
|
||||||
|
prop: 'arrivalAddress',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchLabel: '收货地址',
|
||||||
|
searchOrder: 16,
|
||||||
|
span: 24,
|
||||||
|
order: 780,
|
||||||
|
minWidth: 220,
|
||||||
|
rules: textRule('收货地址', 255, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货联系人',
|
||||||
|
prop: 'departureContact',
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货联系人',
|
||||||
|
prop: 'arrivalContact',
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '单价(计价单位)',
|
||||||
|
prop: 'unitPrice',
|
||||||
|
formatter: row => formatUnitPrice(row),
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运费',
|
||||||
|
prop: 'freight',
|
||||||
|
formatter: row => formatAmount(row, ['freight', 'freightAmount', 'transportFee']),
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '其他费用合计',
|
||||||
|
prop: 'otherFeeTotal',
|
||||||
|
formatter: row => formatAmount(row, ['otherFeeTotal', 'otherAmount', 'otherFeeAmount']),
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运费合计',
|
||||||
|
prop: 'freightTotal',
|
||||||
|
formatter: row => formatAmount(row, ['freightTotal', 'totalFreight', 'totalAmount']),
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '客户合同',
|
||||||
|
prop: 'contractName',
|
||||||
|
formslot: true,
|
||||||
|
span: 6,
|
||||||
|
order: 880,
|
||||||
|
minWidth: 160,
|
||||||
|
rules: textRule('客户合同', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货计划',
|
||||||
|
prop: 'planName',
|
||||||
|
formslot: true,
|
||||||
|
search: true,
|
||||||
|
searchOrder: 7,
|
||||||
|
span: 6,
|
||||||
|
order: 870,
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物类型',
|
||||||
|
prop: 'cargoType',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 18,
|
||||||
|
formatter: row => formatGoodsField(row, ['cargoType', 'goodsType', 'typeName']),
|
||||||
|
minWidth: 130,
|
||||||
|
display: false,
|
||||||
|
rules: textRule('货物类型', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物名称',
|
||||||
|
prop: 'cargoName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 19,
|
||||||
|
formatter: row => formatGoodsField(row, ['cargoName', 'goodsName', 'name']),
|
||||||
|
minWidth: 150,
|
||||||
|
display: false,
|
||||||
|
rules: textRule('货物名称', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '实际发货时间',
|
||||||
|
prop: 'startDate',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
minWidth: 170,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '实际完成时间',
|
||||||
|
prop: 'endDate',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
minWidth: 170,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '原始单号',
|
||||||
|
prop: 'originalNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 12,
|
||||||
|
span: 6,
|
||||||
|
order: 860,
|
||||||
|
minWidth: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运单批次号',
|
||||||
|
prop: 'batchNo',
|
||||||
|
search: true,
|
||||||
|
searchLabel: '运输批次',
|
||||||
|
searchOrder: 3,
|
||||||
|
minWidth: 140,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '预计发货日期',
|
||||||
|
prop: 'estimatedStartTime',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
formatter: row => getFirstValue(row, ['estimatedStartTime', 'planStartDate']),
|
||||||
|
minWidth: 170,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '预计完成日期',
|
||||||
|
prop: 'estimatedEndTime',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
formatter: row => getFirstValue(row, ['estimatedEndTime', 'planEndDate']),
|
||||||
|
minWidth: 170,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
order: 810,
|
||||||
|
minWidth: 180,
|
||||||
|
overHidden: true,
|
||||||
|
maxlength: 200,
|
||||||
|
showWordLimit: true,
|
||||||
|
rules: textRule('备注', 200),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '数据来源',
|
||||||
|
prop: 'dataSource',
|
||||||
|
type: 'select',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 10,
|
||||||
|
dicData: dataSourceOptions,
|
||||||
|
minWidth: 120,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...auditColumn('createTime'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...auditColumn('updateTime'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '状态',
|
||||||
|
prop: 'businessStatus',
|
||||||
|
type: 'select',
|
||||||
|
slot: true,
|
||||||
|
search: true,
|
||||||
|
searchLabel: '状态',
|
||||||
|
searchOrder: 11,
|
||||||
|
dicData: waybillStatusOptions,
|
||||||
|
minWidth: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'shippingInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 800,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'taskInfoTitle',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 770,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'taskInfoForm',
|
||||||
|
formslot: true,
|
||||||
|
span: 24,
|
||||||
|
order: 760,
|
||||||
|
hide: true,
|
||||||
|
labelWidth: '0px',
|
||||||
|
className: 'business-crud-page__full-form-item',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '实际发货时间',
|
||||||
|
prop: 'startDateRange',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
search: true,
|
||||||
|
searchRange: true,
|
||||||
|
searchOrder: 9,
|
||||||
|
hide: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '实际完成时间',
|
||||||
|
prop: 'endDateRange',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
search: true,
|
||||||
|
searchRange: true,
|
||||||
|
searchOrder: 8,
|
||||||
|
hide: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '创建时间',
|
||||||
|
prop: 'createTimeRange',
|
||||||
|
type: 'datetime',
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
search: true,
|
||||||
|
searchRange: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
hide: true,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '关联单号',
|
||||||
|
prop: 'relationNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
span: 6,
|
||||||
|
order: 820,
|
||||||
|
minWidth: 140,
|
||||||
|
hide: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '货物信息',
|
||||||
|
prop: 'goodsJson',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 5,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '承运信息',
|
||||||
|
prop: 'carrierJson',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '过程配置',
|
||||||
|
prop: 'processJson',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '运费信息',
|
||||||
|
prop: 'freightJson',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 4,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '附件',
|
||||||
|
prop: 'attachmentsJson',
|
||||||
|
type: 'textarea',
|
||||||
|
minRows: 3,
|
||||||
|
span: 24,
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
viewDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '所属组织',
|
||||||
|
prop: 'deptName',
|
||||||
|
hide: true,
|
||||||
|
minWidth: 150,
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货地',
|
||||||
|
prop: 'departureName',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
minWidth: 140,
|
||||||
|
rules: textRule('发货地', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货地',
|
||||||
|
prop: 'arrivalName',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
minWidth: 140,
|
||||||
|
rules: textRule('收货地', 100, true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货联系方式',
|
||||||
|
prop: 'departurePhone',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
rules: [phoneRule('发货联系方式'), ...textRule('发货联系方式', 50)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '收货联系方式',
|
||||||
|
prop: 'arrivalPhone',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
rules: [phoneRule('收货联系方式'), ...textRule('收货联系方式', 50)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '项目ID',
|
||||||
|
prop: 'projectId',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '客户合同ID',
|
||||||
|
prop: 'contractId',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货计划ID',
|
||||||
|
prop: 'planId',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '任务录入模式',
|
||||||
|
prop: 'taskEntryMode',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
value: 'simple',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '任务备注',
|
||||||
|
prop: 'taskRemark',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '任务信息',
|
||||||
|
prop: 'taskInfoJson',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
dialogWidth: '96%',
|
||||||
|
dialogTop: '10px',
|
||||||
|
menuWidth: 320,
|
||||||
|
};
|
||||||
@@ -120,14 +120,17 @@ export default {
|
|||||||
calcHeight: 30,
|
calcHeight: 30,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
grid: true,
|
grid: true,
|
||||||
labelWidth: 180,
|
labelWidth: 'auto',
|
||||||
menuWidth: 350,
|
menuWidth: 160,
|
||||||
dialogWidth: 1200,
|
dialogWidth: 1200,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
tabs: true,
|
tabs: true,
|
||||||
|
|||||||
@@ -3,14 +3,17 @@ export default {
|
|||||||
calcHeight: 30,
|
calcHeight: 30,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
grid: true,
|
grid: true,
|
||||||
labelWidth: 100,
|
labelWidth: 'auto',
|
||||||
menuWidth: 350,
|
menuWidth: 160,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ export const LOCK_STATUS_DIC = [
|
|||||||
export const authLockOption = {
|
export const authLockOption = {
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
addBtn: false,
|
addBtn: false,
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ export const GRANT_TYPE_DIC = [
|
|||||||
export const authLogOption = {
|
export const authLogOption = {
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
addBtn: false,
|
addBtn: false,
|
||||||
@@ -18,7 +21,7 @@ export const authLogOption = {
|
|||||||
editBtn: false,
|
editBtn: false,
|
||||||
delBtn: false,
|
delBtn: false,
|
||||||
menu: true,
|
menu: true,
|
||||||
menuWidth: 100,
|
menuWidth: 160,
|
||||||
dialogType: 'drawer',
|
dialogType: 'drawer',
|
||||||
dialogWidth: 800,
|
dialogWidth: 800,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ export const optionParent = {
|
|||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 10,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
menuWidth: 250,
|
menuWidth: 160,
|
||||||
dialogWidth: 880,
|
dialogWidth: 880,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
@@ -92,21 +95,24 @@ export const optionChild = {
|
|||||||
calcHeight: 95,
|
calcHeight: 95,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 10,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
tree: true,
|
tree: true,
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
menuWidth: 300,
|
menuWidth: 160,
|
||||||
dialogWidth: 880,
|
dialogWidth: 880,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '字典编号',
|
label: '字典编号',
|
||||||
prop: 'code',
|
prop: 'code',
|
||||||
addDisabled: true,
|
addDisplay: false,
|
||||||
editDisabled: true,
|
editDisplay: false,
|
||||||
search: true,
|
search: true,
|
||||||
span: 24,
|
span: 24,
|
||||||
rules: [
|
rules: [
|
||||||
|
|||||||
@@ -3,12 +3,15 @@ export const optionParent = {
|
|||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 10,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
menuWidth: 250,
|
menuWidth: 160,
|
||||||
dialogWidth: 880,
|
dialogWidth: 880,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
@@ -93,21 +96,24 @@ export const optionChild = {
|
|||||||
calcHeight: 95,
|
calcHeight: 95,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 10,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
tree: true,
|
tree: true,
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
menuWidth: 300,
|
menuWidth: 160,
|
||||||
dialogWidth: 880,
|
dialogWidth: 880,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '字典编号',
|
label: '字典编号',
|
||||||
prop: 'code',
|
prop: 'code',
|
||||||
addDisabled: true,
|
addDisplay: false,
|
||||||
editDisabled: true,
|
editDisplay: false,
|
||||||
search: true,
|
search: true,
|
||||||
span: 24,
|
span: 24,
|
||||||
rules: [
|
rules: [
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ export const userOption = safe => {
|
|||||||
calcHeight: 150,
|
calcHeight: 150,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
@@ -353,13 +356,16 @@ export const userOption = safe => {
|
|||||||
export const platformOption = {
|
export const platformOption = {
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 120,
|
menuWidth: 160,
|
||||||
editBtnText: '配置',
|
editBtnText: '配置',
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
@@ -475,7 +481,7 @@ export const excelOption = {
|
|||||||
export const platformFormOption = {
|
export const platformFormOption = {
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
labelWidth: 100,
|
labelWidth: 'auto',
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '用户账号',
|
label: '用户账号',
|
||||||
|
|||||||
@@ -6,12 +6,15 @@ export const codeOption = {
|
|||||||
dialogWidth: 900,
|
dialogWidth: 900,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
labelWidth: 120,
|
labelWidth: 'auto',
|
||||||
menuWidth: 350,
|
menuWidth: 160,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
tabs: true,
|
tabs: true,
|
||||||
@@ -376,7 +379,7 @@ export const codeOption = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const genOption = {
|
export const genOption = {
|
||||||
labelWidth: 120,
|
labelWidth: 'auto',
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '上级菜单',
|
label: '上级菜单',
|
||||||
|
|||||||
@@ -3,15 +3,18 @@ export default {
|
|||||||
calcHeight: 50,
|
calcHeight: 50,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
grid: true,
|
grid: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
labelWidth: 120,
|
labelWidth: 'auto',
|
||||||
searchLabelWidth: 100,
|
searchLabelWidth: 160,
|
||||||
menuWidth: 320,
|
menuWidth: 160,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,15 +3,18 @@ export default {
|
|||||||
calcHeight: 50,
|
calcHeight: 50,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 8,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
grid: true,
|
grid: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
labelWidth: 120,
|
labelWidth: 'auto',
|
||||||
searchLabelWidth: 100,
|
searchLabelWidth: 160,
|
||||||
menuWidth: 320,
|
menuWidth: 160,
|
||||||
dialogWidth: 500,
|
dialogWidth: 500,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -3,81 +3,81 @@ export const option = {
|
|||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
indexWidth: 70,
|
||||||
selection: true,
|
selection: true,
|
||||||
addBtn: false,
|
addBtn: false,
|
||||||
editBtn: false,
|
editBtn: false,
|
||||||
delBtn: false,
|
delBtn: false,
|
||||||
viewBtn: false,
|
viewBtn: false,
|
||||||
menuWidth: 180,
|
menuWidth: 220,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '姓名',
|
label: '姓名',
|
||||||
prop: 'driverName',
|
prop: 'driverName',
|
||||||
search: true,
|
search: true,
|
||||||
|
searchOrder: 7,
|
||||||
slot: true,
|
slot: true,
|
||||||
width: 110,
|
minWidth: 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '身份证号',
|
label: '手机号',
|
||||||
prop: 'idCardNo',
|
|
||||||
search: true,
|
|
||||||
width: 190,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '手机号码',
|
|
||||||
prop: 'mobile',
|
prop: 'mobile',
|
||||||
search: true,
|
search: true,
|
||||||
width: 130,
|
searchOrder: 6,
|
||||||
},
|
minWidth: 130,
|
||||||
{
|
|
||||||
label: '性别',
|
|
||||||
prop: 'gender',
|
|
||||||
width: 80,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '司机类型',
|
|
||||||
prop: 'driverType',
|
|
||||||
search: true,
|
|
||||||
type: 'select',
|
|
||||||
dicData: [
|
|
||||||
{
|
|
||||||
label: '自有',
|
|
||||||
value: '自有',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '外协',
|
|
||||||
value: '外协',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
width: 100,
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '岗位',
|
|
||||||
prop: 'posts',
|
|
||||||
width: 150,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '准驾车型',
|
label: '准驾车型',
|
||||||
prop: 'drivingType',
|
prop: 'drivingType',
|
||||||
search: true,
|
search: true,
|
||||||
width: 110,
|
searchOrder: 5,
|
||||||
|
hide: true,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: 'A1',
|
||||||
|
value: 'A1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '所属组织',
|
label: 'A2',
|
||||||
prop: 'organizationName',
|
value: 'A2',
|
||||||
search: true,
|
},
|
||||||
width: 140,
|
{
|
||||||
|
label: 'A3',
|
||||||
|
value: 'A3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'B1',
|
||||||
|
value: 'B1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'B2',
|
||||||
|
value: 'B2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'C1',
|
||||||
|
value: 'C1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'C2',
|
||||||
|
value: 'C2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
minWidth: 110,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: '状态',
|
||||||
prop: 'status',
|
prop: 'status',
|
||||||
search: true,
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
slot: true,
|
slot: true,
|
||||||
dicData: [
|
dicData: [
|
||||||
@@ -93,18 +93,65 @@ export const option = {
|
|||||||
width: 90,
|
width: 90,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '司机类型',
|
||||||
|
prop: 'driverType',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '自有员工',
|
||||||
|
value: '自有',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '外协',
|
||||||
|
value: '外协',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
minWidth: 110,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '身份证号',
|
||||||
|
prop: 'idCardNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
|
minWidth: 190,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '所属组织',
|
||||||
|
prop: 'organizationName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
type: 'select',
|
||||||
|
filterable: true,
|
||||||
|
dicData: [],
|
||||||
|
minWidth: 160,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '性别',
|
||||||
|
prop: 'gender',
|
||||||
|
width: 80,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '岗位',
|
||||||
|
prop: 'posts',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '驾驶认证',
|
label: '驾驶认证',
|
||||||
prop: 'drivingLicenseEndDate',
|
prop: 'drivingLicenseEndDate',
|
||||||
slot: true,
|
slot: true,
|
||||||
width: 130,
|
minWidth: 140,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '从业资格认证',
|
label: '从业资格认证',
|
||||||
prop: 'qualificationEndDate',
|
prop: 'qualificationEndDate',
|
||||||
slot: true,
|
slot: true,
|
||||||
width: 140,
|
minWidth: 150,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ export const option = {
|
|||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
@@ -11,32 +14,52 @@ export const option = {
|
|||||||
editBtn: false,
|
editBtn: false,
|
||||||
delBtn: false,
|
delBtn: false,
|
||||||
viewBtn: false,
|
viewBtn: false,
|
||||||
menuWidth: 210,
|
menuWidth: 160,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
{ label: '船舶名', prop: 'shipName', search: true, slot: true, width: 130 },
|
{ label: '船舶名', prop: 'shipName', search: true, searchOrder: 5, slot: true, width: 130 },
|
||||||
{ label: '船舶识别号', prop: 'shipIdentifierNo', search: true, width: 140 },
|
{
|
||||||
{ label: '所属组织', prop: 'organizationName', search: true, width: 160 },
|
label: '船舶识别号',
|
||||||
{ label: '船检登记号', prop: 'shipInspectionNo', search: true, width: 130 },
|
prop: 'shipIdentifierNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
|
width: 140,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '船检登记号',
|
||||||
|
prop: 'shipInspectionNo',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
|
width: 130,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '船舶类型',
|
label: '船舶类型',
|
||||||
prop: 'shipType',
|
prop: 'shipType',
|
||||||
search: true,
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
dicData: [
|
dicData: [
|
||||||
{ label: '干货船', value: '干货船' },
|
|
||||||
{ label: '集装箱船', value: '集装箱船' },
|
|
||||||
{ label: '散货船', value: '散货船' },
|
{ label: '散货船', value: '散货船' },
|
||||||
|
{ label: '集装箱船', value: '集装箱船' },
|
||||||
|
{ label: '杂货船', value: '杂货船' },
|
||||||
{ label: '油船', value: '油船' },
|
{ label: '油船', value: '油船' },
|
||||||
{ label: '拖轮', value: '拖轮' },
|
|
||||||
],
|
],
|
||||||
width: 110,
|
width: 110,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '所属组织',
|
||||||
|
prop: 'organizationName',
|
||||||
|
search: true,
|
||||||
|
searchOrder: 1,
|
||||||
|
type: 'select',
|
||||||
|
filterable: true,
|
||||||
|
dicData: [],
|
||||||
|
width: 160,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: '状态',
|
||||||
prop: 'status',
|
prop: 'status',
|
||||||
search: true,
|
|
||||||
type: 'select',
|
type: 'select',
|
||||||
slot: true,
|
slot: true,
|
||||||
dicData: [
|
dicData: [
|
||||||
@@ -46,7 +69,13 @@ export const option = {
|
|||||||
width: 90,
|
width: 90,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{ label: '国籍证有效期至', prop: 'nationalityCertEndDate', slot: true, width: 150, align: 'center' },
|
{
|
||||||
|
label: '国籍证有效期至',
|
||||||
|
prop: 'nationalityCertEndDate',
|
||||||
|
slot: true,
|
||||||
|
width: 150,
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '最低安全配员证书有效期至',
|
label: '最低安全配员证书有效期至',
|
||||||
prop: 'safeManningCertEndDate',
|
prop: 'safeManningCertEndDate',
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ export const option = {
|
|||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
@@ -11,13 +14,14 @@ export const option = {
|
|||||||
editBtn: false,
|
editBtn: false,
|
||||||
delBtn: false,
|
delBtn: false,
|
||||||
viewBtn: false,
|
viewBtn: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '车牌号',
|
label: '车牌号',
|
||||||
prop: 'plateNo',
|
prop: 'plateNo',
|
||||||
search: true,
|
search: true,
|
||||||
|
searchOrder: 5,
|
||||||
slot: true,
|
slot: true,
|
||||||
width: 120,
|
width: 120,
|
||||||
},
|
},
|
||||||
@@ -25,46 +29,41 @@ export const option = {
|
|||||||
label: '所属组织',
|
label: '所属组织',
|
||||||
prop: 'organizationName',
|
prop: 'organizationName',
|
||||||
search: true,
|
search: true,
|
||||||
width: 150,
|
searchOrder: 1,
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '车辆类型',
|
|
||||||
prop: 'vehicleType',
|
|
||||||
search: true,
|
|
||||||
type: 'select',
|
type: 'select',
|
||||||
dicData: [
|
filterable: true,
|
||||||
{ label: '厢式', value: '厢式' },
|
dicData: [],
|
||||||
{ label: '高栏', value: '高栏' },
|
width: 150,
|
||||||
{ label: '平板', value: '平板' },
|
|
||||||
{ label: '仓栅', value: '仓栅' },
|
|
||||||
{ label: '牵引车', value: '牵引车' },
|
|
||||||
],
|
|
||||||
width: 110,
|
|
||||||
align: 'center',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '业务关系',
|
label: '业务关系',
|
||||||
prop: 'businessRelation',
|
prop: 'businessRelation',
|
||||||
search: true,
|
search: true,
|
||||||
|
searchOrder: 4,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
dicData: [
|
dicData: [
|
||||||
|
{ label: '全部', value: '' },
|
||||||
{ label: '自有', value: '自有' },
|
{ label: '自有', value: '自有' },
|
||||||
{ label: '业务合作', value: '业务合作' },
|
|
||||||
{ label: '管理挂靠', value: '管理挂靠' },
|
{ label: '管理挂靠', value: '管理挂靠' },
|
||||||
|
{ label: '业务合作', value: '业务合作' },
|
||||||
],
|
],
|
||||||
width: 120,
|
width: 120,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '能源类型',
|
label: '车辆类型',
|
||||||
prop: 'energyType',
|
prop: 'vehicleType',
|
||||||
search: true,
|
search: true,
|
||||||
|
searchOrder: 3,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
dicData: [
|
dicData: [
|
||||||
{ label: '柴油', value: '柴油' },
|
{ label: '全部', value: '' },
|
||||||
{ label: '汽油', value: '汽油' },
|
{ label: '高栏车', value: '高栏' },
|
||||||
{ label: '新能源', value: '新能源' },
|
{ label: '低栏车', value: '低栏' },
|
||||||
{ label: '天然气', value: '天然气' },
|
{ label: '平板车', value: '平板' },
|
||||||
|
{ label: '厢式车', value: '厢式' },
|
||||||
|
{ label: '拖挂车', value: '拖挂' },
|
||||||
|
{ label: '半挂车', value: '半挂' },
|
||||||
],
|
],
|
||||||
width: 110,
|
width: 110,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
@@ -76,9 +75,10 @@ export const option = {
|
|||||||
align: 'right',
|
align: 'right',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: '车辆状态',
|
||||||
prop: 'status',
|
prop: 'status',
|
||||||
search: true,
|
search: true,
|
||||||
|
searchOrder: 2,
|
||||||
type: 'select',
|
type: 'select',
|
||||||
slot: true,
|
slot: true,
|
||||||
dicData: [
|
dicData: [
|
||||||
|
|||||||
@@ -33,17 +33,26 @@ export const accidentResponsibilityDic = [
|
|||||||
export const option = {
|
export const option = {
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 1050,
|
dialogWidth: 960,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
|
searchLabelWidth: 160,
|
||||||
tip: false,
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '车船类型',
|
label: '车船类型',
|
||||||
@@ -53,6 +62,7 @@ export const option = {
|
|||||||
dicData: vehicleTypeDic,
|
dicData: vehicleTypeDic,
|
||||||
value: '车辆',
|
value: '车辆',
|
||||||
search: true,
|
search: true,
|
||||||
|
span: 24,
|
||||||
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -62,6 +72,8 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '输入车牌号/船号查询选择',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
@@ -74,6 +86,8 @@ export const option = {
|
|||||||
format: 'YYYY-MM-DD',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择,日期选择器',
|
||||||
rules: [{ required: true, message: '请选择事故发生日期', trigger: 'click' }],
|
rules: [{ required: true, message: '请选择事故发生日期', trigger: 'click' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -81,6 +95,8 @@ export const option = {
|
|||||||
prop: 'accidentLocation',
|
prop: 'accidentLocation',
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入,100字内',
|
||||||
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
|
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -90,6 +106,9 @@ export const option = {
|
|||||||
dicData: accidentNatureDic,
|
dicData: accidentNatureDic,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择',
|
||||||
|
rules: [{ required: true, message: '请选择事故性质', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '事故责任',
|
label: '事故责任',
|
||||||
@@ -98,13 +117,19 @@ export const option = {
|
|||||||
dicData: accidentResponsibilityDic,
|
dicData: accidentResponsibilityDic,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择',
|
||||||
|
rules: [{ required: true, message: '请选择事故责任', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '直接经济损失',
|
label: '直接经济损失',
|
||||||
prop: 'directEconomicLoss',
|
prop: 'directEconomicLoss',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -112,17 +137,22 @@ export const option = {
|
|||||||
prop: 'insuranceClaimAmount',
|
prop: 'insuranceClaimAmount',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '事故原因',
|
label: '事故原因及损坏情况',
|
||||||
prop: 'accidentReasonDamage',
|
prop: 'accidentReasonDamage',
|
||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
minRows: 3,
|
minRows: 4,
|
||||||
span: 24,
|
span: 24,
|
||||||
search: true,
|
search: true,
|
||||||
hide: true,
|
minWidth: 220,
|
||||||
|
overHidden: true,
|
||||||
|
placeholder: '请输入,500字以内',
|
||||||
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -131,25 +161,18 @@ export const option = {
|
|||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
minRows: 3,
|
minRows: 3,
|
||||||
span: 24,
|
span: 24,
|
||||||
hide: true,
|
minWidth: 180,
|
||||||
|
overHidden: true,
|
||||||
|
placeholder: '请输入,200字以内',
|
||||||
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '事故评定开始日期',
|
label: '事故评定开始日期',
|
||||||
@@ -188,23 +211,12 @@ export const option = {
|
|||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建开始时间',
|
label: '创建时间',
|
||||||
prop: 'createTimeStart',
|
prop: 'createTimeRange',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD 00:00:00',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
search: true,
|
searchRange: true,
|
||||||
hide: true,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建结束时间',
|
|
||||||
prop: 'createTimeEnd',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD 23:59:59',
|
|
||||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
|
||||||
search: true,
|
search: true,
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
@@ -251,6 +263,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -32,17 +32,26 @@ export const shipInspectionTypeDic = [
|
|||||||
export const option = {
|
export const option = {
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 1050,
|
dialogWidth: 960,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
|
searchLabelWidth: 160,
|
||||||
tip: false,
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '车船类型',
|
label: '车船类型',
|
||||||
@@ -52,6 +61,7 @@ export const option = {
|
|||||||
dicData: vehicleTypeDic,
|
dicData: vehicleTypeDic,
|
||||||
value: '车辆',
|
value: '车辆',
|
||||||
search: true,
|
search: true,
|
||||||
|
span: 24,
|
||||||
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -61,6 +71,8 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '输入车牌号/船号查询选择',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
@@ -73,6 +85,8 @@ export const option = {
|
|||||||
format: 'YYYY-MM-DD',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择,日期选择器',
|
||||||
rules: [{ required: true, message: '请选择检测评定日期', trigger: 'click' }],
|
rules: [{ required: true, message: '请选择检测评定日期', trigger: 'click' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -82,6 +96,8 @@ export const option = {
|
|||||||
format: 'YYYY-MM-DD',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ required: true, message: '请选择有效期截止日', trigger: 'click' }],
|
rules: [{ required: true, message: '请选择有效期截止日', trigger: 'click' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -90,6 +106,8 @@ export const option = {
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
dicData: vehicleTechnicalLevelDic,
|
dicData: vehicleTechnicalLevelDic,
|
||||||
minWidth: 130,
|
minWidth: 130,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择',
|
||||||
rules: [{ required: true, message: '请选择车辆技术等级', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择车辆技术等级', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -99,19 +117,24 @@ export const option = {
|
|||||||
dicData: shipInspectionTypeDic,
|
dicData: shipInspectionTypeDic,
|
||||||
display: false,
|
display: false,
|
||||||
minWidth: 130,
|
minWidth: 130,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择',
|
||||||
rules: [{ required: true, message: '请选择船舶检验类型', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择船舶检验类型', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '客车类型及等级',
|
label: '客车类型及等级',
|
||||||
prop: 'passengerTypeLevel',
|
prop: 'passengerTypeLevel',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
hide: true,
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '检测评定单位',
|
label: '检测评定单位',
|
||||||
prop: 'inspectionUnit',
|
prop: 'inspectionUnit',
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -119,7 +142,10 @@ export const option = {
|
|||||||
prop: 'fee',
|
prop: 'fee',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入费用', trigger: 'blur' },
|
{ required: true, message: '请输入费用', trigger: 'blur' },
|
||||||
{ validator: validateNonNegative, trigger: 'blur' },
|
{ validator: validateNonNegative, trigger: 'blur' },
|
||||||
@@ -129,7 +155,8 @@ export const option = {
|
|||||||
label: '评定(复核)单位',
|
label: '评定(复核)单位',
|
||||||
prop: 'assessmentUnit',
|
prop: 'assessmentUnit',
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
hide: true,
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -138,25 +165,18 @@ export const option = {
|
|||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
minRows: 3,
|
minRows: 3,
|
||||||
span: 24,
|
span: 24,
|
||||||
hide: true,
|
minWidth: 180,
|
||||||
|
overHidden: true,
|
||||||
|
placeholder: '请输入,200字以内',
|
||||||
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '检测评定开始日期',
|
label: '检测评定开始日期',
|
||||||
@@ -195,24 +215,11 @@ export const option = {
|
|||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建开始时间',
|
label: '创建时间',
|
||||||
prop: 'createTimeStart',
|
prop: 'createTimeRange',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD 00:00:00',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
search: true,
|
|
||||||
hide: true,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建结束时间',
|
|
||||||
prop: 'createTimeEnd',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD 23:59:59',
|
|
||||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
|
||||||
search: true,
|
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
@@ -258,6 +265,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -22,17 +22,26 @@ const maskEtcCardNo = value => {
|
|||||||
export const option = {
|
export const option = {
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 980,
|
dialogWidth: 960,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
|
searchLabelWidth: 160,
|
||||||
tip: false,
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
menuFixed: 'right',
|
menuFixed: 'right',
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
@@ -42,22 +51,13 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '输入车牌号模糊查询选择',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入车牌号', trigger: 'blur' },
|
{ required: true, message: '请输入车牌号', trigger: 'blur' },
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'ETC卡号',
|
|
||||||
prop: 'etcCardNo',
|
|
||||||
formatter: row => maskEtcCardNo(row.etcCardNo),
|
|
||||||
search: true,
|
|
||||||
minWidth: 220,
|
|
||||||
rules: [
|
|
||||||
{ required: true, message: '请输入ETC卡号', trigger: 'blur' },
|
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: '入口时间',
|
label: '入口时间',
|
||||||
prop: 'entryTime',
|
prop: 'entryTime',
|
||||||
@@ -65,6 +65,21 @@ export const option = {
|
|||||||
format: 'YYYY-MM-DD HH:mm',
|
format: 'YYYY-MM-DD HH:mm',
|
||||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择,日期选择器',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ETC卡号',
|
||||||
|
prop: 'etcCardNo',
|
||||||
|
formatter: row => maskEtcCardNo(row.etcCardNo),
|
||||||
|
search: true,
|
||||||
|
minWidth: 220,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请输入ETC卡号', trigger: 'blur' },
|
||||||
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '出口时间',
|
label: '出口时间',
|
||||||
@@ -73,18 +88,38 @@ export const option = {
|
|||||||
format: 'YYYY-MM-DD HH:mm',
|
format: 'YYYY-MM-DD HH:mm',
|
||||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择,日期选择器',
|
||||||
rules: [{ required: true, message: '请选择出口时间', trigger: 'click' }],
|
rules: [{ required: true, message: '请选择出口时间', trigger: 'click' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '入口站',
|
label: '入口站',
|
||||||
prop: 'entryStation',
|
prop: 'entryStation',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '交易金额',
|
||||||
|
prop: 'transactionAmount',
|
||||||
|
type: 'number',
|
||||||
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
|
minWidth: 130,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请输入交易金额', trigger: 'blur' },
|
||||||
|
{ validator: validateNonNegative, trigger: 'blur' },
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '出口站',
|
label: '出口站',
|
||||||
prop: 'exitStation',
|
prop: 'exitStation',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -94,18 +129,7 @@ export const option = {
|
|||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
},
|
viewDisplay: false,
|
||||||
{
|
|
||||||
label: '交易金额',
|
|
||||||
prop: 'transactionAmount',
|
|
||||||
type: 'number',
|
|
||||||
precision: 2,
|
|
||||||
append: '元',
|
|
||||||
minWidth: 130,
|
|
||||||
rules: [
|
|
||||||
{ required: true, message: '请输入交易金额', trigger: 'blur' },
|
|
||||||
{ validator: validateNonNegative, trigger: 'blur' },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '备注',
|
label: '备注',
|
||||||
@@ -115,24 +139,16 @@ export const option = {
|
|||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
|
placeholder: '请输入,200字以内',
|
||||||
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '组织',
|
label: '组织',
|
||||||
@@ -185,6 +201,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -33,16 +33,23 @@ export const option = {
|
|||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 1100,
|
dialogWidth: 1100,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
tip: false,
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '车船类型',
|
label: '车船类型',
|
||||||
@@ -123,6 +130,7 @@ export const option = {
|
|||||||
prop: 'insuredAmount',
|
prop: 'insuredAmount',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
@@ -131,6 +139,7 @@ export const option = {
|
|||||||
prop: 'premium',
|
prop: 'premium',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入保费', trigger: 'blur' },
|
{ required: true, message: '请输入保费', trigger: 'blur' },
|
||||||
@@ -173,23 +182,12 @@ export const option = {
|
|||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建开始时间',
|
label: '创建时间',
|
||||||
prop: 'createTimeStart',
|
prop: 'createTimeRange',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD 00:00:00',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
search: true,
|
searchRange: true,
|
||||||
hide: true,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建结束时间',
|
|
||||||
prop: 'createTimeEnd',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD 23:59:59',
|
|
||||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
|
||||||
search: true,
|
search: true,
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
@@ -236,6 +234,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -12,66 +12,111 @@ const validateNonNegative = (rule, value, callback) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const vehicleTypeDic = [
|
||||||
|
{ label: '车辆', value: '车辆' },
|
||||||
|
{ label: '船舶', value: '船舶' },
|
||||||
|
];
|
||||||
|
|
||||||
export const option = {
|
export const option = {
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 980,
|
dialogWidth: 980,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
tip: false,
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
menuFixed: 'right',
|
menuFixed: 'right',
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '车牌号',
|
label: '车船类型',
|
||||||
|
prop: 'vehicleType',
|
||||||
|
type: 'radio',
|
||||||
|
dicData: vehicleTypeDic,
|
||||||
|
value: '车辆',
|
||||||
|
search: true,
|
||||||
|
searchSpan: 6,
|
||||||
|
minWidth: 110,
|
||||||
|
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '车牌号/船号',
|
||||||
prop: 'vehicleNo',
|
prop: 'vehicleNo',
|
||||||
slot: true,
|
slot: true,
|
||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
|
searchSpan: 6,
|
||||||
minWidth: 130,
|
minWidth: 130,
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入车牌号', trigger: 'blur' },
|
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '上月统计日里程表示值(km)',
|
label: '上月统计里程数',
|
||||||
prop: 'previousMonthMileage',
|
prop: 'previousMonthMileage',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '公里',
|
||||||
minWidth: 210,
|
minWidth: 210,
|
||||||
|
slot: true,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '本月统计日里程表示值(km)',
|
label: '本月统计里程数',
|
||||||
prop: 'currentMonthMileage',
|
prop: 'currentMonthMileage',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '公里',
|
||||||
minWidth: 210,
|
minWidth: 210,
|
||||||
|
slot: true,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '本月行驶里程(km)',
|
label: '本月行驶里程数',
|
||||||
prop: 'monthlyMileage',
|
prop: 'monthlyMileage',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '公里',
|
||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
|
slot: true,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '累计行驶里程(km)',
|
label: '累计行驶里程数',
|
||||||
prop: 'totalMileage',
|
prop: 'totalMileage',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '公里',
|
||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
|
slot: true,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '里程单位',
|
||||||
|
prop: 'mileageUnit',
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{ label: '公里', value: '公里' },
|
||||||
|
{ label: '海里', value: '海里' },
|
||||||
|
],
|
||||||
|
value: '公里',
|
||||||
|
hide: true,
|
||||||
|
display: false,
|
||||||
|
search: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '备注',
|
label: '备注',
|
||||||
prop: 'remark',
|
prop: 'remark',
|
||||||
@@ -85,37 +130,28 @@ export const option = {
|
|||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '累计行驶里程开始值',
|
label: '累计行驶里程',
|
||||||
prop: 'totalMileageStart',
|
prop: 'totalMileageStart',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
search: true,
|
search: true,
|
||||||
|
searchSpan: 8,
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
viewDisplay: false,
|
viewDisplay: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '累计行驶里程结束值',
|
label: '累计行驶里程数结束值',
|
||||||
prop: 'totalMileageEnd',
|
prop: 'totalMileageEnd',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
search: true,
|
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
@@ -134,24 +170,14 @@ export const option = {
|
|||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建开始时间',
|
label: '创建时间',
|
||||||
prop: 'createTimeStart',
|
prop: 'createTimeRange',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD 00:00:00',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
search: true,
|
searchRange: true,
|
||||||
hide: true,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建结束时间',
|
|
||||||
prop: 'createTimeEnd',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD 23:59:59',
|
|
||||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
|
||||||
search: true,
|
search: true,
|
||||||
|
searchSpan: 6,
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
@@ -168,6 +194,7 @@ export const option = {
|
|||||||
},
|
},
|
||||||
checkStrictly: true,
|
checkStrictly: true,
|
||||||
search: true,
|
search: true,
|
||||||
|
searchSpan: 6,
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
@@ -197,6 +224,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -26,16 +26,19 @@ export const option = {
|
|||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 980,
|
dialogWidth: 980,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
menuFixed: 'right',
|
menuFixed: 'right',
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
@@ -85,6 +88,7 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
|
placeholder: '输入车牌号/船号查询选择',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
@@ -159,19 +163,10 @@ export const option = {
|
|||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '交易开始时间',
|
label: '交易开始时间',
|
||||||
@@ -232,24 +227,11 @@ export const option = {
|
|||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建开始时间',
|
label: '创建时间',
|
||||||
prop: 'createTimeStart',
|
prop: 'createTimeRange',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD 00:00:00',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
search: true,
|
|
||||||
hide: true,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建结束时间',
|
|
||||||
prop: 'createTimeEnd',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD 23:59:59',
|
|
||||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
|
||||||
search: true,
|
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
@@ -295,6 +277,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -30,37 +30,28 @@ export const expenseTypeDic = [
|
|||||||
export const option = {
|
export const option = {
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 980,
|
dialogWidth: 960,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
|
searchLabelWidth: 160,
|
||||||
tip: false,
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
menuFixed: 'right',
|
menuFixed: 'right',
|
||||||
column: [
|
column: [
|
||||||
{
|
|
||||||
label: '费用日期',
|
|
||||||
prop: 'expenseDate',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD',
|
|
||||||
valueFormat: 'YYYY-MM-DD',
|
|
||||||
minWidth: 140,
|
|
||||||
rules: [{ required: true, message: '请选择费用日期', trigger: 'click' }],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '其他费用类型',
|
|
||||||
prop: 'expenseType',
|
|
||||||
type: 'select',
|
|
||||||
dicData: expenseTypeDic,
|
|
||||||
search: true,
|
|
||||||
minWidth: 150,
|
|
||||||
rules: [{ required: true, message: '请选择其他费用类型', trigger: 'change' }],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: '车船类型',
|
label: '车船类型',
|
||||||
prop: 'vehicleType',
|
prop: 'vehicleType',
|
||||||
@@ -69,6 +60,7 @@ export const option = {
|
|||||||
value: '车辆',
|
value: '车辆',
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 110,
|
minWidth: 110,
|
||||||
|
span: 24,
|
||||||
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -78,11 +70,49 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '输入车牌号/船号查询选择',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '费用日期',
|
||||||
|
prop: 'expenseDate',
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择,日期选择器',
|
||||||
|
rules: [{ required: true, message: '请选择费用日期', trigger: 'click' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '费用类型',
|
||||||
|
prop: 'expenseType',
|
||||||
|
type: 'select',
|
||||||
|
dicData: expenseTypeDic,
|
||||||
|
search: true,
|
||||||
|
minWidth: 150,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择',
|
||||||
|
rules: [{ required: true, message: '请选择费用类型', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '金额',
|
||||||
|
prop: 'amount',
|
||||||
|
type: 'number',
|
||||||
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
|
minWidth: 120,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请输入金额', trigger: 'blur' },
|
||||||
|
{ validator: validateNonNegative, trigger: 'blur' },
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '数据来源',
|
label: '数据来源',
|
||||||
prop: 'dataSource',
|
prop: 'dataSource',
|
||||||
@@ -90,18 +120,7 @@ export const option = {
|
|||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
editDisplay: false,
|
editDisplay: false,
|
||||||
},
|
viewDisplay: false,
|
||||||
{
|
|
||||||
label: '金额',
|
|
||||||
prop: 'amount',
|
|
||||||
type: 'number',
|
|
||||||
precision: 2,
|
|
||||||
append: '元',
|
|
||||||
minWidth: 120,
|
|
||||||
rules: [
|
|
||||||
{ required: true, message: '请输入金额', trigger: 'blur' },
|
|
||||||
{ validator: validateNonNegative, trigger: 'blur' },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '备注',
|
label: '备注',
|
||||||
@@ -111,24 +130,16 @@ export const option = {
|
|||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
|
placeholder: '请输入,200字以内',
|
||||||
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '费用日期',
|
label: '费用日期',
|
||||||
@@ -194,6 +205,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -23,17 +23,26 @@ const validatePositiveInteger = (rule, value, callback) => {
|
|||||||
export const option = {
|
export const option = {
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 980,
|
dialogWidth: 960,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
|
searchLabelWidth: 160,
|
||||||
tip: false,
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '车牌号',
|
label: '车牌号',
|
||||||
@@ -42,6 +51,8 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 130,
|
minWidth: 130,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '输入车牌号查询选择',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入车牌号', trigger: 'blur' },
|
{ required: true, message: '请输入车牌号', trigger: 'blur' },
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
@@ -51,6 +62,8 @@ export const option = {
|
|||||||
label: '处理人',
|
label: '处理人',
|
||||||
prop: 'handler',
|
prop: 'handler',
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 20, message: '最多 20 个字符', trigger: 'blur' }],
|
rules: [{ max: 20, message: '最多 20 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -60,12 +73,16 @@ export const option = {
|
|||||||
format: 'YYYY-MM-DD',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
minWidth: 130,
|
minWidth: 130,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择',
|
||||||
rules: [{ required: true, message: '请选择换胎时间', trigger: 'click' }],
|
rules: [{ required: true, message: '请选择换胎时间', trigger: 'click' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '轮胎品牌',
|
label: '轮胎品牌',
|
||||||
prop: 'tireBrand',
|
prop: 'tireBrand',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -74,6 +91,8 @@ export const option = {
|
|||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 0,
|
precision: 0,
|
||||||
minWidth: 110,
|
minWidth: 110,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ validator: validatePositiveInteger, trigger: 'blur' }],
|
rules: [{ validator: validatePositiveInteger, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -81,7 +100,10 @@ export const option = {
|
|||||||
prop: 'replacementCost',
|
prop: 'replacementCost',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入换胎费用', trigger: 'blur' },
|
{ required: true, message: '请输入换胎费用', trigger: 'blur' },
|
||||||
{ validator: validateNonNegative, trigger: 'blur' },
|
{ validator: validateNonNegative, trigger: 'blur' },
|
||||||
@@ -92,6 +114,8 @@ export const option = {
|
|||||||
prop: 'replacementDescription',
|
prop: 'replacementDescription',
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
|
span: 24,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -102,24 +126,16 @@ export const option = {
|
|||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
@@ -134,23 +150,12 @@ export const option = {
|
|||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建开始时间',
|
label: '创建时间',
|
||||||
prop: 'createTimeStart',
|
prop: 'createTimeRange',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD 00:00:00',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
search: true,
|
searchRange: true,
|
||||||
hide: true,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建结束时间',
|
|
||||||
prop: 'createTimeEnd',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD 23:59:59',
|
|
||||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
|
||||||
search: true,
|
search: true,
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
@@ -197,6 +202,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -17,16 +17,19 @@ export const option = {
|
|||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 980,
|
dialogWidth: 980,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
tip: false,
|
tip: false,
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
menuFixed: 'right',
|
menuFixed: 'right',
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
@@ -46,6 +49,7 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
placeholder: '输入车牌号/船号模糊查询选择',
|
||||||
rules: [{ max: 30, message: '最多 30 个字符', trigger: 'blur' }],
|
rules: [{ max: 30, message: '最多 30 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -83,19 +87,10 @@ export const option = {
|
|||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
@@ -110,23 +105,12 @@ export const option = {
|
|||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建开始时间',
|
label: '创建时间',
|
||||||
prop: 'createTimeStart',
|
prop: 'createTimeRange',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD 00:00:00',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
search: true,
|
searchRange: true,
|
||||||
hide: true,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建结束时间',
|
|
||||||
prop: 'createTimeEnd',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD 23:59:59',
|
|
||||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
|
||||||
search: true,
|
search: true,
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
@@ -173,6 +157,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -41,17 +41,26 @@ export const processStatusDic = [
|
|||||||
export const option = {
|
export const option = {
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
dialogWidth: 1100,
|
dialogWidth: 960,
|
||||||
labelPosition: 'top',
|
labelPosition: 'right',
|
||||||
|
labelWidth: 'auto',
|
||||||
|
searchLabelWidth: 160,
|
||||||
tip: false,
|
tip: false,
|
||||||
|
searchBtnText: '查询',
|
||||||
|
emptyBtnText: '重置',
|
||||||
|
saveBtnText: '提交',
|
||||||
|
updateBtnText: '提交',
|
||||||
searchShow: true,
|
searchShow: true,
|
||||||
searchMenuSpan: 6,
|
searchMenuSpan: 24,
|
||||||
|
searchIcon: true,
|
||||||
|
searchIndex: 4,
|
||||||
|
searchMenuPosition: 'right',
|
||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 160,
|
||||||
column: [
|
column: [
|
||||||
{
|
{
|
||||||
label: '车船类型',
|
label: '车船类型',
|
||||||
@@ -61,6 +70,7 @@ export const option = {
|
|||||||
dicData: vehicleTypeDic,
|
dicData: vehicleTypeDic,
|
||||||
value: '车辆',
|
value: '车辆',
|
||||||
search: true,
|
search: true,
|
||||||
|
span: 24,
|
||||||
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -70,6 +80,8 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '输入车牌号/船号查询选择',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
||||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||||
@@ -81,6 +93,8 @@ export const option = {
|
|||||||
formslot: true,
|
formslot: true,
|
||||||
search: true,
|
search: true,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入驾驶人/船长', trigger: 'blur' },
|
{ required: true, message: '请输入驾驶人/船长', trigger: 'blur' },
|
||||||
{ max: 20, message: '最多 20 个字符', trigger: 'blur' },
|
{ max: 20, message: '最多 20 个字符', trigger: 'blur' },
|
||||||
@@ -92,6 +106,8 @@ export const option = {
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
dicData: violationTypeDic,
|
dicData: violationTypeDic,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择',
|
||||||
rules: [{ required: true, message: '请选择类型', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择类型', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -100,6 +116,8 @@ export const option = {
|
|||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
display: false,
|
display: false,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入事项', trigger: 'blur' },
|
{ required: true, message: '请输入事项', trigger: 'blur' },
|
||||||
{ max: 100, message: '最多 100 个字符', trigger: 'blur' },
|
{ max: 100, message: '最多 100 个字符', trigger: 'blur' },
|
||||||
@@ -112,6 +130,8 @@ export const option = {
|
|||||||
format: 'YYYY-MM-DD HH:mm:ss',
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请选择',
|
||||||
rules: [{ required: true, message: '请选择时间', trigger: 'click' }],
|
rules: [{ required: true, message: '请选择时间', trigger: 'click' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -119,6 +139,8 @@ export const option = {
|
|||||||
prop: 'location',
|
prop: 'location',
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入地点', trigger: 'blur' },
|
{ required: true, message: '请输入地点', trigger: 'blur' },
|
||||||
{ max: 100, message: '最多 100 个字符', trigger: 'blur' },
|
{ max: 100, message: '最多 100 个字符', trigger: 'blur' },
|
||||||
@@ -129,7 +151,10 @@ export const option = {
|
|||||||
prop: 'fineAmount',
|
prop: 'fineAmount',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 2,
|
precision: 2,
|
||||||
|
append: '元',
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -137,14 +162,17 @@ export const option = {
|
|||||||
prop: 'deductPoints',
|
prop: 'deductPoints',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
precision: 0,
|
precision: 0,
|
||||||
hide: true,
|
minWidth: 110,
|
||||||
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ validator: validateDeductPoints, trigger: 'blur' }],
|
rules: [{ validator: validateDeductPoints, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '被罚单位',
|
label: '被罚单位',
|
||||||
prop: 'penaltyUnit',
|
prop: 'penaltyUnit',
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
hide: true,
|
span: 12,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -152,9 +180,11 @@ export const option = {
|
|||||||
prop: 'processStatus',
|
prop: 'processStatus',
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
dicData: processStatusDic,
|
dicData: processStatusDic,
|
||||||
value: '已处理',
|
value: '未处理',
|
||||||
search: true,
|
search: true,
|
||||||
|
clearable: true,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
|
span: 12,
|
||||||
rules: [{ required: true, message: '请选择状态', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择状态', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -163,7 +193,9 @@ export const option = {
|
|||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
minRows: 3,
|
minRows: 3,
|
||||||
span: 24,
|
span: 24,
|
||||||
hide: true,
|
minWidth: 220,
|
||||||
|
overHidden: true,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [
|
rules: [
|
||||||
{ required: true, message: '请输入过程描述', trigger: 'blur' },
|
{ required: true, message: '请输入过程描述', trigger: 'blur' },
|
||||||
{ max: 500, message: '最多 500 个字符', trigger: 'blur' },
|
{ max: 500, message: '最多 500 个字符', trigger: 'blur' },
|
||||||
@@ -175,25 +207,18 @@ export const option = {
|
|||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
minRows: 3,
|
minRows: 3,
|
||||||
span: 24,
|
span: 24,
|
||||||
hide: true,
|
minWidth: 220,
|
||||||
|
overHidden: true,
|
||||||
|
placeholder: '请输入',
|
||||||
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '附件',
|
label: '附件',
|
||||||
prop: 'attachments',
|
prop: 'attachments',
|
||||||
type: 'upload',
|
|
||||||
listType: 'text',
|
|
||||||
multiple: true,
|
|
||||||
accept: '.jpg,.jpeg,.png,.pdf',
|
|
||||||
propsHttp: {
|
|
||||||
res: 'data',
|
|
||||||
url: 'link',
|
|
||||||
name: 'name',
|
|
||||||
},
|
|
||||||
action: '/blade-resource/oss/endpoint/put-file',
|
|
||||||
span: 24,
|
span: 24,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
slot: true,
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
@@ -208,23 +233,12 @@ export const option = {
|
|||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '创建开始时间',
|
label: '创建时间',
|
||||||
prop: 'createTimeStart',
|
prop: 'createTimeRange',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
format: 'YYYY-MM-DD 00:00:00',
|
format: 'YYYY-MM-DD',
|
||||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
search: true,
|
searchRange: true,
|
||||||
hide: true,
|
|
||||||
addDisplay: false,
|
|
||||||
editDisplay: false,
|
|
||||||
viewDisplay: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建结束时间',
|
|
||||||
prop: 'createTimeEnd',
|
|
||||||
type: 'date',
|
|
||||||
format: 'YYYY-MM-DD 23:59:59',
|
|
||||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
|
||||||
search: true,
|
search: true,
|
||||||
hide: true,
|
hide: true,
|
||||||
addDisplay: false,
|
addDisplay: false,
|
||||||
@@ -271,6 +285,7 @@ export const option = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
|
labelPosition: 'right',
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
column: [
|
column: [
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="avue-logo">
|
<div class="avue-logo" @click="goHome" style="cursor: pointer">
|
||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<span v-if="getScreen(isCollapse)" class="avue-logo_subtitle" key="0">
|
<span v-if="getScreen(isCollapse)" class="avue-logo_subtitle" key="0">
|
||||||
<img class="logo-img" src="/img/logo.png" />
|
<img class="logo-img" src="/img/logo.png" />
|
||||||
@@ -23,19 +23,23 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {},
|
created() {},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['isCollapse']),
|
...mapGetters(['isCollapse', 'tagWel']),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
goHome() {
|
||||||
|
this.$router.push(this.tagWel);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.logo-title {
|
.logo-title {
|
||||||
font-size: 16px;
|
font-size: 17px;
|
||||||
background-image: linear-gradient(120deg, #54b6d0 16%, #3f8bdb, #2c77f1);
|
color: #fff;
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
padding-left: 30px;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.logo-img {
|
.logo-img {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
:key="index"
|
:key="index"
|
||||||
@click="handleSelect(item)"
|
@click="handleSelect(item)"
|
||||||
>
|
>
|
||||||
<i :class="[item[iconKey], 'avue-searchs__item-icon']"></i>
|
<i v-if="item[iconKey]" :class="[item[iconKey], 'avue-searchs__item-icon']"></i>
|
||||||
<span class="avue-searchs__item-title">{{ item[labelKey] }}</span>
|
<span class="avue-searchs__item-title">{{ item[labelKey] }}</span>
|
||||||
<div class="avue-searchs__item-path">
|
<div class="avue-searchs__item-path">
|
||||||
{{ item[pathKey] }}
|
{{ item[pathKey] }}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
@click="open(item)"
|
@click="open(item)"
|
||||||
:key="item[labelKey]"
|
:key="item[labelKey]"
|
||||||
>
|
>
|
||||||
<i :class="item[iconKey]"></i>
|
<i v-if="item[iconKey]" :class="item[iconKey]"></i>
|
||||||
<template #title>
|
<template #title>
|
||||||
<span :alt="item[pathKey]">{{ getTitle(item) }}</span>
|
<span :alt="item[pathKey]">{{ getTitle(item) }}</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
:key="item[labelKey]"
|
:key="item[labelKey]"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<i :class="item[iconKey]"></i>
|
<i v-if="item[iconKey]" :class="item[iconKey]"></i>
|
||||||
<span>{{ getTitle(item) }}</span>
|
<span>{{ getTitle(item) }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-for="(child, cindex) in item[childrenKey]" :key="child[labelKey]">
|
<template v-for="(child, cindex) in item[childrenKey]" :key="child[labelKey]">
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
@click="open(child)"
|
@click="open(child)"
|
||||||
v-if="validatenull(child[childrenKey])"
|
v-if="validatenull(child[childrenKey])"
|
||||||
>
|
>
|
||||||
<i :class="child[iconKey]"></i>
|
<i v-if="child[iconKey]" :class="child[iconKey]"></i>
|
||||||
<template #title>
|
<template #title>
|
||||||
<span>{{ getTitle(child) }}</span>
|
<span>{{ getTitle(child) }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -10,20 +10,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-bar__title">
|
<div class="top-bar__title">
|
||||||
<top-menu ref="topMenu" v-if="setting.menu"></top-menu>
|
<!-- <top-menu ref="topMenu" v-if="setting.menu"></top-menu>-->
|
||||||
<top-search class="top-bar__item" v-if="setting.search"></top-search>
|
<top-search class="top-bar__item" v-if="setting.search"></top-search>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-bar__right">
|
<div class="top-bar__right">
|
||||||
<div v-if="setting.color" class="top-bar__item">
|
<div v-if="setting.color" class="top-bar__item">
|
||||||
<top-color></top-color>
|
<top-color></top-color>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="setting.theme" class="top-bar__item">
|
<div v-if="setting.theme" class="top-bar__item" style="display: none;">
|
||||||
<top-theme></top-theme>
|
<top-theme></top-theme>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="setting.lock" class="top-bar__item">
|
<div v-if="setting.lock" class="top-bar__item">
|
||||||
<top-lock></top-lock>
|
<top-lock></top-lock>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-bar__item">
|
<div v-if="setting.lang" class="top-bar__item">
|
||||||
<top-lang></top-lang>
|
<top-lang></top-lang>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-bar__item" v-if="setting.fullscreen">
|
<div class="top-bar__item" v-if="setting.fullscreen">
|
||||||
@@ -33,9 +33,9 @@
|
|||||||
<top-logs></top-logs>
|
<top-logs></top-logs>
|
||||||
</div>
|
</div>
|
||||||
<div class="top-user">
|
<div class="top-user">
|
||||||
<img class="top-bar__img" :src="userInfo.avatar" />
|
<el-dropdown :hide-on-click="false" trigger="hover">
|
||||||
<el-dropdown :hide-on-click="false">
|
<span class="el-dropdown-link top-user__trigger">
|
||||||
<span class="el-dropdown-link">
|
<img class="top-bar__img" :src="userInfo.avatar" alt="" />
|
||||||
{{ userInfo.real_name }}
|
{{ userInfo.real_name }}
|
||||||
<el-icon class="el-icon--right">
|
<el-icon class="el-icon--right">
|
||||||
<arrow-down />
|
<arrow-down />
|
||||||
@@ -43,12 +43,12 @@
|
|||||||
</span>
|
</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item @click="toDashboard">
|
<!-- <el-dropdown-item @click="toDashboard">-->
|
||||||
<i class="icon-zuzhixiaxia" /> {{ $t('navbar.dashboard') }}
|
<!-- <i class="icon-zuzhixiaxia" /> {{ $t('navbar.dashboard') }}-->
|
||||||
</el-dropdown-item>
|
<!-- </el-dropdown-item>-->
|
||||||
<el-dropdown-item @click="toAllMenu">
|
<!-- <el-dropdown-item @click="toAllMenu">-->
|
||||||
<i class="icon-liebiao" /> {{ $t('navbar.allMenu') }}
|
<!-- <i class="icon-liebiao" /> {{ $t('navbar.allMenu') }}-->
|
||||||
</el-dropdown-item>
|
<!-- </el-dropdown-item>-->
|
||||||
<el-dropdown-item @click="toInfo">
|
<el-dropdown-item @click="toInfo">
|
||||||
<i class="icon-yonghu" />{{ $t('navbar.userinfo') }}
|
<i class="icon-yonghu" />{{ $t('navbar.userinfo') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<top-setting></top-setting>
|
<top-setting v-if="setting.settingBtn"></top-setting>
|
||||||
<el-dialog title="请选择身份信息后切换" append-to-body v-model="userBox" width="400px">
|
<el-dialog title="请选择身份信息后切换" append-to-body v-model="userBox" width="400px">
|
||||||
<avue-form :option="userOption" v-model="userForm" @submit="toAll" />
|
<avue-form :option="userOption" v-model="userForm" @submit="toAll" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -161,7 +161,7 @@ export default {
|
|||||||
roleId: '',
|
roleId: '',
|
||||||
},
|
},
|
||||||
userOption: {
|
userOption: {
|
||||||
labelWidth: 70,
|
labelWidth: 'auto',
|
||||||
submitBtn: true,
|
submitBtn: true,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
submitText: '切 换',
|
submitText: '切 换',
|
||||||
@@ -361,4 +361,22 @@ export default {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
.top-user__trigger {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
outline: none;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: rgba(255, 255, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar__img {
|
||||||
|
margin: 0 5px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'; // default color
|
import { mapGetters } from 'vuex'; // default color
|
||||||
|
const DEFAULT_PRIMARY_COLOR = '#409eff';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'topColor',
|
name: 'topColor',
|
||||||
data() {
|
data() {
|
||||||
@@ -17,7 +19,7 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.themeVal = this.colorName || '#2C77F1';
|
this.themeVal = this.colorName || DEFAULT_PRIMARY_COLOR;
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
themeVal(val, oldVal) {
|
themeVal(val, oldVal) {
|
||||||
@@ -69,6 +71,7 @@ export default {
|
|||||||
`${this.getLightColor(e, i / 10)}`
|
`${this.getLightColor(e, i / 10)}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
document.documentElement.style.setProperty(`${pre}-dark-2`, `${this.getDarkColor(e, 0.2)}`);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<span v-if="text" @click="handleLock">{{ text }}</span>
|
<span v-if="text" @click="handleLock">{{ text }}</span>
|
||||||
<i v-else class="icon-suoping" @click="handleLock"></i>
|
<i v-else class="icon-suoping" @click="handleLock"></i>
|
||||||
<el-dialog title="设置锁屏密码" v-model="box" width="30%" append-to-body>
|
<el-dialog title="设置锁屏密码" v-model="box" width="30%" append-to-body>
|
||||||
<el-form :model="form" ref="form" label-width="80px">
|
<el-form :model="form" ref="form" label-width="auto">
|
||||||
<el-form-item
|
<el-form-item
|
||||||
label="锁屏密码"
|
label="锁屏密码"
|
||||||
prop="passwd"
|
prop="passwd"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<el-menu class="top-menu" :default-active="activeIndex" mode="horizontal" text-color="#333">
|
<el-menu class="top-menu" :default-active="activeIndex" mode="horizontal" text-color="#333">
|
||||||
<el-menu-item index="0" @click="openHome">
|
<el-menu-item index="0" @click="openHome">
|
||||||
<template #title>
|
<template #title>
|
||||||
<i :class="itemHome.source" style="padding-right: 5px"></i>
|
<i v-if="itemHome.source" :class="itemHome.source" style="padding-right: 5px"></i>
|
||||||
<span>{{ itemHome.name }}</span>
|
<span>{{ itemHome.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<template v-for="(item, index) in items" :key="index">
|
<template v-for="(item, index) in items" :key="index">
|
||||||
<el-menu-item :index="item.id + ''" @click="openMenu(item)">
|
<el-menu-item :index="item.id + ''" @click="openMenu(item)">
|
||||||
<template #title>
|
<template #title>
|
||||||
<i :class="item.source" style="padding-right: 5px"></i>
|
<i v-if="item.source" :class="item.source" style="padding-right: 5px"></i>
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ item.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
@select="handleSelect"
|
@select="handleSelect"
|
||||||
>
|
>
|
||||||
<template #="{ item }">
|
<template #="{ item }">
|
||||||
<i :class="[item[iconKey], 'icon']"></i>
|
<i v-if="item[iconKey]" :class="[item[iconKey], 'icon']"></i>
|
||||||
<div class="name">{{ item[labelKey] }}</div>
|
<div class="name">{{ item[labelKey] }}</div>
|
||||||
<div class="addr">{{ item[pathKey] }}</div>
|
<div class="addr">{{ item[pathKey] }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -10,8 +10,10 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<span>
|
<span class="top-theme-icon" @click="open">
|
||||||
<i class="icon-zhuti" @click="open"></i>
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M7 3l3 3h4l3-3 4 4-3 2v11a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V9L3 7l4-4z" />
|
||||||
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -116,4 +118,44 @@ export default {
|
|||||||
.list {
|
.list {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-theme-icon {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
vertical-align: middle;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
margin: auto;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f2f3f5;
|
||||||
|
transform: scale(0.6);
|
||||||
|
opacity: 0;
|
||||||
|
transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover::before,
|
||||||
|
&:focus-visible::before {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ RouterPlugin.install = function (option = {}) {
|
|||||||
export const formatPath = (ele, first) => {
|
export const formatPath = (ele, first) => {
|
||||||
const propsDefault = website.menu;
|
const propsDefault = website.menu;
|
||||||
const icon = ele[propsDefault.icon];
|
const icon = ele[propsDefault.icon];
|
||||||
ele[propsDefault.icon] = !icon ? propsDefault.iconDefault : icon;
|
ele[propsDefault.icon] = icon || '';
|
||||||
ele.meta = {
|
ele.meta = {
|
||||||
keepAlive: ele.isOpen === 2,
|
keepAlive: ele.isOpen === 2,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import { setStore, getStore, removeStore } from 'utils/store';
|
import { setStore, getStore, removeStore } from 'utils/store';
|
||||||
import website from '@/config/website';
|
import website from '@/config/website';
|
||||||
|
|
||||||
|
const DEFAULT_PRIMARY_COLOR = '#409eff';
|
||||||
|
const LEGACY_PRIMARY_COLORS = ['#2C77F1', '#5C9DF8'];
|
||||||
|
const storedColorName = getStore({ name: 'colorName' });
|
||||||
|
|
||||||
const common = {
|
const common = {
|
||||||
state: {
|
state: {
|
||||||
language: getStore({ name: 'language' }) || 'zh-cn',
|
language: getStore({ name: 'language' }) || 'zh-cn',
|
||||||
@@ -10,8 +14,11 @@ const common = {
|
|||||||
isSearch: false,
|
isSearch: false,
|
||||||
isRefresh: true,
|
isRefresh: true,
|
||||||
isLock: getStore({ name: 'isLock' }),
|
isLock: getStore({ name: 'isLock' }),
|
||||||
colorName: getStore({ name: 'colorName' }) || '#2C77F1',
|
colorName:
|
||||||
themeName: getStore({ name: 'themeName' }) || 'theme-go',
|
!storedColorName || LEGACY_PRIMARY_COLORS.includes(String(storedColorName).toUpperCase())
|
||||||
|
? DEFAULT_PRIMARY_COLOR
|
||||||
|
: storedColorName,
|
||||||
|
themeName: getStore({ name: 'themeName' }) || 'theme-d2',
|
||||||
lockPasswd: getStore({ name: 'lockPasswd' }) || '',
|
lockPasswd: getStore({ name: 'lockPasswd' }) || '',
|
||||||
website: website,
|
website: website,
|
||||||
setting: website.setting,
|
setting: website.setting,
|
||||||
|
|||||||