Compare commits

..

70 Commits

Author SHA1 Message Date
5aefa23f50 fix(system): 修复部门管理操作列错位问题并统一客商档案弹窗风格
- 修复/system/dept页面操作列竖排错位问题,通过提升CSS选择器特异性并强制inline-flex布局
- 在department页面添加scoped样式,双保险保证操作列横排显示及间距正确
- 将客商档案/vehicle/customer-archive中的表单分组和弹窗内容统一改为section-card组件风格
- 清理废弃旧样式类,提升界面一致性及可维护性
- 调整相关弹窗中卡片内容结构,消除双层灰色背景,使弹窗风格与/business/project-apply一致
- 对评分、联系人、收款信息、发票信息、客商材料、变更记录和证明材料等模块使用全局section-card组件包裹
- 优化样式细节,确保按钮组进入卡头右侧,保证操作体验一致
- 验证构建成功及热更新生效,提醒用户发布需清除旧CSS缓存
2026-08-07 12:47:19 +08:00
c92d2a405a style(ui): 统一操作列文字字重和全站表格文字溢出提示
- 取消操作列内 el-link 默认加粗,统一为常规字体粗细,避免字体显得突兀
- 在 element-ui.scss 中新增样式覆盖 el-link 的 font-weight 为 normal
- 全站表格开启 Element Plus 全局配置 showOverflowTooltip,统一显示单元格文字省略提示
- Avue 全局 crudOption 和手写表格均启用 showOverflowTooltip,覆盖所有相关表格列
- 通过 CSS 豁免操作列单元格不受 tooltip 固定宽度裁切影响,保证操作列内部链接显示完整
- 调整部分菜单宽度以适配视觉和布局需求
- 验证构建成功,无新增 CSS 警告,确保兼容性和功能正常
2026-08-07 12:24:17 +08:00
be4ccc89f6 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/views/system/dept.vue
2026-08-07 12:02:41 +08:00
565553b3f7 refactor(table): 统一调整全仓表格操作列宽度及按钮样式
- 将所有操作按钮数量≤3的表格操作列宽度统一调整为180px
- 调整涉及全局默认值、各模块和页面中menuWidth显式设定
- 单独修改/authority/role页面操作列宽度为240px,/system/menu及流程配置对应调为220px
- 通过CSS新规则视觉统一Avue内置操作按钮为el-link链接样式,无功能变更
- 优化通知公告操作列宽度,解决三按钮链接换行问题
- 调整首页Logo图标尺寸及边距以适配设计需求
- 保证所有相关改动经过npm run build验证通过
2026-08-07 12:02:29 +08:00
52d4b6b486 Merge remote-tracking branch 'websoft/master'
# Conflicts:
#	src/option/transportCapacity/transport-ship.js
#	src/option/transportCapacity/transport-vehicle.js
2026-08-07 08:28:42 +08:00
6a02e9126b 1、车船模块fix bug
2、运力模块fix bug
3、新增设备台账
4、其他bug 修复
5、调整组织、人员模块
2026-08-07 08:28:21 +08:00
6364b593ce style(business): 优化派遣摘要及路线项布局样式
- 调整派遣摘要网格列宽,改善整体布局比例
- 增加派遣路线容器间距,提升视觉分隔效果
- 修改派遣路线项最大宽度和内边距,提升内容展示空间
- 添加派遣路线项最小高度及虚线边框,增强区块感和可视性
- 调整派遣路线项边角圆角,优化界面圆润度
2026-08-07 01:41:43 +08:00
bb580b2bfc style(business): 优化派遣摘要及路线项布局样式
- 调整派遣摘要网格列宽,改善整体布局比例
- 增加派遣路线容器间距,提升视觉分隔效果
- 修改派遣路线项最大宽度和内边距,提升内容展示空间
- 添加派遣路线项最小高度及虚线边框,增强区块感和可视性
- 调整派遣路线项边角圆角,优化界面圆润度
2026-08-07 01:41:35 +08:00
6c91889e33 style(business): 优化调度路线组件样式及结构调整
- 用车辆图标替换调度路线横线,提升视觉表现
- 调整调度路线布局,使用 grid 增强对齐和间距控制
- 修改调度路线节点样式,统一圆形背景和阴影效果
- 优化标题、地址、联系人文本样式,增加省略号和颜色区分
- 调整调度路线图标容器样式,增加边框和柔和阴影
- 使用伪元素实现两侧虚线提醒,增强组件连接感
2026-08-07 01:29:32 +08:00
4bef3430e0 refactor(business): 优化派车信息展示和样式布局
- 将基本信息部分整体包裹在section-card内并调整布局顺序
- 调整收发货路线结构,合并地址和联系人信息至路线节点内
- 使用CSS grid替代部分flex布局,优化网格间距和对齐
- 更新文字换行和溢出处理,增强可读性
- 删除冗余的收发货路线详细信息区域,精简代码结构
- 统一section-card的样式和内部内容伸缩布局
- 调整附件显示方式,保证链接样式一致性
2026-08-07 01:21:46 +08:00
17d12d279d refactor(business): 优化派车信息展示和样式布局
- 将基本信息部分整体包裹在section-card内并调整布局顺序
- 调整收发货路线结构,合并地址和联系人信息至路线节点内
- 使用CSS grid替代部分flex布局,优化网格间距和对齐
- 更新文字换行和溢出处理,增强可读性
- 删除冗余的收发货路线详细信息区域,精简代码结构
- 统一section-card的样式和内部内容伸缩布局
- 调整附件显示方式,保证链接样式一致性
2026-08-07 01:03:29 +08:00
9cf005cece refactor(business): 优化派车信息展示和样式布局
- 将基本信息部分整体包裹在section-card内并调整布局顺序
- 调整收发货路线结构,合并地址和联系人信息至路线节点内
- 使用CSS grid替代部分flex布局,优化网格间距和对齐
- 更新文字换行和溢出处理,增强可读性
- 删除冗余的收发货路线详细信息区域,精简代码结构
- 统一section-card的样式和内部内容伸缩布局
- 调整附件显示方式,保证链接样式一致性
2026-08-07 00:54:19 +08:00
d8db9b1edd feat(table): 调整表格操作列宽度并统一文字链接间距
- /business/project-apply 主表操作列宽度固定为 220,移除 applyTableMenuWidth 调用
- /business/temporary-credit-limit 通过传入 menuWidth prop 固定操作列宽度为 180
- /base/common-address 操作列宽度由 220 降至 180
- /business/process-config 操作列宽度由 320 调整为 180,修复末尾语法错误
- /vehicle/insurance-record 操作列宽度先降至 140 后改回 160,后全部车/船务管理模块记录页统一为 180
- 多个车/船务管理模块相关 option 文件及 vue 文件操作列宽统调为 180
- 新增 business-crud-page 组件 menuWidth prop,支持外部传值控制操作列宽度
- 全站操作列文字链接去除 el-link 默认 margin,避免和 gap 叠加导致文字间距过宽
- 优化操作列按钮过多时自动换行展示逻辑,确保按钮不被裁切
2026-08-07 00:44:26 +08:00
cf04d48010 feat(table): 调整表格操作列宽度并统一文字链接间距
- /business/project-apply 主表操作列宽度固定为 220,移除 applyTableMenuWidth 调用
- /business/temporary-credit-limit 通过传入 menuWidth prop 固定操作列宽度为 180
- /base/common-address 操作列宽度由 220 降至 180
- /business/process-config 操作列宽度由 320 调整为 180,修复末尾语法错误
- /vehicle/insurance-record 操作列宽度先降至 140 后改回 160,后全部车/船务管理模块记录页统一为 180
- 多个车/船务管理模块相关 option 文件及 vue 文件操作列宽统调为 180
- 新增 business-crud-page 组件 menuWidth prop,支持外部传值控制操作列宽度
- 全站操作列文字链接去除 el-link 默认 margin,避免和 gap 叠加导致文字间距过宽
- 优化操作列按钮过多时自动换行展示逻辑,确保按钮不被裁切
2026-08-06 23:55:30 +08:00
454608d7be feat(dispatch): 优化运输计划调度弹窗视觉布局并提升紧凑度
- 弹窗标题和单号合并一行,移除分隔符,提升信息整体感
- 基本信息和收发货路线由左右双列改为上下堆叠,改善视觉层次
- 基本信息网格调整为4列布局,货物信息扩大占2列,附件独占一行
- 计划执行时间范围由‘-’改为‘ ~ ’,更清晰表达时间区间
- 路线节点展示改为横向徽章加下方双列详细信息,避免空白和居中留白
- 调整字体大小、颜色及间距,整体风格更简洁且信息更紧凑
- 移除无用边距和min-height约束,使弹窗整体更加紧凑精简
- 更新代理配置,开发期/api请求代理指向指定内网地址,统一路径无需重写,
  以解决跨域问题并保持与后端网关路径一致
- 进行了完整构建验证,确保修改不会影响现有功能稳定性
2026-08-06 23:10:06 +08:00
d82d06dc78 feat(dispatch): 优化运输计划调度弹窗视觉布局并提升紧凑度
- 弹窗标题和单号合并一行,移除分隔符,提升信息整体感
- 基本信息和收发货路线由左右双列改为上下堆叠,改善视觉层次
- 基本信息网格调整为4列布局,货物信息扩大占2列,附件独占一行
- 计划执行时间范围由‘-’改为‘ ~ ’,更清晰表达时间区间
- 路线节点展示改为横向徽章加下方双列详细信息,避免空白和居中留白
- 调整字体大小、颜色及间距,整体风格更简洁且信息更紧凑
- 移除无用边距和min-height约束,使弹窗整体更加紧凑精简
- 更新代理配置,开发期/api请求代理指向指定内网地址,统一路径无需重写,
  以解决跨域问题并保持与后端网关路径一致
- 进行了完整构建验证,确保修改不会影响现有功能稳定性
2026-08-06 23:06:45 +08:00
f03f764472 feat(dispatch): 优化运输计划调度弹窗视觉布局并提升紧凑度
- 弹窗标题和单号合并一行,移除分隔符,提升信息整体感
- 基本信息和收发货路线由左右双列改为上下堆叠,改善视觉层次
- 基本信息网格调整为4列布局,货物信息扩大占2列,附件独占一行
- 计划执行时间范围由‘-’改为‘ ~ ’,更清晰表达时间区间
- 路线节点展示改为横向徽章加下方双列详细信息,避免空白和居中留白
- 调整字体大小、颜色及间距,整体风格更简洁且信息更紧凑
- 移除无用边距和min-height约束,使弹窗整体更加紧凑精简
- 更新代理配置,开发期/api请求代理指向指定内网地址,统一路径无需重写,
  以解决跨域问题并保持与后端网关路径一致
- 进行了完整构建验证,确保修改不会影响现有功能稳定性
2026-08-06 19:53:34 +08:00
1e4de76978 Merge remote-tracking branch 'websoft/master'
# Conflicts:
#	src/option/business/process-config.js
#	src/views/business/process-config.vue
#	src/views/vehicle/customer-archive.vue
2026-08-06 17:41:03 +08:00
e6d4edf362 项目、合同fix 2026-08-06 17:40:03 +08:00
1862115e1d feat(business-crud-page): 优化运输计划调度弹窗UI与交互体验
- 使用全局<section-card>组件重构调度弹窗三块分区,提升视觉一致性
- 将弹窗灰底设置为#f5f6fa,调整padding及溢出滚动,增强弹窗内容可读性
- 收发货路线样式由黑实线改为主色号虚线并添加箭头,增强方向感
- 待调度列表纳入白卡容器,新增按钮及汇总文字移入列表卡extra slot
- 操作列宽度由180调整至220,预留扩展空间
- 增加分隔线和间距分割调度表底部区域,优化布局层次
2026-08-06 17:39:04 +08:00
49236cad56 style(ui): 调整对话框宽度以优化界面布局
- 将driver.vue中driver-dialog宽度从92%调整为90%
- 将process-config.vue中process-config-dialog宽度从1440px调整为70%
- 保持对话框顶部间距和关闭事件不变
2026-08-06 16:59:34 +08:00
02b2e3b673 refactor(transportCapacity): 使用 section-card 重构司机管理弹窗布局
- 将司机管理页面新增/编辑弹窗中四个分组改为使用标准 section-card 组件包裹
- 删除手写的扁平样式和红色竖条,统一使用全局 element-ui 样式维护弹窗视觉风格
- 调整司机证件上传区尺寸为 240x151 px,保持身份证比例并左对齐显示
- 优化弹窗中各表单项布局,提高视觉层次与一致性
- 更新 scoped 样式,移除无用的 section-title 样式,保持代码清洁
2026-08-06 16:53:23 +08:00
53676a1150 refactor(vehicle): 优化customer-archive弹窗结构与样式
- 使用<section-card>替换旧版灰底分组块与内层白卡,统一表单分组样式
- 删除冗余的基本信息大标题,减少嵌套层级
- 将客商材料和变更记录区域改用<section-card>,操作按钮通过插槽放置卡头右侧
- 清理无效的scoped样式,简化样式管理
- 统一弹窗内部灰底背景并增加16px内边距,与project-apply保持一致
- 确认vue文件与sass编译无误,保证改动稳定性
2026-08-06 15:09:44 +08:00
5e92124710 Merge remote-tracking branch 'websoft/master' 2026-08-06 11:52:14 +08:00
8a262d9d41 style(ui): 统一弹窗分组白卡样式并改造相关弹窗布局
- 新增全局弹窗灰底背景色,提升视觉一致性
- 新增通用分组白卡组件 section-card,标题融入卡头,支持额外插槽
- 统一 Avue 弹窗表单及分组为白卡样式
- 调整 common-route.vue 弹窗,使用 section-card 分组包裹查询条件与常用地址
- 改造 loading-manage.vue 弹窗所有分区,采用 section-card 统一风格
- 全局样式调整弹窗内容区表单项间距及两列表单布局工具类
- 在 main.js 全局注册 section-card 组件,便于项目统一复用
2026-08-06 09:27:49 +08:00
badfed7ff1 Merge remote-tracking branch 'websoft/master' 2026-08-06 02:57:58 +08:00
c339852e04 1、基础数据修复bug
2、客商模块修复bug
2026-08-06 02:57:55 +08:00
819a59e6fc style(project-apply): 调整项目申请样式优化布局
- 将项目申请表单内边距改为0取消左右填充
- 修改弹窗主体溢出控制,新增横向溢出隐藏设置
- 调整弹窗主体内边距为16px统一四周间距
- 设置弹窗背景色为浅灰色提升视觉一致性
2026-08-05 21:13:38 +08:00
f663098b4a style(project-apply): 调整项目申请样式优化布局
- 将项目申请表单内边距改为0取消左右填充
- 修改弹窗主体溢出控制,新增横向溢出隐藏设置
- 调整弹窗主体内边距为16px统一四周间距
- 设置弹窗背景色为浅灰色提升视觉一致性
2026-08-05 21:11:35 +08:00
ef417a0290 style(ui): 优化分页箭头及project-apply弹窗样式
- 撤销分页中“上一页/下一页”按钮隐藏,恢复原生箭头图标显示
- 重新删除element-ui.scss中多余的分页箭头文字注入和display:none规则
- 全局Avue CRUD弹窗内容区背景改为灰色 #f5f6fa,提升视觉层次感
- project-apply弹窗背景改为灰色底,分组区块改为白色卡片风格,统一界面风格
- 分区标题与内容区域合并为单张白色卡片,调整圆角和阴影实现视觉统一
- 相应区域内边距、圆角和阴影细节优化,保持结构和功能不变
2026-08-05 20:53:48 +08:00
e5a7aca09e style(vehicle): 移除红色背景样式以优化界面显示
- 删除了 .archive-dialog 的红色背景色定义
- 保留了弹窗主体的最大高度和滚动样式
- 改善了归档对话框的视觉效果和用户体验
2026-08-05 18:25:24 +08:00
4d0cc2d595 feat(customer-archive): 优化客商档案弹窗基本信息分组UI
- 将单一el-row拆分为工商信息、联系信息、财务/信用信息、其他信息四个分组
- 每个分组外层使用灰色背景块,内层字段区为白底卡片,提升视觉层次感
- 字段顺序重新调整,保留全部字段并优化布局,联系信息三项均分一行
- 新增.archive-form__group样式,定义背景色、圆角、内外边距及阴影效果
- 复用全局.dialog-section-title样式作为分组标题样式,保持风格统一
- 确保表单校验正常,vue/compiler-sfc解析无错误,标签闭合平衡
- 在项目长期记忆新增设计约定,明确弹窗字段分组的UI方案及理由
2026-08-05 18:05:07 +08:00
f6451643e8 Merge remote-tracking branch 'origin/master' 2026-08-05 15:55:19 +08:00
8dddb72328 fix(cargo-type): 优化导入失败原因展示格式
- 移除导入失败原因中的“第N行”前缀,简化信息展示
- 失败原因编号从字母改为数字序号,提升可读性
- 备注超长提示编号改为数字编号,保持格式统一
- 保留导入失败原因列标红及列宽自动换行等已有样式调整
2026-08-05 15:55:11 +08:00
fa99cc3eff Merge remote-tracking branch 'websoft/master' 2026-08-05 15:52:31 +08:00
433c611195 1、完善发货模板
2、完善运输计划
3、完善运单管理
2026-08-05 15:52:24 +08:00
6cf535cc79 feat(option): 允许货物类型列支持排序
- 在货物类型的相关列中添加 sortable 属性
- 设置 sortable 为 true 以启用列排序功能
- 适配数据表的展示以支持排序交互
- 保持原有列的宽度和显示配置不变
2026-08-05 15:52:12 +08:00
e683c2cc00 style(pagination): 优化分页组件上一页/下一页样式及环境配置说明
- 取消分页组件中上一页、下一页按钮的额外宽度设置,使其与页码按钮等宽
- 恢复上一页、下一页的原生箭头图标显示,取消自定义文字和隐藏图标的样式规则
- 更新分页相关的注释,明确首页/尾页按钮依旧由脚本控制不注入,上一页/下一页显示原生箭头
- 修改 .env.development 配置,增加 API 代理和跨域说明,避免直接使用绝对地址引发的 CORS 问题
- 优化 VITE_APP_API 配置为 /api,配合 Vite 代理减少跨域错误,保障开发环境稳定运行
2026-08-05 14:35:36 +08:00
3268f12501 style(pagination): 优化分页组件上一页/下一页样式及环境配置说明
- 取消分页组件中上一页、下一页按钮的额外宽度设置,使其与页码按钮等宽
- 恢复上一页、下一页的原生箭头图标显示,取消自定义文字和隐藏图标的样式规则
- 更新分页相关的注释,明确首页/尾页按钮依旧由脚本控制不注入,上一页/下一页显示原生箭头
- 修改 .env.development 配置,增加 API 代理和跨域说明,避免直接使用绝对地址引发的 CORS 问题
- 优化 VITE_APP_API 配置为 /api,配合 Vite 代理减少跨域错误,保障开发环境稳定运行
2026-08-05 14:35:30 +08:00
f9f8221870 1、完善项目
2、完善合同
3、完善费用项
4、司机管理对接OCR
5、完善运输计划
6、完善临时额度
2026-08-04 12:17:49 +08:00
81c98f6ad8 1、完善客商模块
2、完善基础数据模块
3、完善规范
2026-08-01 01:23:13 +08:00
6a4c5d02f4 style(wel): 为容器添加最小高度限制
- 在容器样式中添加了min-height属性,设置最小高度为200px
- 保证容器在内容较少时仍保持一定高度,提升布局稳定性
2026-07-31 23:40:47 +08:00
70856ca44c style(wel): 增加面板等高布局样式优化
- 为图表区左右面板添加flex布局实现等高效果
- 为下方区左右面板添加flex布局实现等高效果
- 在metric-card内添加内容区自动撑满的flex样式
- 优化了.el-col和.panel的布局结构和弹性属性
2026-07-31 20:53:56 +08:00
dd857414c9 style(wel): 增加面板等高布局样式优化
- 为图表区左右面板添加flex布局实现等高效果
- 为下方区左右面板添加flex布局实现等高效果
- 在metric-card内添加内容区自动撑满的flex样式
- 优化了.el-col和.panel的布局结构和弹性属性
2026-07-31 20:52:47 +08:00
4383e9956e style(top-bar): 给顶部状态栏标题区添加背景条以区分视觉层次
- 顶部状态栏 `.top-bar__title` 增加品牌色淡底背景和左侧主色竖条
- 文字颜色调整为深色,保持搜索框可读性
- 调整主题相关样式,处理 light 主题和 dark 主题下背景条效果差异
- 优化多个主题下 Logo 背景和文字颜色,提升整体视觉一致性
- 修改欢迎页背景颜色及相关元素颜色,增强视觉层次感
- 调整部分组件和布局的内边距与边框颜色,提升界面细节表现
- 隐藏顶部主题切换项,调整 hover 背景颜色以适应新视觉风格
2026-07-31 20:50:18 +08:00
79f8fbad1d style(wel-banner): 优化欢迎横幅样式并添加装饰元素
- 调整背景渐变角度和颜色过渡,提高视觉层次感
- 修改边框圆角和内边距,优化整体布局
- 增加横幅装饰元素,包括多个半透明圆和点阵图案
- 使用绝对定位和透明度设置装饰元素,增强视觉细节
- 调整横幅内容区层级,确保装饰元素不影响交互
- 优化阴影效果,使横幅更具立体感
2026-07-31 20:13:45 +08:00
70779fcf63 style(theme): 更新各主题logo及顶部栏样式,统一白底阴影效果
- 所有主题的 avue-logo 背景改为白色,并添加 0 2px 8px rgba(0,0,0,0.06) 阴影效果
- 各主题顶部栏背景及文字颜色调整,提升整体对比度与视觉统一性
- 统一调整下拉菜单、面包屑、图标等元素颜色为 rgba(0,0,0,0.85) 或 0.65,增强易读性
- 修正部分输入框和色彩选择器的边框及背景颜色,增强一致性
- index.html 添加 favicon.ico 作为页面图标
- 新增图标悬停显示浅灰圆形背景效果示例页面 icon-hover-demo.html
- icon-hover-demo.html 包含核心 CSS 代码和 Element Plus 的示例用法,方便复用和参考
2026-07-31 20:01:38 +08:00
71dd52c650 style(theme): 更新各主题logo及顶部栏样式,统一白底阴影效果
- 所有主题的 avue-logo 背景改为白色,并添加 0 2px 8px rgba(0,0,0,0.06) 阴影效果
- 各主题顶部栏背景及文字颜色调整,提升整体对比度与视觉统一性
- 统一调整下拉菜单、面包屑、图标等元素颜色为 rgba(0,0,0,0.85) 或 0.65,增强易读性
- 修正部分输入框和色彩选择器的边框及背景颜色,增强一致性
- index.html 添加 favicon.ico 作为页面图标
- 新增图标悬停显示浅灰圆形背景效果示例页面 icon-hover-demo.html
- icon-hover-demo.html 包含核心 CSS 代码和 Element Plus 的示例用法,方便复用和参考
2026-07-31 19:51:25 +08:00
7f01b119b5 style(theme): 更新各主题logo及顶部栏样式,统一白底阴影效果
- 所有主题的 avue-logo 背景改为白色,并添加 0 2px 8px rgba(0,0,0,0.06) 阴影效果
- 各主题顶部栏背景及文字颜色调整,提升整体对比度与视觉统一性
- 统一调整下拉菜单、面包屑、图标等元素颜色为 rgba(0,0,0,0.85) 或 0.65,增强易读性
- 修正部分输入框和色彩选择器的边框及背景颜色,增强一致性
- index.html 添加 favicon.ico 作为页面图标
- 新增图标悬停显示浅灰圆形背景效果示例页面 icon-hover-demo.html
- icon-hover-demo.html 包含核心 CSS 代码和 Element Plus 的示例用法,方便复用和参考
2026-07-31 19:46:21 +08:00
d1c8786043 style(theme): 更新各主题logo及顶部栏样式,统一白底阴影效果
- 所有主题的 avue-logo 背景改为白色,并添加 0 2px 8px rgba(0,0,0,0.06) 阴影效果
- 各主题顶部栏背景及文字颜色调整,提升整体对比度与视觉统一性
- 统一调整下拉菜单、面包屑、图标等元素颜色为 rgba(0,0,0,0.85) 或 0.65,增强易读性
- 修正部分输入框和色彩选择器的边框及背景颜色,增强一致性
- index.html 添加 favicon.ico 作为页面图标
- 新增图标悬停显示浅灰圆形背景效果示例页面 icon-hover-demo.html
- icon-hover-demo.html 包含核心 CSS 代码和 Element Plus 的示例用法,方便复用和参考
2026-07-31 19:37:12 +08:00
368e027426 style(theme): 更新各主题logo及顶部栏样式,统一白底阴影效果
- 所有主题的 avue-logo 背景改为白色,并添加 0 2px 8px rgba(0,0,0,0.06) 阴影效果
- 各主题顶部栏背景及文字颜色调整,提升整体对比度与视觉统一性
- 统一调整下拉菜单、面包屑、图标等元素颜色为 rgba(0,0,0,0.85) 或 0.65,增强易读性
- 修正部分输入框和色彩选择器的边框及背景颜色,增强一致性
- index.html 添加 favicon.ico 作为页面图标
- 新增图标悬停显示浅灰圆形背景效果示例页面 icon-hover-demo.html
- icon-hover-demo.html 包含核心 CSS 代码和 Element Plus 的示例用法,方便复用和参考
2026-07-31 19:22:05 +08:00
c270258b7b feat(ui): 顶部工具栏隐藏并重设计欢迎页仪表盘
- website.js中新增配置项关闭顶部语言切换、主题切换、日志和设置按钮
- top组件根据配置动态隐藏语言切换和设置按钮,仅保留用户头像下拉
- 默认主题改为浅色theme-d2,需手动切换或清空旧主题存储
- 完全重写欢迎页,移除默认营销内容,设计为TMS-ERP业务仪表盘,使用纯SVG/CSS绘图
- 欢迎页包括用户问候、四个核心指标卡、运单趋势、货物类型分布、运输方式占比、预警提醒和快捷入口
- 快捷入口路径模拟真实路由,需与后端菜单一致
- 对车辆里程录入界面搜索栏做细节调整,添加更合理的搜索字段宽度
- user模块中默认用户头像改为jpg格式图片
- vite配置文件新增多项插件和生产环境下的压缩优化配置
2026-07-31 19:04:57 +08:00
a9fd78b5b9 style(config): 调整多个组件菜单宽度为160
- 统一将多个选项和视图组件的 menuWidth 从180调整为160
- 涉及车辆、机场、权限、系统、工具、流程等多个模块
- 优化界面元素尺寸,使菜单显示更加协调一致
- 修正部分对话框和表格配置,提升用户体验
2026-07-31 18:30:52 +08:00
e799b20428 style(crud): 统一操作列宽度并调整内容左对齐
- 将全站 Avue CRUD 操作列宽度统一修改为 180px,替换原有不同宽度配置
- 修正部分页面菜单宽度从 160、220、250、300、350 等多值变为统一 180
- 新增全局样式,实现操作列内容左对齐,解决内置右对齐不统一问题
- 统一所有“删 除”按钮文本为“删除”,提升文案一致性
- 根据 cargo-type 参考,精简全站操作列宽度,提升界面紧凑度和一致性
- 说明风险:部分按钮较多页面可能出现换行或溢出,需单独处理
2026-07-31 18:28:46 +08:00
638d09b19d style(crud): 统一操作列宽度并调整内容左对齐
- 将全站 Avue CRUD 操作列宽度统一修改为 180px,替换原有不同宽度配置
- 修正部分页面菜单宽度从 160、220、250、300、350 等多值变为统一 180
- 新增全局样式,实现操作列内容左对齐,解决内置右对齐不统一问题
- 统一所有“删 除”按钮文本为“删除”,提升文案一致性
- 根据 cargo-type 参考,精简全站操作列宽度,提升界面紧凑度和一致性
- 说明风险:部分按钮较多页面可能出现换行或溢出,需单独处理
2026-07-31 18:26:44 +08:00
06dc1c64f6 style(global): 统一全站搜索按钮文案及操作栏按钮样式
- 统一修改搜索按钮文案,CRUD搜索栏“搜索”改为“查询”,“清空条件”改为“重置”
- 新增全局CSS,隐藏Avue CRUD操作栏按钮前图标,仅保留文字
- 统一操作栏按钮间距为4px,内边距调整为4px,提升界面紧凑度
- 变更影响全站所有Avue CRUD组件的搜索与操作栏样式与文案,非CRUD场景按钮不受影响
2026-07-31 18:11:38 +08:00
9b7f8db96b refactor(pagination): 全站统一隐藏分页导航按钮
- cargo-type 页面原先通过局部方案隐藏首页/上一页/下一页/尾页按钮,现回退该方案
- 修改 src/utils/pagination.js,删除首页和尾页按钮全局增强器注入逻辑
- 优化 updatePaginationButtons,移除首页/尾页按钮状态更新代码
- 在 src/styles/element-ui.scss 添加全局样式,统一隐藏 el-pagination 组件的上一页和下一页按钮
- 保留跳转按钮功能,确保分页跳转操作可用
- 修改语言文件,将“收缩”文案优化为“收起”以提升用户体验
- 全站所有分页组件仅显示总数、每页大小、页码与跳转,符合统一规范要求
- 如需恢复个别页面导航按钮,需添加更高优先级样式覆盖或单独处理
2026-07-31 17:54:51 +08:00
449719dfe1 refactor(option): 优化货物类型相关字段结构与样式调整
- 删除重复的“上级货物类型”相关字段配置,移至更合理位置
- 为部分字段增加隐藏和只读属性,避免误操作
- 注释移除样式中max-width限制,调整宽度显示
- 保持字段校验规则一致性,确保表单验证准确
- 代码格式与结构整理,提升可读性和维护性
2026-07-31 15:39:31 +08:00
81b2a3e99b 1、大量页面调整
2、完善运力模块
3、完善规范、需求卡
2026-07-31 01:32:41 +08:00
ccaca521d3 Merge remote-tracking branch 'websoft/master' 2026-07-31 01:31:44 +08:00
af0675f26b style(cargo-type): 优化表格样式及时间格式展示
- 为部分字段添加溢出显示提示(showOverflowTooltip)
- 修改更新时间和创建时间的格式为“YYYY-MM-DD”
- 调整el-table头部和数据行的内边距,提高视觉一致性
- 将按钮类型由success和danger统一更改为primary,简化按钮样式
2026-07-29 17:26:27 +08:00
89c4f0d4df fix(option): 调整货物类型搜索菜单宽度
- 将搜索菜单的跨度从24调整为10
- 改善搜索菜单在界面中的布局与显示效果
2026-07-29 17:07:05 +08:00
08ec2389a5 style(cargo-type): 调整表格行高及注释部分样式
- 将表格行高从32调整为22以增强紧凑感
- 注释掉表头和数据行的 padding 样式,暂时禁用加高效果
- 注释掉表格容器的高度自适应样式,避免布局异常
- 调整分页组件容器的内边距以优化视觉间距
2026-07-29 17:00:34 +08:00
46d34f489e style(cargo-type): 调整表格行高及注释部分样式
- 将表格行高从32调整为22以增强紧凑感
- 注释掉表头和数据行的 padding 样式,暂时禁用加高效果
- 注释掉表格容器的高度自适应样式,避免布局异常
- 调整分页组件容器的内边距以优化视觉间距
2026-07-29 16:52:14 +08:00
ee84cad033 style(table): 优化表格样式和布局自适应
- 移除 basic-container 内部 el-card 的无效 box-shadow 样式
- 调整表头单元格高度,增加上下内边距至10px
- 保持数据行单元格紧凑,内边距缩小至2px上下
- 改善表格底部空白区域,自适应高度,不再强制填满
- 使表格容器高度自动适应内容尺寸
2026-07-29 16:02:06 +08:00
17df5e8cbe 1、新增预警规则需求卡
2、修复组织结构新增时提示无租户号的bug
2026-07-29 15:42:31 +08:00
780968b68f style(cargo-type): 调整按钮样式及表格行高与单元格内边距
- 将查看按钮类型由 primary 改为 success
- 将删除按钮类型由 primary 改为 danger
- 将表格行高从 44px 调整为 40px
- 调整表格单元格内边距从 6px 变为 1px
2026-07-29 15:12:53 +08:00
de8a87af6c style(cargo-type): 调整搜索栏标签宽度及表格样式
- 将搜索栏标签宽度从80px调整为50px,优化界面布局
- 覆盖Avue内置搜索栏label最小宽度样式
- 设置表格行高为44px,提升内容显示密度
- 调整表格单元格内边距为6px,增强视觉效果
- 维护偶数行背景色和边框颜色不变
2026-07-29 15:02:27 +08:00
ff91e8dbd7 style(base): 调整货物类型搜索栏宽度及样式优化
- 新增 cargo-type 搜索栏标签宽度属性 searchLabelWidth 为 80
- 覆盖搜索栏 label 宽度,缩小至 80px,覆盖 Avue 默认 160px
- 基础容器内 el-card 卡片 body 层 padding 设置为 0
- 调整公共样式中滚动容器的内边距为 8px
- 修正 go.scss 中 avue-tags 左边距,优化标签样式
- 减小 tags.scss 中相关元素的底部外边距至 5px
2026-07-29 12:44:49 +08:00
90d96e01a4 fix(cargo-type): 修复查看编辑弹窗请求未完成问题
- 删除 beforeOpen 中 view/edit 分支的 getDetail 调用,避免请求失败卡死弹窗
- 直接复用已填充的 this.form,提升弹窗打开性能和稳定性
- 调整菜单宽度由 220 改为 160,优化界面布局
- 更新导出逻辑,去除导出时对 ids 的拼接,统一按搜索条件导出
- 隐藏 Avue 内置“新增”按钮,仅保留自定义菜单中新增按钮
2026-07-29 12:20:50 +08:00
209 changed files with 33617 additions and 7212 deletions

View File

@@ -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
#调试参数 #调试参数

View File

@@ -0,0 +1,3 @@
## 2025-07-29
- 货物类型管理页面(cargo-type):搜索栏「类型」和「货物类型编码」字段 searchSpan 从 12 分别调整为 6 和 8收窄 input 宽度使两字段在一排内紧凑展示

View File

@@ -20,3 +20,9 @@
## cargo-type 导出逻辑修复 + 去重新增按钮(本次) ## cargo-type 导出逻辑修复 + 去重新增按钮(本次)
- **导出逻辑**`buildExportParams()` 移除 `ids` 参数拼接,始终按当前搜索条件导出(不再受勾选行影响) - **导出逻辑**`buildExportParams()` 移除 `ids` 参数拼接,始终按当前搜索条件导出(不再受勾选行影响)
- **去重新增按钮**Avue 内置 addBtn 由 `validData(permission, false)` 改为 `false`,隐藏内置"新增"按钮;仅保留 `menu-left` 插槽中带图标的"新增"按钮 - **去重新增按钮**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` 的 importapi 文件中的导出保留勿删)。
- **副作用消除**:查看/编辑不再发 detail 请求,彻底规避该接口失败导致的卡死与报错。若后续确需"打开时拉最新数据",需先排查后端 `/blade-system/cargo-type/detail` 为何报错(网关默认只拦 actuator/healthdetail 不在拦截名单)。

View 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-typemenuWidth: 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) ⑤ 运输方式占比(横向条) ⑥ 预警提醒列表 ⑦ 快捷入口网格(跳真实路由)
- **数据**: 全 mockdata() 中每项标注对应后端接口(如 /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 主题单独覆盖。

View 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-jsmanaged 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 变主色,禁用态灰显。

View 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`,每个分组区域用白色卡片
- 改动:
- 弹窗 bodyglobal 选择器):加 `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()` 排除材料标题避免破坏既有布局

View File

@@ -0,0 +1,116 @@
# 2026-08-06 工作日志
## 全站表格操作列文字链接统一为蓝色
- 需求:客户档案页(/vehicle/customer-archive操作列颜色统一蓝色且全站统一风格。
- 实现:在 `src/styles/element-ui.scss` 新增全局规则,覆盖 Avue `#menu` 槽位(`.avue-crud__menu .el-link`)与手写表格操作列(`.el-table .el-table__body .cell:has(.el-link) .el-link`)中所有 `el-link``--el-link-text-color` / hover / active / disabled 变量为主色 `#409eff` 及其浅/深色,从而把 warning/success/danger 等类型强制转蓝。
- 单点生效,无需逐页改 `type`。dev server(2888) 已运行会热更新。
- 注意:选择器以「表格体内含 el-link 的单元格」为目标,本仓库表格内 el-link 仅用于操作列,无副作用;若未来某数据单元格用 el-link 作强调色需另行排除。
## 运输计划调度弹窗 UX 分析
- 完成 `/business/transport-plan` 调度弹窗的 UX 审查,对比 project-apply 页面风格
- 输出 6 项改进方案P0-P5核心问题为缺少灰底(#f5f6fa)+白卡(section-card)分组设计模式
- 所有改动集中在 `business-crud-page.vue` 一个文件
- 待用户确认后实施第一阶段P0灰底 + P1白卡分组
## 已实施的改进(全部在 business-crud-page.vue
- P0: `__dispatch-dialog``.el-dialog__body` 改为 `padding:16px; background:#f5f6fa; overflow-y:auto`(原 padding:0
- P1: 调度弹窗三块分区用全局 `<section-card>` 包裹:基本信息 / 收发货路线 / 待调度列表;"新增"按钮+汇总文字移入列表卡 `#extra` slot
- P2: `__dispatch-route-line` 由黑色实线改为 `#409EFF` 虚线 + 箭头(主色方向感)
- P3: 待调度列表纳入白卡容器(随 P1 完成)
- P4: 调度表操作列 `width` 180→220 预留扩展
- P5: `__dispatch-footer` 增加 `border-top` + padding/margin-top 分隔
-`__dispatch-list` / `__dispatch-top`(border-bottom/32px padding) 样式已清理section-card 已全局注册,无需 import
- 验证SFC 模板单独编译通过6 处 section-card 引用配对平衡);完整 vite build 仍因预存 `xlsx` 幽灵依赖pnpm 未装)失败,与本次改动无关
- 注意:本项目完整 build 依赖 `xlsx@0.18.5`package.json 有声明但 node_modules 缺失),属环境预存问题,非本次引入
## 运输计划调度弹窗二次视觉紧凑化
- 客户反馈:弹窗“空、不紧凑、内容多但不好看”
- 改动仍集中在 `business-crud-page.vue`
- 模板:
- 标题与单号/状态标签合并到同一行,移除 `|` 分隔符
- 基本信息与收发货路线由左右双列改为上下堆叠的白卡,各自独占一行
- 基本信息网格改为 4 列:客户 / 项目 / 合同编号 / 计划执行时间;货物信息占 2 列;附件独占一行
- 日期展示由 `-` 改为 ` ~ `,更明确是区间
- 路线改为“横向节点 + 下方双列明细”:起点/终点徽章+名称居中,发货地址/收货地址左对齐分两列,避免居中留白
- 样式:
- 顶部标题字号 22px→18px顶部 padding 22px→0
- 信息标签字号 14px→12px、颜色 #666#909399,值行高 1.45→1.4
- 基本信息网格 3 列/48px 列间距/18px 行间距 → 4 列/24px 列间距/12px 行间距
- 路线徽章 46px→32px、字号 16px→13px、圆角 6px→4px
- 路线标题字号 22px→16px取消居中最长名称省略
- 路线区域取消 `min-height:200px` 和居中,改为紧凑堆叠
- 卡片间统一 `margin-bottom: 12px`
- 验证:`npm run build` 成功
## /business/project-apply 主表操作列收窄
- 需求project-apply 主表avue-crud #menu)操作列太宽,缩小一点。
- 原:`buildTableOption()` 调用 `applyTableMenuWidth(option, 4)` → 强制 `menuWidth: 320`four 档因按钮数≥4。
- 改动:`src/views/business/project-apply.vue``buildTableOption()` 改为直接返回对象并显式设 `menuWidth: 220`,移除 `applyTableMenuWidth` 调用及对应 import仅本文件使用
- 说明220 低于 AGENTS.md「>3 按钮≥320px」约定但属用户明确要求操作列链接已全局支持 flex-wrap按钮多时会自动换行不会裁切。
- 影响范围:仅 project-apply 主表;子表(附件/变更/用户权限)操作列 width 维持 110/100/100 不变;全局 `TABLE_MENU_WIDTH` 未改。
## /business/temporary-credit-limit 操作列宽度固定为 180
- 需求:该页操作列宽度也给 180。
- 背景:该页用共享组件 `business-crud-page.vue`,其 `option` 在 data() 中由 `cloneOption(crudOption, estimateMenuButtonCount(config))` 生成菜单宽度按按钮数估算≥4 按钮→320option 文件本身无 menuWidth。
- 改动:
1. `business-crud-page.vue` 新增可选 prop `menuWidth`Number默认 nulldata() 中生成 `option` 时若 `menuWidth != null` 则强制覆盖 `opt.menuWidth`。默认 null 不影响其他页面。
2. `temporary-credit-limit.vue` 调用处加 `:menu-width="180"`
- 复用提示:后续任何使用 `business-crud-page` 的页面想固定操作列宽度,直接传 `:menu-width="N"` 即可,无需再改 option 或组件逻辑。
- 注意180 同样低于 AGENTS「>3 按钮≥320」约定按用户明确要求链接支持换行兜底。
## /base/common-address 操作列宽度 220 → 180
- 需求:「这个也调一下宽度」。上一条刚把 temporary-credit-limit 设为 180用户用「也」字故对齐为 180。
- 机制:该页是独立 `avue-crud``option` 来自 `@/option/base/common-address.js``createOption()`,其中已显式设 `menuWidth: 220`
- 改动:将 `src/option/base/common-address.js``menuWidth: 220``180`。操作列仅 3 个链接(查看/编辑/删除)。
- 说明:低于 AGENTS「>3 按钮≥320」约定按用户明确要求链接支持换行兜底。
## 操作列宽度的三种设置入口(备忘)
- 独立 avue-crud + 自管 option直接改 option 文件的 `menuWidth`(如 common-address
- 独立 avue-crud + buildTableOption 调 `applyTableMenuWidth(option, N)`helper 会按按钮数强制下限≥4→320要更窄需绕过 helper 直接设 `menuWidth`(如 project-apply 改 220
- 共用 `business-crud-page` 组件:新增可选 prop `menuWidth`(默认 null 不动既有逻辑),调用处传 `:menu-width="N"`(如 temporary-credit-limit 传 180
## /business/process-config 操作列宽度 320 → 180
- 需求:「这个也调一下宽度」。延续上几条把操作列设 180 的系列要求。
- 机制:该页是独立 `avue-crud``option` 来自 `@/option/business/process-config.js`,原先包在 `applyTableMenuWidth({...}, 5)`five 档→强制 `menuWidth: 320`,因菜单有 6 个链接:查看/编辑/复制/启用/停用/删除)。
- 改动:移除 `applyTableMenuWidth` 包裹与对应 importoption 改为普通对象并显式设 `menuWidth: 180`
- 说明180 明显低于 AGENTS「>3 按钮≥320」约定按用户明确要求链接已全局支持 flex-wrap 换行兜底6 个按钮会多行展示、不裁切。
## 修复 process-config.js 末尾语法错误(红色警)
- 现象:用户反馈 `src/option/business/process-config.js` 最后一行有红色警。
- 根因:上一轮把 `applyTableMenuWidth({...}, 5)` 去掉外层函数包裹时,结尾 `}, 5);` 被改成 `});`,多留了一个 `)`(因 `export const option = {` 本身没有左括号),导致括号不匹配。
- 改动:末尾 `});``};`。移除 `applyTableMenuWidth` import 时无误。
- 验证node 动态 import 不再报 SyntaxError仅剩 node 无法解析 extensionless `./common` 的模块解析提示,与语法无关),说明语法已恢复。
## /vehicle/insurance-record 操作列宽度 160 → 140紧凑
- 需求:「这个也调一下宽度,紧凑一点」。本页与上几条不同,用户明确要求更紧凑(其他页给的 180 比这页还宽)。
- 机制:独立 `avue-crud``option` 来自 `@/option/vehicle/insurance-record.js`;无自定义 `#menu` 槽,行菜单用 Avue 内置(仅显式 `viewBtn: true`edit/del 默认开启→3 个链接:查看/编辑/删除)。原已显式 `menuWidth: 160`
- 改动:将 `menuWidth: 160``140`
- 说明:低于 AGENTS「>3 按钮≥320」约定按用户明确要求链接已全局支持 flex-wrap 换行兜底。
## 车/船务管理模块下所有记录页操作列宽度统一为 160
- 需求:用户截图列出「车/船务管理」下 11 个子菜单,要求操作栏宽度都设为 160。
- 对应页面/option 文件:
- 保险记录 insurance-recordoption → `src/option/vehicle/insurance-record.js`(由 140 改回 160
- 违章记录 violation-recordoption → `src/option/vehicle/violation-record.js`(原 160无需改动
- 维修记录 maintenance-recordinline option → `src/views/vehicle/maintenance-record.vue`(原 160无需改动
- 保养记录 maintenance-planinline option → `src/views/vehicle/maintenance-plan.vue`(原 160无需改动
- 换胎记录 tire-replacement-recordoption → `src/option/vehicle/tire-replacement-record.js`(原 160无需改动
- 事故记录 accident-recordoption → `src/option/vehicle/accident-record.js`(原 160无需改动
- 年检记录 annual-inspection-recordoption → `src/option/vehicle/annual-inspection-record.js`(原 160无需改动
- 里程记录 mileage-recordoption → `src/option/vehicle/mileage-record.js`(原 160无需改动
- 变更记录 transport-change-recordoption → `src/option/vehicle/transport-change-record.js`(原 160无需改动
- 油电记录 oil-electric-recordoption → `src/option/vehicle/oil-electric-record.js`(原 160无需改动
- ETC记录 etc-recordoption → `src/option/vehicle/etc-record.js`(原 160无需改动
- 实际改动:仅 `insurance-record.js` 从 140 恢复到 160其余 10 个已经是 160。
- 注意:`src/option/vehicle/other-expense-record.js` 不在截图菜单内,保持不动。
## 车/船务管理模块操作列宽度 160 → 180用户反馈 160 偏小)
- 需求:上一轮统一 160 后,用户觉得还是小,全部改成 180。
- 改动11 个文件 `menuWidth: 160``180`9 个 option 文件 + maintenance-record.vue / maintenance-plan.vue 两处 inline option
- 现状:车/船务管理模块全部 11 个记录页操作列均为 180。
## 操作列文字链接间距过宽问题
- 现象:用户截图反馈操作列文字链接之间间距太宽,要求统一风格。
- 根因:全局已设 `.avue-crud .avue-crud__menu { gap: 8px; }` 与手写表格操作列 `gap: 8px`,但 Avue 默认 `.el-link``.cell` 上可能存在 `margin-right`,与 gap 叠加后显得过宽。
- 改动:`src/styles/element-ui.scss` 新增规则,对 `.avue-crud .avue-crud__menu .el-link` 和手写表格操作列 `.el-link` 强制 `margin: 0`,使间距完全由 8px gap 控制,不再叠加。
- 影响范围全站表格操作列Avue #menu 与手写操作列),仅作用于操作列链接,不修改普通数据单元格。

View File

@@ -0,0 +1,110 @@
# 2026-08-07 工作日志
## 运输计划调度弹窗恢复左右分栏布局
- 需求:客户提供「计划详情」参考截图,要求调度弹窗改回「左侧基本信息卡 + 右侧收发货路线卡」的左右分栏布局。
- 改动:`src/views/business/components/business-crud-page.vue`
- 模板:把基本信息与收发货路线重新包进 `business-crud-page__dispatch-summary` 双列容器;左侧 `section-card` 内恢复 3 列网格(客户/项目/合同编号),货物信息占 2 列、计划执行时间占 1 列、附件独占一行;右侧 `section-card` 内恢复左右排列的起点/终点(徽章+名称+地址+联系人),中间用方向虚线连接。
- 样式:
- 外容器恢复 `grid-template-columns: minmax(0, 1.25fr) minmax(420px, 1fr)`gap 16px卡片等高拉伸。
- 基本信息网格恢复 3 列,列间距 16px、行间距 12px。
- 路线区恢复 `grid-template-columns: 1fr 56px 1fr`,徽章 32px标题 16px地址/联系人 13px连接线 56px。
- 保留紧凑化后的字号/间距(标签 12px、值 14px避免回到原先过松的状态。
- 验证:`npm run build` 成功。
## 运输计划调度弹窗基本信息改为 2 列
- 需求:客户截图反馈左侧「基本信息」还嫌松,要求改为 2 列更紧凑。
- 改动:`src/views/business/components/business-crud-page.vue`
- 模板:调整基本信息字段顺序为 客户/项目、合同编号/计划执行时间、货物信息(占满 2 列)、附件(占满 2 列)。
- 样式:`business-crud-page__dispatch-summary-grid``repeat(3, minmax(0, 1fr))` 改为 `repeat(2, minmax(0, 1fr))`,保持 gap 12px 16px。
- 验证:`npm run build` 成功。
## 运输计划调度弹窗路线连接改为车辆图标
- 需求:客户希望把收发货路线中间的方向虚线换成车辆图标。
- 改动:`src/views/business/components/business-crud-page.vue`
- 模板:把 `<div class="business-crud-page__dispatch-route-line" />` 替换为 `<div class="business-crud-page__dispatch-route-vehicle"><el-icon><Van /></el-icon></div>`
- 样式:删除原 `&__dispatch-route-line` 虚线箭头样式,新增 `&__dispatch-route-vehicle`,使用主色圆形背景、白色 `Van` 图标,尺寸 36×36px居中与路线节点对齐。
- 验证:`npm run build` 成功。
## 运输计划调度弹窗收发货路线视觉美化
- 需求:客户反馈右上角「收发货路线」卡片仍不够美观,要求继续优化。
- 改动:`src/views/business/components/business-crud-page.vue`
- 样式:
- 路线容器去掉 `padding-top`,改为 `align-items: center` 垂直居中。
- 起点/终点 item 改为 `align-items: center`,徽章从方角改为圆形,并加轻微阴影。
- 车辆图标改为白底 + 主色边框 + 主色 `Van` 图标,尺寸加大到 44×44px两侧各延伸 20px 虚线,形成「路线」流动感。
- 城市名称限制单行并溢出省略,地址/联系人间距收紧、颜色变淡。
- 验证:`npm run build` 成功。
## 通知公告 /desk/notice 操作列加宽
- 需求:客户截图反馈操作列中「查看、编辑、删除」三个文字链接被挤成两行,要求加宽。
- 改动:`src/views/desk/notice.vue`
- 在 Avue CRUD option 中新增 `menuWidth: 220`,使操作列可在一行容纳三个操作链接;符合项目样式规范「三个操作按钮时宽度不小于 220px」。
## 全仓表格操作列宽度统一≤3 按钮统一 180
- 需求:客户提供新截图,要求所有操作按钮 ≤3 个的表格操作列统一宽度为 180>3 个按钮保持 320。
- 核心改动:
- `src/utils/table-menu.js``TABLE_MENU_WIDTH``default``three` 都从 160/220 统一改为 180`four` 保持 320`resolveTableMenuWidth` 逻辑不变。
- `src/main.js`:全局 `crudOption.menuWidth` 从 160 改为 180覆盖未显式设置 menuWidth 的 Avue CRUD 页面。
- `src/views/desk/notice.vue``menuWidth` 从 220 改为 180。
- `src/option/business/process-config.js``menuWidth` 从 200 改为 180。
- `src/views/system/param.vue`:手写 el-table 操作列宽度从 220 改为 180。
- 批量替换:对 44 个显式设置 `menuWidth: 160``.vue` / `.js` / `const/*.js` 文件统一改为 180含部分文件内多处
- 验证:`npm run build` 成功exit code 0
## 角色管理 /authority/role 操作列改 180
- 需求:用户明确要求把 /authority/role 页面操作列宽度设为 180该页面此前设为 320因含「查看/编辑/删除 + 权限设置」自定义菜单)。
- 改动:`src/views/authority/role.vue`
- option 内联 `menuWidth: 320` 改为 `menuWidth: 180`
## 全站操作列按钮统一为链接el-link风格
- 需求:用户要求「操作栏里的按钮改成链接的方案,全站风格统一」,并先确认了对功能是否有影响。
- 调研结论(关键):全仓手写 el-table 操作列10 个文件、约 28 列)与 53 个 avue-crud 自定义 `#menu` 插槽**已全部是 `<el-link>`**,全库 `type="text"` 残留为 0真正未链接化的只剩下 **Avue 内置 viewBtn/editBtn/delBtn**(渲染为 `<el-button is-text>`,包在 `div.avue-crud__menu` 内,且自带 `permission` 指令与 `rowView/rowEdit/rowDel` 事件)。
- 实施手法:采用「方案 A纯 CSS 视觉对齐」(零功能影响、不动事件与权限,符合用户「不要影响功能」的诉求)。
- 改动:`src/styles/element-ui.scss`
- 新增 `.avue-crud__menu > .el-button.is-text` 规则,把 Avue 内置行操作按钮外观对齐为 el-link主色文字、无边框/无背景、hover 下划线 + 浅色、禁用态浅色无下划线、`height:auto / padding:0`(配合父级 `inline-flex; gap:8px` 与已存在的主色/间距覆盖规则)。
- 选择器仅命中行操作列 `.avue-crud__menu` 内的 `is-text` 按钮,不误伤顶部工具栏(`.avue-crud__header`)与弹窗按钮(`.avue-crud__dialog__menu`)。
- 注意:现有全局规则 `.avue-crud__menu .el-link` 会强制操作列内所有 el-link`type="danger"` 的删除)显示为主色蓝。如需删除按钮保留红色告警,需单独调整该覆盖规则(本次未改,保持统一蓝)。
- 验证:`npm run build` 成功exit code 0构建日志中的 CSS `*` 告警来自第三方库压缩,与本次无关(历史既有)。
## 操作列文字取消加粗(统一常规字重)
- 需求:用户要求操作栏下的按钮字体都不要加粗,统一风格。
- 根因Element Plus `el-link` 默认 `font-weight: var(--el-font-weight-primary)`500 中等粗),导致操作列里的链接(查看/编辑/删除等)显示为加粗;而 Avue 内置 `is-text` 按钮此前已被规则设为 normal。
- 改动:`src/styles/element-ui.scss`
- 在既有 `.avue-crud__menu .el-link, .el-table ... .cell:has(.el-link) .el-link` 统一规则中增加 `font-weight: normal;`(0,2,0) 优先级高于 el-link 自身 (0,1,0) 的默认字重,可覆盖)。
- 覆盖范围Avue 行菜单内的 el-link + 任意含 el-link 的表格体单元格手写操作列一次统一全站操作列字重Avue 内置 `is-text` 按钮与顶部工具栏/弹窗按钮字重保持原样不受影响。
- 验证:`npm run build` 成功exit code 0
## 全站表格省略文字 hover tooltip 提示统一
- 需求:用户截图反馈合同管理等页面中「所属项目」等列文字被省略,要求像 `/base/common-address` 一样,鼠标移上去显示完整提示;全站统一加,改完列出文件。
- 参考实现:`src/option/base/common-address.js` 中 Avue 列配置使用 `showOverflowTooltip: true`
- 调研结论:全站表格可见列约 848 个Avue+ 424 个手写 `<el-table-column>`,其中 801 个 Avue 列、268 个手写列未开启 tooltip。Element Plus 支持全局 `table: { showOverflowTooltip: true }` 配置Avue 3.9.2 完整透传,可一行代码覆盖全站。
- 改动文件清单:
- `src/main.js`
- Element Plus 全局配置新增 `table: { showOverflowTooltip: true }`,一次性覆盖所有 Avue CRUD 与手写 el-table。
- Avue 全局 `crudOption` 新增 `showOverflowTooltip: true` 作为双保险,避免页面级 option 被错误覆盖时失效。
- `src/styles/element-ui.scss`
- 新增 `.el-table .cell.avue-crud__menu, .el-table .el-table__body .cell.el-tooltip:has(> .el-link)` 规则,豁免操作列单元格的固定宽度与溢出隐藏,防止全局 tooltip 导致操作列内 el-link 换行后被裁切,保持原有 8px gap 与自动换行。
- `src/option/business/common.js`
- 共享工厂函数 `createCrudOption` 新增 `showOverflowTooltip: true`,覆盖 business 模块通过该工厂生成的所有 CRUD option。
- 覆盖范围:全站所有表格可见文本列(含 Avue 与手写 el-table`type="selection"` 选择列由 Element Plus 自动豁免;操作列通过 CSS 豁免不被影响。
- 验证:`npm run build` 成功exit code 0构建日志中 CSS `*` 告警来自第三方库压缩,与本次无关(历史既有)。
## 修复 /system/dept 操作栏错位(链接竖排)
- 现象:用户截图反馈机构管理页操作列「查看 / 编辑 / 删除 / 新增子项」竖排且偏右错位。
- 根因Avue 自带默认样式 `.avue-crud .avue-crud__menu{display:block}`(特异性 0,2,0与项目全局覆盖样式选择器完全相同项目原规则虽带 `!important`,但在 dev 模式 CSS 注入时序或浏览器缓存旧 element-ui.scss 时,`.avue-crud__menu` 退化成 block导致内部按钮/链接竖排。
- 修复:
- `src/styles/element-ui.scss`:把 `.avue-crud .avue-crud__menu` 改为重复类名 `.avue-crud .avue-crud__menu.avue-crud__menu`(特异性升到 0,3,0并新增 `width: 100% !important` 让操作列容器占满单元格、左对齐横排更稳。
- `src/views/system/dept.vue`scoped 样式新增 `:deep(.avue-crud__menu)` 兜底inline-flex + gap 8px + 子元素 inline-flex双保险确保本页操作列横排。
- 验证dev server 已热更新curl 确认两处编译结果均含 `display: inline-flex !important`;构建需用户硬刷新浏览器清旧 CSS 缓存。
## 客商档案 /vehicle/customer-archive 弹窗风格统一为 section-card
- 需求:用户截图反馈弹窗有「双层灰色背景」,且「工商信息」等标题没有放到卡片里面;要求改成和 `/business/project-apply` 一致的白卡风格。
- 根因:原页面主表单使用 `.archive-form__group` 灰色容器,内部再包一层白色 `.el-row` 卡片,标题坐在灰色背景上,形成外层 dialog body 灰 + 分组灰的「双层灰」;客商材料、变更记录、评分材料、发票/邮寄信息也沿用旧的分节标题样式。
- 改动:`src/views/vehicle/customer-archive.vue`
- 主表单 4 个分组改为 `<section-card title="工商信息 / 联系信息 / 财务/信用信息 / 其他信息">` 全局白卡组件,删除外层「基本信息」大标题。
- 评分/联系人/收款/发票 4 个 Tab 内容改为 `<section-card>` + `<template #extra>`,按钮组进入卡头右侧。
- 客商材料改为 `<section-card title="客商材料" #extra>`,变更记录改为 `<section-card title="变更记录">`
- 发票信息弹窗的「发票信息 / 邮寄信息」改为两张 `<section-card>`
- 评分详情弹窗的「证明材料」改为 `<section-card title="证明材料" class="score-material-card">`
- 清理不再使用的样式:`.archive-form__group``.section-title``.section-head``.customer-material-section``.change-record-section``.invoice-form__section-title``.score-material-section` 等。
- 验证:`npm run build` 成功exit code 0

View File

@@ -0,0 +1,66 @@
# 项目长期记忆tms-erp-web-ws / Saber3 客商模块)
## 设计约定(经用户确认的决策)
### 弹窗内多字段表单分组:使用全局 `<section-card>` 组件(项目统一标准)
**整体结构**
- 整个弹窗 body 由 `src/styles/element-ui.scss` 全局 `.el-dialog__body { background: #f5f6fa; padding: 16px }` 统一灰底(无需页面再覆盖)。
- 每个业务分组 = 一张白底卡片。用全局组件 `<section-card title="分组名">...</section-card>`,自动渲染 4px 主色竖条 + 8px 间距的卡头与白底 body圆角 6px + 极淡阴影),与 `loading-manage.vue` / `customer-archive.vue` 等已落地页面一致。
- 严禁再手写 `.xxx-form__block` + `.dialog-section-title` override 拼凑卡片(项目已有 `<section-card>` 标准组件)。
**HTML 结构**(每组三件套):
```vue
<section-card title="分组标题">
<el-row :gutter="18">
<el-col :span="8">...</el-col>
</el-row>
<!-- 同一组的所有 row 都放同一张白卡内 -->
</section-card>
```
**适用**:新增/编辑弹窗中字段超过 ~10 个、需按业务语义分组时。
### 简单分组(仅 3 项)
- 联系信息等仅 3 项的分组,可用 `el-col :span="8"` 让三项均分一行,避免 4 列网格留白。
### 上传证件区域尺寸规范transportCapacity 模块强制)
- **比例**:中国二代身份证标准尺寸 85.6 × 53.98 mm → 宽:高 = **1.586 : 1**(横放)
- **尺寸**:取真实身份证的 ~75% → 固定 **240 × 151 px**1.586:1 精确151 × 1.586 ≈ 240
- **位置**:在 el-col 列内 `margin: 0` 左对齐显示(不再 `width: 100%` 占满整栏,也不再居中)
- **适用范围**:所有 `<image-upload-field large>` 上传区,包括身份证正反面、大头照、机动车行驶证主页正/反面/副页正/反面、道路运输证、机动车登记本、船舶所有权/安全环保/国籍/最低安全配员/光船租赁/营业运输 等所有 cert 图片
- **实现方式**:在每个页面 scoped 样式里覆盖 class-prefix 对应的 `--large` 选择器(`.driver-uploader--large` / `.vehicle-uploader--large` / `.ship-uploader--large`
```scss
:deep(.xxx-uploader) { display: block; } // 不再 width:100%
:deep(.xxx-uploader--large) {
display: block;
width: 240px;
margin: 0;
}
:deep(.xxx-uploader--large .el-upload),
:deep(.xxx-uploader--large.el-upload) {
width: 100%;
height: 151px;
}
```
- **CSS 顺序要点**`.xxx-uploader`(特定性 0,0,1,0必须写在 `.xxx-uploader--large`(同为 0,0,1,0之前源码位置决定覆盖生效。
### 上传图片点击放大预览(全局组件 `image-upload-field` 已实现)
- **组件**`src/components/image-upload-field/main.vue`。原裸 `<img>` 改为 `<el-image :preview-src-list="[value]" fit="contain" preview-teleported :z-index="3000" @click.stop>`。点击图片即全屏预览(滚轮缩放 / 旋转 / 下载),零额外依赖。
- **预览与上传分离**:图片 `@click.stop` 阻止冒泡到 `el-upload`(否则会触发重传);"更换"入口form 模式图片下方 `el-link`、card 模式 head 的 `actionText`)通过 `el-upload` 内部隐藏 `input.el-upload__input` 的 `.click()` 触发文件框。
- **为什么用 DOM click**Element Plus `el-upload` 仅 expose `abort/submit/clearFiles/handleStart/handleRemove`**没有** `openFileDialog`,故用 `this.$refs.uploadRef.$el.querySelector('.el-upload__input').click()`。
- **readonly 模式**:仅渲染 `el-image` 预览,不显示上传入口(查看档案时也能放大看证件)。
- **z-index 注意**:务必 `preview-teleported`(预览层挂 body+ `:z-index="3000"`,否则会被 `el-dialog` 遮罩2000 区间)盖住。
- **适用范围**全仓通用组件driver / vehicle / ship 三个页面自动获得该能力(改动一次组件即可)。
## 关键文件
- 通用分组白卡组件:`src/components/section-card/main.vue`(已全局注册为 `<section-card>`,支持 `title` / `#title` / `#extra` slot
- 弹窗灰底 body + section-card 全局样式:`src/styles/element-ui.scss``.el-dialog__body`、`.section-card { &__header / &__bar / &__title / &__extra / &__body }`)。
- 司机档案弹窗:`src/views/transportCapacity/driver.vue`(手写 `el-form` + `<section-card>` 4 大分组:基础身份信息 / 驾驶证信息 / 从业资格证信息 / 司机联系信息)。
- 车辆档案弹窗:`src/views/transportCapacity/vehicle.vue`(手写 `el-form` + `<section-card>` 2 大分组:基础车辆信息 / 车辆资质图片6 张大图按身份证比例 240×151 左对齐)。
- 船舶档案弹窗:`src/views/transportCapacity/ship.vue`(手写 `el-form` + `<section-card>` 2 大分组:基础船舶信息 / 船舶证书信息;内部 6 张 cert 图片按身份证比例 240×151 左对齐;子证书分段用 `.cert-block` + border-top
- 客商档案弹窗:`src/views/vehicle/customer-archive.vue`(工商信息 / 联系信息 / 财务/信用信息 / 其他信息 等分组也用 `<section-card>`)。
- 项目补录弹窗:`src/views/business/project-apply.vue`(手写 `__grid` / `__table` / `__textarea-list` 同款白卡结构,先于 `<section-card>` 组件化之前落地,可视为视觉参照)。
## 环境注意
- Vite 代理跨域Saber3 axios 开 `withCredentials=true`,直连绝对地址后端须让 CORS `Allow-Origin` 为具体域名(不能用 `*`),否则浏览器拒绝。改 `.env`/`vite.config.mjs` 必须重启 dev。

View File

@@ -167,13 +167,17 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
- 搜索组件需展示轻量阴影,统一使用 `0 2px 8px rgba(0, 0, 0, 0.06)`,不得被局部卡片去样式规则覆盖。 - 搜索组件需展示轻量阴影,统一使用 `0 2px 8px rgba(0, 0, 0, 0.06)`,不得被局部卡片去样式规则覆盖。
- 表格线条颜色需统一使用 `#EFF1F7`,包括表格外边框、单元格分割线和固定列边线。 - 表格线条颜色需统一使用 `#EFF1F7`,包括表格外边框、单元格分割线和固定列边线。
- 表格偶数行需统一使用 `#FAFAFA` 背景色,固定列单元格必须与对应行背景保持一致。 - 表格偶数行需统一使用 `#FAFAFA` 背景色,固定列单元格必须与对应行背景保持一致。
- 表格操作列同时展示“查看、编辑、删除”等三个按钮时,操作列宽度统一不小于 `220px`,禁止出现按钮裁切或显示不全。 - 表格操作列同时展示“查看、编辑、删除”等三个按钮时,操作列宽度统一不小于 `220px`;操作列最大按钮数量超过 3 个时,操作列宽度统一加宽到不小于 `320px`;最大按钮数量超过 4 个时,仍按 `320px` 保持列宽,并从第 5 个按钮开始换行展示,禁止出现按钮裁切或显示不全。
- 表格操作列按钮统一仅展示文字,禁止配置 `icon` / `:icon` 或在操作按钮、操作下拉项中嵌入图标;顶部工具栏按钮不受此条限制。
- 纯文字操作入口统一使用 `<el-link>`,禁止使用带 `text` 属性的 `<el-button>`;提交、确认、上传等具有明确命令语义或需要加载状态的按钮可继续使用 `<el-button>`
- 所有表格操作列中的文字链接统一保持 `8px` 间距操作按钮超过操作列可用宽度时必须自动换行禁止链接连续粘连或被裁切。Avue 自定义 `#menu` 插槽和手写 `el-table-column` 操作列均适用。
- `.avue-crud__header` 顶部间距统一为 `12px` - `.avue-crud__header` 顶部间距统一为 `12px`
- 分页组件整体靠右展示,必须展示接口返回的数据总条数,`X条/页` 的页容量选择器必须放在总条数右侧。 - 分页组件整体靠右展示,必须展示接口返回的数据总条数,`X条/页` 的页容量选择器必须放在总条数右侧。
- `.basic-container__card` 的直接子级 `.el-card__body` 内边距统一去除,保持 `padding: 0` - `.basic-container__card` 的直接子级 `.el-card__body` 内边距统一去除,保持 `padding: 0`
- 所有 CRUD 页面搜索栏需与下方表格拆分为独立区域,两者垂直间距统一为 `8px` - 所有 CRUD 页面搜索栏需与下方表格拆分为独立区域,两者垂直间距统一为 `8px`
- 所有 CRUD 页面搜索栏操作按钮(搜索、清空等)需在搜索表单下方独占一行并放置在最右侧;搜索条件超过行时必须显示“展开/折叠”,默认折叠且仅展示行搜索条件。 - 所有 CRUD 页面搜索栏操作按钮(搜索、清空等)需在搜索表单下方独占一行并放置在最右侧;搜索条件超过行时必须显示“展开/折叠”,默认折叠且仅展示行搜索条件;一行布局默认展示 4 个筛选项Avue 配置统一使用 `searchIndex: 4`
- 所有 CRUD 页面中新增、批量导入等顶部按钮组行不需要背景色,应保持透明背景。 - 所有 CRUD 页面中新增、批量导入等顶部按钮组行不需要背景色,应保持透明背景。
- 所有 CRUD 页面顶部工具栏的“新增/新建”主操作按钮统一使用蓝底白字的实心主按钮(`type="primary"` 且不使用 `plain`),视觉标准与“新建运单”一致;批量导入、导出等辅助工具按钮仍使用描边样式。
- 所有 `.basic-container__card` 内的 Avue 内层 `el-card` 需去卡片化,仅保留外层容器卡片样式,禁止出现二级卡片边框、阴影或额外内边距。 - 所有 `.basic-container__card` 内的 Avue 内层 `el-card` 需去卡片化,仅保留外层容器卡片样式,禁止出现二级卡片边框、阴影或额外内边距。
### 4.5 全局注册组件 ### 4.5 全局注册组件
@@ -213,6 +217,20 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
- 表格的排序默认按照创建时间降序;分页列表应由后端默认按 `create_time DESC` 返回,前端不得在无明确业务要求时覆盖为其它默认排序。 - 表格的排序默认按照创建时间降序;分页列表应由后端默认按 `create_time DESC` 返回,前端不得在无明确业务要求时覆盖为其它默认排序。
### 4.11 搜索顺序规范
- 当用户已明确列出筛选字段时,搜索栏必须严格按照用户给出的字段清单和顺序展示;不得自行新增、保留、推断或迁移未列出的筛选项。
- 新增/编辑表单字段、表格列字段和搜索筛选字段必须分开理解;除非用户明确要求同步,禁止把表单字段或表格字段擅自加入搜索栏。
- Avue 搜索栏的字段展示顺序按 `searchOrder` **倒序** 渲染,配置时数值越大越靠前。
### 4.12 日期区间搜索规范
- 当同一业务维度的筛选条件是开始/结束日期或时间,并且接口按区间查询时,前端搜索栏必须合并为一个 `searchRange: true` 的区间字段展示。
- 区间字段在页面层统一归一化为后端所需的起止参数,禁止同时保留两个独立的“开始/结束”搜索项。
- 若用户已明确要求展示区间样式,必须严格按区间控件实现,不得退回为两个普通日期控件。
- 修改搜索项顺序时必须同步调整 `searchOrder`,不要依赖 `column` 数组前后位置来控制搜索栏顺序。
- `searchIndex: 4` 仅控制首屏展示数量,不影响 `searchOrder` 的优先级。
--- ---
## 5. 新功能开发流程 ## 5. 新功能开发流程

Binary file not shown.

View 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 与人对齐的"单一事实来源",不靠口头交代。**
---
## 三、工程规范如何约束 AIAGENTS.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
View 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">&lt;el-button class="icon-hover-btn" link&gt;
&lt;el-icon size="22"&gt;&lt;Upload /&gt;&lt;/el-icon&gt;
&lt;/el-button&gt;</pre>
</div>
</body>
</html>

View File

@@ -19,6 +19,7 @@
<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" />
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<title>运输板块数字化管理平台</title> <title>运输板块数字化管理平台</title>
</head> </head>

View File

@@ -36,7 +36,8 @@
"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",

71
pnpm-lock.yaml generated
View File

@@ -92,6 +92,9 @@ importers:
vuex: vuex:
specifier: ^4.1.0 specifier: ^4.1.0
version: 4.1.0(vue@3.5.34) version: 4.1.0(vue@3.5.34)
xlsx:
specifier: 0.18.5
version: 0.18.5
devDependencies: devDependencies:
'@vitejs/plugin-vue': '@vitejs/plugin-vue':
specifier: ^5.2.4 specifier: ^5.2.4
@@ -2772,30 +2775,30 @@ snapshots:
dependencies: dependencies:
vue: 3.5.34 vue: 3.5.34
'@wangeditor-next/basic-modules@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3)': '@wangeditor-next/basic-modules@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
dependencies: dependencies:
'@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 4.0.6 dom7: 3.0.0
is-url: 1.2.4 is-url: 1.2.4
lodash.throttle: 4.1.1 lodash.throttle: 4.1.1
nanoid: 5.1.11 nanoid: 3.3.12
slate: 0.123.0 slate: 0.72.8
snabbdom: 3.6.3 snabbdom: 3.6.3
'@wangeditor-next/code-highlight@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(slate@0.123.0)(snabbdom@3.6.3)': '@wangeditor-next/code-highlight@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(slate@0.123.0)(snabbdom@3.6.3)':
dependencies: dependencies:
'@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 4.0.6 dom7: 4.0.6
prismjs: 1.30.0 prismjs: 1.30.0
slate: 0.123.0 slate: 0.123.0
snabbdom: 3.6.3 snabbdom: 3.6.3
'@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3)': '@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
dependencies: dependencies:
'@types/event-emitter': 0.3.5 '@types/event-emitter': 0.3.5
'@uppy/core': 2.3.4 '@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
dom7: 4.0.6 dom7: 3.0.0
event-emitter: 0.3.5 event-emitter: 0.3.5
html-void-elements: 3.0.0 html-void-elements: 3.0.0
i18next: 23.16.8 i18next: 23.16.8
@@ -2806,9 +2809,9 @@ snapshots:
lodash.foreach: 4.5.0 lodash.foreach: 4.5.0
lodash.throttle: 4.1.1 lodash.throttle: 4.1.1
lodash.toarray: 4.4.0 lodash.toarray: 4.4.0
nanoid: 5.1.11 nanoid: 3.3.12
scroll-into-view-if-needed: 3.1.0 scroll-into-view-if-needed: 3.1.0
slate: 0.123.0 slate: 0.72.8
slate-history: 0.115.0(slate@0.123.0) slate-history: 0.115.0(slate@0.123.0)
snabbdom: 3.6.3 snabbdom: 3.6.3
@@ -2816,9 +2819,9 @@ snapshots:
dependencies: dependencies:
'@uppy/core': 2.3.4 '@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor-next/basic-modules': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/basic-modules': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor-next/code-highlight': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/code-highlight': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(slate@0.123.0)(snabbdom@3.6.3)
'@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor-next/list-module': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/list-module': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(slate@0.123.0)(snabbdom@3.6.3)
'@wangeditor-next/table-module': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.debounce@4.0.8)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/table-module': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.debounce@4.0.8)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3)
'@wangeditor-next/upload-image-module': 2.0.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor-next/basic-modules@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.foreach@4.5.0)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/upload-image-module': 2.0.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor-next/basic-modules@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.foreach@4.5.0)(slate@0.123.0)(snabbdom@3.6.3)
@@ -2837,14 +2840,14 @@ snapshots:
'@wangeditor-next/list-module@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(slate@0.123.0)(snabbdom@3.6.3)': '@wangeditor-next/list-module@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(slate@0.123.0)(snabbdom@3.6.3)':
dependencies: dependencies:
'@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 4.0.6 dom7: 4.0.6
slate: 0.123.0 slate: 0.123.0
snabbdom: 3.6.3 snabbdom: 3.6.3
'@wangeditor-next/table-module@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.debounce@4.0.8)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3)': '@wangeditor-next/table-module@2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.debounce@4.0.8)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3)':
dependencies: dependencies:
'@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 4.0.6 dom7: 4.0.6
lodash.debounce: 4.0.8 lodash.debounce: 4.0.8
lodash.throttle: 4.1.1 lodash.throttle: 4.1.1
@@ -2856,8 +2859,8 @@ snapshots:
dependencies: dependencies:
'@uppy/core': 2.3.4 '@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor-next/basic-modules': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/basic-modules': 2.0.0(@wangeditor-next/core@1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 4.0.6 dom7: 4.0.6
lodash.foreach: 4.5.0 lodash.foreach: 4.5.0
slate: 0.123.0 slate: 0.123.0
@@ -2867,36 +2870,36 @@ snapshots:
dependencies: dependencies:
'@uppy/core': 2.3.4 '@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor-next/core': 1.8.0(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 4.0.6 dom7: 4.0.6
nanoid: 5.1.11 nanoid: 5.1.11
slate: 0.123.0 slate: 0.123.0
snabbdom: 3.6.3 snabbdom: 3.6.3
'@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3)': '@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
dependencies: dependencies:
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 4.0.6 dom7: 3.0.0
is-url: 1.2.4 is-url: 1.2.4
lodash.throttle: 4.1.1 lodash.throttle: 4.1.1
nanoid: 5.1.11 nanoid: 3.3.12
slate: 0.123.0 slate: 0.72.8
snabbdom: 3.6.3 snabbdom: 3.6.3
'@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)': '@wangeditor/code-highlight@1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)':
dependencies: dependencies:
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0 dom7: 3.0.0
prismjs: 1.30.0 prismjs: 1.30.0
slate: 0.72.8 slate: 0.72.8
snabbdom: 3.6.3 snabbdom: 3.6.3
'@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3)': '@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
dependencies: dependencies:
'@types/event-emitter': 0.3.5 '@types/event-emitter': 0.3.5
'@uppy/core': 2.3.4 '@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
dom7: 4.0.6 dom7: 3.0.0
event-emitter: 0.3.5 event-emitter: 0.3.5
html-void-elements: 2.0.1 html-void-elements: 2.0.1
i18next: 20.6.1 i18next: 20.6.1
@@ -2908,9 +2911,9 @@ snapshots:
lodash.isequal: 4.5.0 lodash.isequal: 4.5.0
lodash.throttle: 4.1.1 lodash.throttle: 4.1.1
lodash.toarray: 4.4.0 lodash.toarray: 4.4.0
nanoid: 5.1.11 nanoid: 3.3.12
scroll-into-view-if-needed: 2.2.31 scroll-into-view-if-needed: 2.2.31
slate: 0.123.0 slate: 0.72.8
slate-history: 0.66.0(slate@0.72.8) slate-history: 0.66.0(slate@0.72.8)
snabbdom: 3.6.3 snabbdom: 3.6.3
@@ -2923,9 +2926,9 @@ snapshots:
dependencies: dependencies:
'@uppy/core': 2.3.4 '@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3) '@wangeditor/code-highlight': 1.0.3(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3) '@wangeditor/list-module': 1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3) '@wangeditor/table-module': 1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.3) '@wangeditor/upload-image-module': 1.0.2(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(@wangeditor/basic-modules@1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.foreach@4.5.0)(slate@0.72.8)(snabbdom@3.6.3)
@@ -2945,14 +2948,14 @@ snapshots:
'@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)': '@wangeditor/list-module@1.0.5(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(slate@0.72.8)(snabbdom@3.6.3)':
dependencies: dependencies:
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0 dom7: 3.0.0
slate: 0.72.8 slate: 0.72.8
snabbdom: 3.6.3 snabbdom: 3.6.3
'@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)': '@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)':
dependencies: dependencies:
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0 dom7: 3.0.0
lodash.isequal: 4.5.0 lodash.isequal: 4.5.0
lodash.throttle: 4.1.1 lodash.throttle: 4.1.1
@@ -2964,8 +2967,8 @@ snapshots:
dependencies: dependencies:
'@uppy/core': 2.3.4 '@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@4.0.6)(lodash.throttle@4.1.1)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/basic-modules': 1.1.7(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3))(dom7@3.0.0)(lodash.throttle@4.1.1)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0 dom7: 3.0.0
lodash.foreach: 4.5.0 lodash.foreach: 4.5.0
slate: 0.72.8 slate: 0.72.8
@@ -2975,7 +2978,7 @@ snapshots:
dependencies: dependencies:
'@uppy/core': 2.3.4 '@uppy/core': 2.3.4
'@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4) '@uppy/xhr-upload': 2.1.3(@uppy/core@2.3.4)
'@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@4.0.6)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@5.1.11)(slate@0.123.0)(snabbdom@3.6.3) '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.12)(slate@0.72.8)(snabbdom@3.6.3)
dom7: 3.0.0 dom7: 3.0.0
nanoid: 3.3.12 nanoid: 3.3.12
slate: 0.72.8 slate: 0.72.8

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -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,
},
});
};

View File

@@ -82,6 +82,16 @@ export const createCrudApi = baseUrl => ({
}, },
}); });
}, },
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) { reassign(id) {
return request({ return request({
url: `${baseUrl}/reassign`, url: `${baseUrl}/reassign`,

View File

@@ -45,6 +45,13 @@ export const reject = id =>
params: { id }, params: { id },
}); });
export const updateAttachments = row =>
request({
url: `${baseUrl}/update-attachments`,
method: 'post',
data: row,
});
export const withdraw = id => export const withdraw = id =>
request({ request({
url: `${baseUrl}/withdraw`, url: `${baseUrl}/withdraw`,

View 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,
},
});

View File

@@ -51,6 +51,20 @@ export const voidProject = (id, reason) =>
params: { id, reason }, 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) => export const startChange = (id, reason) =>
request({ request({
url: `${baseUrl}/start-change`, url: `${baseUrl}/start-change`,

View File

@@ -1,4 +1,5 @@
import { createCrudApi } from './common'; import { createCrudApi } from './common';
import request from '@/axios';
const api = createCrudApi('/blade-transport/shipping-template'); const api = createCrudApi('/blade-transport/shipping-template');
@@ -7,3 +8,4 @@ export const getDetail = api.getDetail;
export const submit = api.submit; export const submit = api.submit;
export const remove = api.remove; export const remove = api.remove;
export const copy = api.copy; export const copy = api.copy;
export const nextCode = () => request({ url: '/blade-transport/shipping-template/next-code', method: 'get' });

View File

@@ -1,11 +1,38 @@
import { createCrudApi } from './common'; import { createCrudApi } from './common';
import request from '@/axios';
const api = createCrudApi('/blade-transport/transport-plan'); const baseUrl = '/blade-transport/transport-plan';
const api = createCrudApi(baseUrl);
export const getList = api.getList; export const getList = api.getList;
export const getDetail = api.getDetail; export const getDetail = api.getDetail;
export const submit = api.submit; export const submit = api.submit;
export const dispatch = api.dispatch;
export const remove = api.remove; export const remove = api.remove;
export const copy = api.copy; export const copy = api.copy;
export const cancel = api.cancel; export const cancel = api.cancel;
export const complete = api.complete; 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,
});
};

View File

@@ -1,6 +1,8 @@
import request from '@/axios';
import { createCrudApi } from './common'; import { createCrudApi } from './common';
const api = createCrudApi('/blade-transport/waybill-manage'); const baseUrl = '/blade-transport/waybill-manage';
const api = createCrudApi(baseUrl);
export const getList = api.getList; export const getList = api.getList;
export const getDetail = api.getDetail; export const getDetail = api.getDetail;
@@ -11,3 +13,20 @@ export const cancel = api.cancel;
export const reassign = api.reassign; export const reassign = api.reassign;
export const complete = api.complete; export const complete = api.complete;
export const batchComplete = api.batchComplete; 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 });

View File

@@ -1,17 +1,37 @@
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) => { export const importBlob = (url, file) => {

View File

@@ -61,6 +61,13 @@ export const getUser = id => {
}); });
}; };
export const getCustomerOptions = () => {
return request({
url: '/blade-system/user/customer-options',
method: 'get',
});
};
export const getUserPlatform = id => { export const getUserPlatform = id => {
return request({ return request({
url: '/blade-system/user/platform-detail', url: '/blade-system/user/platform-detail',

View File

@@ -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,
});
};

View File

@@ -51,6 +51,14 @@ export const changeStatus = (id, status) => {
}); });
}; };
export const auditCertification = (id, certificationStatus, rejectReason) => {
return request({
url: '/blade-transport/transport-vehicle/audit-certification',
method: 'post',
params: { id, certificationStatus, rejectReason },
});
};
export const getExpiryStat = params => { export const getExpiryStat = params => {
return request({ return request({
url: '/blade-transport/transport-vehicle/expiry-stat', url: '/blade-transport/transport-vehicle/expiry-stat',
@@ -58,3 +66,12 @@ export const getExpiryStat = params => {
params, params,
}); });
}; };
export const recognitionTransportCertificates = objectKeys => {
return request({
url: '/blade-file/file/recognitionTransportCertificates',
method: 'post',
timeout: 60000,
data: objectKeys,
});
};

View File

@@ -40,6 +40,16 @@ export const submitApproval = id => {
}); });
}; };
export const withdrawApproval = id => {
return request({
url: '/blade-transport/customer-archive/withdraw-approval',
method: 'post',
params: {
id,
},
});
};
export const approve = id => { export const approve = id => {
return request({ return request({
url: '/blade-transport/customer-archive/approve', url: '/blade-transport/customer-archive/approve',

View File

@@ -0,0 +1,23 @@
import request from '@/axios';
export const getList = (current, size, params) =>
request({
url: '/blade-transport/equipment-ledger/list',
method: 'get',
params: { ...params, current, size },
});
export const getDetail = id =>
request({ url: '/blade-transport/equipment-ledger/detail', method: 'get', params: { id } });
export const getNextEquipmentCode = () =>
request({ url: '/blade-transport/equipment-ledger/next-equipment-code', method: 'get' });
export const add = row =>
request({ url: '/blade-transport/equipment-ledger/submit', method: 'post', data: row });
export const update = row =>
request({ url: '/blade-transport/equipment-ledger/submit', method: 'post', data: row });
export const remove = ids =>
request({ url: '/blade-transport/equipment-ledger/remove', method: 'post', params: { ids } });

View File

@@ -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 {

View File

@@ -1,5 +1,5 @@
<template> <template>
<div v-if="isEmptyTotal" class="empty-pagination avue-crud__pagination"> <div v-if="shouldShow" class="empty-pagination avue-crud__pagination">
<el-pagination <el-pagination
background background
:current-page="page.currentPage" :current-page="page.currentPage"
@@ -21,9 +21,16 @@ export default {
type: Object, type: Object,
required: true, required: true,
}, },
alwaysShow: {
type: Boolean,
default: false,
},
}, },
emits: ['size-change', 'current-change', 'load'], emits: ['size-change', 'current-change', 'load'],
computed: { computed: {
shouldShow() {
return this.alwaysShow || this.isEmptyTotal;
},
isEmptyTotal() { isEmptyTotal() {
return Number(this.page.total || 0) === 0; return Number(this.page.total || 0) === 0;
}, },

View File

@@ -0,0 +1,182 @@
<template>
<el-form-item v-if="mode === 'form'" :label="label" :prop="prop">
<div :class="[`${classPrefix}-uploader`, { [`${classPrefix}-uploader--large`]: large }]">
<el-upload
ref="uploadRef"
class="upload-inner"
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"
>
<el-image
v-if="value"
:src="value"
:class="`${classPrefix}-uploader__image`"
:preview-src-list="[value]"
fit="contain"
preview-teleported
:z-index="3000"
@click.stop
/>
<div v-else :class="`${classPrefix}-uploader__empty`">{{ emptyText }}</div>
</el-upload>
<el-link
v-if="value && !readonly"
type="primary"
class="upload-replace-link"
@click.stop="triggerUpload"
>
更换
</el-link>
</div>
</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>
<el-link
v-if="!readonly"
type="primary"
:class="`${classPrefix}-upload-card__action`"
@click.stop="triggerUpload"
>
{{ actionText }}
</el-link>
<span v-else :class="`${classPrefix}-upload-card__action`">{{ actionText }}</span>
</div>
<el-upload
ref="uploadRef"
: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"
>
<el-image
v-if="value"
:src="value"
:class="`${classPrefix}-upload-card__image`"
:preview-src-list="[value]"
fit="contain"
preview-teleported
:z-index="3000"
@click.stop
/>
<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: {
triggerUpload() {
const uploadEl = this.$refs.uploadRef && this.$refs.uploadRef.$el;
const input = uploadEl && uploadEl.querySelector('.el-upload__input');
if (input) input.click();
},
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>

View File

@@ -0,0 +1,28 @@
<template>
<div class="section-card">
<div v-if="title || $slots.title || $slots.extra" class="section-card__header">
<span class="section-card__bar" />
<span class="section-card__title">
<slot name="title">{{ title }}</slot>
</span>
<span class="section-card__extra">
<slot name="extra" />
</span>
</div>
<div class="section-card__body">
<slot />
</div>
</div>
</template>
<script>
export default {
name: 'SectionCard',
props: {
title: {
type: String,
default: ''
}
}
}
</script>

View File

@@ -9,7 +9,7 @@
:multiple="multiple" :multiple="multiple"
:limit="limit" :limit="limit"
:disabled="readonly" :disabled="readonly"
:show-file-list="true" :show-file-list="showFileList"
:on-success="handleSuccess" :on-success="handleSuccess"
:on-error="handleError" :on-error="handleError"
:on-remove="handleRemove" :on-remove="handleRemove"
@@ -69,8 +69,7 @@ import {
import '@open-file-viewer/core/style.css'; import '@open-file-viewer/core/style.css';
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url'; import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
import { baseUrl } from '@/config/env'; import { baseUrl } from '@/config/env';
import website from '@/config/website'; import { getUploadHeaders } from '@/utils/upload';
import { getToken } from '@/utils/auth';
const MIME_MAP = { const MIME_MAP = {
jpg: 'image/jpeg', jpg: 'image/jpeg',
@@ -86,6 +85,9 @@ const MIME_MAP = {
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
ppt: 'application/vnd.ms-powerpoint', ppt: 'application/vnd.ms-powerpoint',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
eml: 'message/rfc822',
msg: 'application/vnd.ms-outlook',
zip: 'application/zip',
txt: 'text/plain', txt: 'text/plain',
}; };
@@ -159,6 +161,10 @@ export default {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
showFileList: {
type: Boolean,
default: true,
},
}, },
emits: ['update:modelValue', 'change', 'success'], emits: ['update:modelValue', 'change', 'success'],
data() { data() {
@@ -182,9 +188,7 @@ export default {
return this.action || `${baseUrl}/blade-resource/oss/endpoint/put-file`; return this.action || `${baseUrl}/blade-resource/oss/endpoint/put-file`;
}, },
uploadHeaders() { uploadHeaders() {
return { return getUploadHeaders();
[website.tokenHeader]: getToken(),
};
}, },
acceptedList() { acceptedList() {
const types = this.fileTypes.length ? this.fileTypes : this.accept; const types = this.fileTypes.length ? this.fileTypes : this.accept;

View File

@@ -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,
}, },
//首页配置 //首页配置

View File

@@ -147,7 +147,7 @@ export const option = {
viewBtn: true, viewBtn: true,
grid: true, grid: true,
selection: true, selection: true,
menuWidth: 250, menuWidth: 180,
column: [ column: [
{ {
label: '数据源', label: '数据源',

View File

@@ -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',

View File

@@ -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,30 +52,30 @@ 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: '登录 ',
@@ -128,7 +128,7 @@ export default {
color: '换色', color: '换色',
}, },
tagsView: { tagsView: {
search: '搜索', search: '查询',
menu: '更多', menu: '更多',
clearCache: '清除缓存', clearCache: '清除缓存',
closeOthers: '关闭其它', closeOthers: '关闭其它',

View File

@@ -39,6 +39,8 @@ import codeSetting from './views/tool/codesetting.vue';
import formSetting from './views/tool/formsetting.vue'; import formSetting from './views/tool/formsetting.vue';
import tenantPackage from './views/system/tenantpackage.vue'; import tenantPackage from './views/system/tenantpackage.vue';
import tenantDatasource from './views/system/tenantdatasource.vue'; import tenantDatasource from './views/system/tenantdatasource.vue';
// 通用弹窗分组白卡(灰底弹窗内使用,标题在卡内)
import sectionCard from './components/section-card/main.vue';
window.$crudCommon = crudCommon; window.$crudCommon = crudCommon;
debug(); debug();
@@ -61,6 +63,7 @@ app.component('codeSetting', codeSetting);
app.component('formSetting', formSetting); app.component('formSetting', formSetting);
app.component('tenantPackage', tenantPackage); app.component('tenantPackage', tenantPackage);
app.component('tenantDatasource', tenantDatasource); app.component('tenantDatasource', tenantDatasource);
app.component('sectionCard', sectionCard);
app.config.globalProperties.$app = app; app.config.globalProperties.$app = app;
app.config.globalProperties.$dayjs = dayjs; app.config.globalProperties.$dayjs = dayjs;
app.config.globalProperties.website = website; app.config.globalProperties.website = website;
@@ -72,17 +75,27 @@ app.use(store);
app.use(router); app.use(router);
app.use(ElementPlus, { app.use(ElementPlus, {
locale: messages[language], locale: messages[language],
table: { showOverflowTooltip: true },
}); });
app.use(Avue, { app.use(Avue, {
axios, axios,
calcHeight: 10, calcHeight: 10,
crudOption: { crudOption: {
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchLabelWidth: 160, searchLabelWidth: 160,
searchMenuSpan: 24, searchMenuSpan: 24,
searchMenuPosition: 'right', searchMenuPosition: 'right',
menuWidth: 220, menuWidth: 180,
showOverflowTooltip: true,
viewBtnIcon: ' ',
editBtnIcon: ' ',
copyBtnIcon: ' ',
delBtnIcon: ' ',
saveBtnIcon: ' ',
updateBtnIcon: ' ',
cancelBtnIcon: ' ',
mockBtnIcon: ' ',
}, },
labelPosition: 'right', labelPosition: 'right',
labelWidth: 'auto', labelWidth: 'auto',

View File

@@ -24,7 +24,7 @@ const validateRemark = (rule, value, callback) => {
export const getCargoTypeOption = ctx => ({ export const getCargoTypeOption = ctx => ({
height: 'auto', height: 'auto',
calcHeight: 32, calcHeight: 22,
dialogWidth: 760, dialogWidth: 760,
labelPosition: 'right', labelPosition: 'right',
labelWidth: 'auto', labelWidth: 'auto',
@@ -34,9 +34,10 @@ export const getCargoTypeOption = ctx => ({
saveBtnText: '提交', saveBtnText: '提交',
updateBtnText: '提交', updateBtnText: '提交',
searchShow: true, searchShow: true,
searchIcon: false, searchIcon: true,
searchMenuSpan: 24, searchLabelWidth: 50,
searchIndex: 8, searchMenuSpan: 10,
searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
@@ -47,7 +48,7 @@ export const getCargoTypeOption = ctx => ({
editBtn: false, editBtn: false,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
column: [ column: [
{ {
label: '类型', label: '类型',
@@ -55,62 +56,48 @@ export const getCargoTypeOption = ctx => ({
type: 'radio', type: 'radio',
dataType: 'number', dataType: 'number',
dicData: typeLevelDic, dicData: typeLevelDic,
search: true, search: false,
searchSpan: 12,
value: 2, value: 2,
span: 24, span: 24,
order: 100,
hide: true,
minWidth: 120, minWidth: 120,
editDisabled: true, editDisabled: true,
rules: [{ required: true, message: '请选择货物类型级别', trigger: 'change' }], rules: [{ required: true, message: '请选择货物类型级别', trigger: 'change' }],
change: ({ value }) => ctx.handleTypeLevelChange(value), change: ({ value }) => ctx.handleTypeLevelChange(value),
}, },
{
label: '上级货物类型',
prop: 'parentId',
formslot: true,
hide: true,
display: false,
span: 24,
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
},
{
label: '上级货物类型',
prop: 'parentCargoName',
slot: true,
addDisplay: false,
editDisplay: false,
display: false,
minWidth: 160,
},
{
label: '上级货物类型编码',
prop: 'parentCargoCode',
slot: true,
readonly: true,
editDisabled: true,
addDisplay: false,
editDisplay: false,
display: false,
minWidth: 160,
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
},
{ {
label: '货物类型', label: '货物类型',
prop: 'cargoName', prop: 'cargoName',
minWidth: 150, minWidth: 150,
search: true,
searchPlaceholder: '请输入',
searchSpan: 6,
searchOrder: 2,
order: 70,
placeholder: '请输入',
maxlength: 50, maxlength: 50,
showWordLimit: true, showWordLimit: true,
rules: [{ validator: validateCargoName, trigger: 'blur' }], showOverflowTooltip: true,
rules: [
{ required: true, message: '请输入货物类型名称', trigger: 'blur' },
{ validator: validateCargoName, trigger: 'blur' },
],
}, },
{ {
label: '货物类型编码', label: '货物类型编码',
prop: 'cargoCode', prop: 'cargoCode',
minWidth: 140, minWidth: 140,
search: true, search: true,
searchSpan: 12, searchPlaceholder: '请输入',
searchSpan: 6,
searchOrder: 1,
maxlength: 4, maxlength: 4,
order: 60,
placeholder: '请输入',
editDisabled: true, editDisabled: true,
rules: [ rules: [
{ required: true, message: '请输入货物类型编码', trigger: 'blur' },
{ {
validator: (rule, value, callback) => { validator: (rule, value, callback) => {
const form = ctx.form || {}; const form = ctx.form || {};
@@ -135,6 +122,43 @@ export const getCargoTypeOption = ctx => ({
], ],
change: ({ value }) => ctx.handleCargoCodeChange(value), change: ({ value }) => ctx.handleCargoCodeChange(value),
}, },
{
label: '上级货物类型',
prop: 'parentId',
formslot: true,
hide: true,
display: false,
span: 12,
order: 90,
placeholder: '请输入',
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,
addDisabled: true,
addDisplay: false,
editDisplay: false,
display: false,
span: 12,
order: 80,
minWidth: 160,
placeholder: '请输入',
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
},
{ {
label: '创建人', label: '创建人',
prop: 'createUserName', prop: 'createUserName',
@@ -151,31 +175,35 @@ export const getCargoTypeOption = ctx => ({
minRows: 4, minRows: 4,
span: 24, span: 24,
minWidth: 180, minWidth: 180,
placeholder: '请输入',
maxlength: 200, maxlength: 200,
showWordLimit: true, showWordLimit: true,
overHidden: true, overHidden: true,
showOverflowTooltip: true,
rules: [{ validator: validateRemark, trigger: 'blur' }], rules: [{ validator: validateRemark, trigger: 'blur' }],
}, },
{ {
label: '更新时间', label: '更新时间',
prop: 'updateTime', prop: 'updateTime',
type: 'datetime', type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'YYYY-MM-DD',
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
display: false, display: false,
sortable: true,
minWidth: 160, minWidth: 160,
}, },
{ {
label: '创建时间', label: '创建时间',
prop: 'createTime', prop: 'createTime',
type: 'datetime', type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'YYYY-MM-DD',
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
display: false, display: false,
sortable: true,
minWidth: 160, minWidth: 160,
}, },
], ],

View File

@@ -5,15 +5,17 @@ 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: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
@@ -25,14 +27,24 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
delBtn: false, delBtn: false,
addBtn: false, addBtn: false,
dialogClickModal: false, dialogClickModal: false,
menuFixed: 'right',
menuWidth: 180, menuWidth: 180,
column: [ column: [
{ {
label: '地址名称', label: '地址名称',
prop: 'addressName', prop: 'addressName',
search: true, search: true,
searchOrder: 8,
span: 24,
minWidth: 150, minWidth: 150,
rules: [{ required: true, message: '请输入地址名称', trigger: 'blur' }], showOverflowTooltip: true,
placeholder: '请输入',
maxlength: 100,
showWordLimit: true,
rules: [
{ required: true, message: '请输入地址名称', trigger: 'blur' },
{ max: 100, message: '地址名称不能超过100个字', trigger: 'blur' },
],
}, },
{ {
label: '地址编号', label: '地址编号',
@@ -45,17 +57,14 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
label: '类型', label: '类型',
prop: 'addressType', prop: 'addressType',
type: 'select', type: 'select',
formslot: true,
search: true, search: true,
searchOrder: 7,
span: 24,
minWidth: 140,
dicData: addressTypeOptions, dicData: addressTypeOptions,
rules: [{ required: true, message: '请选择类型', trigger: 'change' }], rules: [{ required: true, message: '请选择类型', trigger: 'change' }],
}, },
{
label: '来源主数据',
prop: 'sourceId',
formslot: true,
hide: true,
span: 24,
},
{ {
label: '站点编码', label: '站点编码',
prop: 'siteCodeDisplay', prop: 'siteCodeDisplay',
@@ -64,54 +73,66 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
}, },
{
label: '站点编码',
prop: 'siteCode',
search: true,
hide: true,
addDisplay: false,
editDisplay: false,
},
{ {
label: '详细地址', label: '详细地址',
prop: 'detailAddress', prop: 'detailAddress',
search: true, search: true,
searchOrder: 5,
formslot: true, formslot: true,
type: 'textarea', type: 'textarea',
minRows: 3, minRows: 3,
span: 24, span: 24,
minWidth: 220, minWidth: 220,
rules: [{ required: true, message: '请输入详细地址', trigger: 'blur' }], showOverflowTooltip: true,
rules: [
{ required: true, message: '请输入详细地址', trigger: 'blur' },
{ max: 255, message: '详细地址不能超过255个字', trigger: 'blur' },
],
}, },
{ {
label: '经度', label: '经度',
prop: 'longitude', prop: 'longitude',
formslot: true,
minWidth: 120, minWidth: 120,
rules: [{ validator: validateLongitude, trigger: 'blur' }], addDisplay: false,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '纬度', label: '纬度',
prop: 'latitude', prop: 'latitude',
formslot: true,
minWidth: 120, minWidth: 120,
rules: [{ validator: validateLatitude, trigger: 'blur' }], addDisplay: false,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '行政区划', label: '行政区划',
prop: 'regionName', prop: 'regionName',
search: true, search: true,
searchOrder: 4,
display: false,
minWidth: 150, minWidth: 150,
rules: [{ required: true, message: '请输入行政区划', trigger: 'blur' }], rules: [{ required: true, message: '请选择行政区划', trigger: 'change' }],
}, },
{ {
label: '组织', label: '联系人',
prop: 'deptId', prop: 'contactName',
type: 'select',
search: true, search: true,
hide: true, searchOrder: 2,
display: false, minWidth: 110,
dicData: [], placeholder: '请输入',
maxlength: 50,
rules: [{ max: 50, message: '联系人不能超过50个字', trigger: 'blur' }],
},
{
label: '联系方式',
prop: 'contactPhone',
search: true,
searchOrder: 1,
minWidth: 130,
placeholder: '请输入',
maxlength: 20,
rules: [{ max: 20, message: '联系方式不能超过20个字', trigger: 'blur' }],
}, },
{ {
label: '组织', label: '组织',
@@ -120,43 +141,27 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
}, },
{
label: '联系人',
prop: 'contactName',
search: true,
minWidth: 110,
},
{
label: '联系方式',
prop: 'contactPhone',
search: true,
minWidth: 130,
},
{ {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 4,
span: 24, span: 24,
hide: true, minWidth: 160,
overHidden: true,
showOverflowTooltip: true,
placeholder: '请输入',
maxlength: 200, maxlength: 200,
showWordLimit: true, showWordLimit: true,
rules: [{ max: 200, message: '备注不能超过200个字', trigger: 'blur' }], rules: [{ max: 200, message: '备注不能超过200个字', trigger: 'blur' }],
}, },
{
label: '更新人',
prop: 'updateUserName',
minWidth: 120,
addDisplay: false,
editDisplay: false,
},
{ {
label: '更新时间', label: '更新时间',
prop: 'updateTime', prop: 'updateTime',
type: 'datetime', type: 'datetime',
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: 160, width: 180,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
}, },
@@ -166,9 +171,64 @@ export const createOption = ({ validateLongitude, validateLatitude }) => ({
type: 'datetime', type: 'datetime',
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: 160, width: 180,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
}, },
{
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: '站点编码',
prop: 'siteCode',
search: true,
searchOrder: 6,
hide: true,
addDisplay: false,
editDisplay: false,
},
{
label: '组织',
prop: 'deptId',
type: 'select',
search: true,
searchOrder: 3,
hide: true,
display: false,
dicData: [],
},
], ],
}); });

View File

@@ -1,13 +1,20 @@
import { import {
auditColumns, auditColumns,
createCrudOption, createCrudOption,
nonNegativeRule,
packageOptions, packageOptions,
priceUnitOptions, priceUnitOptions,
selectRule,
textRule, textRule,
} from './common'; } 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 = { export const config = {
title: '常用货物', title: '常用货物',
permission: 'common_cargo', permission: 'common_cargo',
@@ -15,68 +22,168 @@ export const config = {
exportName: '常用货物', exportName: '常用货物',
importUrl: '/blade-transport/common-cargo/import-common-cargo', importUrl: '/blade-transport/common-cargo/import-common-cargo',
templateUrl: '/blade-transport/common-cargo/export-template', templateUrl: '/blade-transport/common-cargo/export-template',
enableAllDept: true, enableAllDept: false,
}; };
export const option = createCrudOption([ export const option = createCrudOption([
{
label: '组织',
prop: 'deptName',
search: true,
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
{
label: '一级货物类型',
prop: 'firstCargoTypeName',
search: true,
minWidth: 150,
editDisabled: true,
rules: textRule('一级货物类型', 100, true),
},
{
label: '一级货物类型编码',
prop: 'firstCargoTypeCode',
hide: true,
editDisabled: true,
},
{
label: '二级货物类型',
prop: 'secondCargoTypeName',
search: true,
minWidth: 150,
editDisabled: true,
rules: textRule('二级货物类型', 100, true),
},
{
label: '二级货物类型编码',
prop: 'secondCargoTypeCode',
search: true,
minWidth: 150,
editDisabled: true,
rules: textRule('二级货物类型编码', 20, true),
},
{ {
label: '货物名称', label: '货物名称',
prop: 'cargoName', prop: 'cargoName',
search: true,
minWidth: 150, minWidth: 150,
placeholder: '请输入',
rules: textRule('货物名称', 100, true), rules: textRule('货物名称', 100, true),
}, },
{ {
label: '货物编号', label: '货物编号',
prop: 'cargoCode', prop: 'cargoCode',
search: true, formslot: true,
minWidth: 120, minWidth: 120,
maxlength: 20,
showWordLimit: true,
rules: [
{ required: true, message: '请输入货物编号', trigger: 'blur' },
{ max: 20, message: '货物编号不能超过20个字符', trigger: 'blur' },
],
},
{
label: '一级货物类型',
prop: 'firstCargoTypeName',
formslot: true,
minWidth: 150,
editDisabled: true, editDisabled: true,
rules: textRule('货物编号', 20, true), rules: [{ required: true, message: '请选择一级货物类型', trigger: 'change' }],
},
{
label: '一级货物类型编码',
prop: 'firstCargoTypeCode',
hide: true,
display: false,
addDisplay: false,
editDisabled: true,
},
{
label: '二级货物类型',
prop: 'secondCargoTypeName',
formslot: true,
minWidth: 150,
editDisabled: true,
rules: [{ required: true, message: '请选择二级货物类型', trigger: 'change' }],
},
{
label: '二级货物类型编码',
prop: 'secondCargoTypeCode',
display: false,
addDisplay: false,
editDisabled: true,
},
// 搜索字段与表格、表单字段独立,避免筛选配置影响数据展示和编辑布局。
{
label: '货物名称',
prop: 'searchCargoName',
searchProp: 'cargoName',
search: true,
searchOrder: 5,
searchPlaceholder: '请输入',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '货物编号',
prop: 'searchCargoCode',
searchProp: 'cargoCode',
search: true,
searchOrder: 4,
searchPlaceholder: '请输入',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '一级货物类型',
prop: 'searchFirstCargoTypeName',
searchProp: 'firstCargoTypeName',
type: 'select',
searchType: 'select',
search: true,
searchOrder: 3,
searchPlaceholder: '请选择',
dicUrl: '/blade-system/cargo-type/list?current=1&size=9999&typeLevel=1',
dicFormatter: listDicFormatter,
props: {
label: 'cargoName',
value: 'cargoName',
},
filterable: true,
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '二级货物类型',
prop: 'searchSecondCargoTypeName',
searchProp: 'secondCargoTypeName',
type: 'select',
searchType: 'select',
search: true,
searchOrder: 2,
searchPlaceholder: '请选择',
dicUrl: '/blade-system/cargo-type/list?current=1&size=9999&typeLevel=2',
dicFormatter: listDicFormatter,
props: {
label: 'cargoName',
value: 'cargoName',
},
filterable: true,
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '组织',
prop: 'searchDeptId',
searchProp: 'deptId',
type: 'select',
searchType: 'select',
search: true,
searchOrder: 1,
searchPlaceholder: '请选择',
dicData: [],
props: {
label: 'label',
value: 'value',
},
filterable: true,
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '包装品牌',
prop: 'packageBrand',
slot: true,
minWidth: 150,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
}, },
{ {
label: '品牌', label: '品牌',
prop: 'brand', prop: 'brand',
search: true, search: false,
hide: true,
minWidth: 120, minWidth: 120,
placeholder: '请输入',
rules: textRule('品牌', 50), rules: textRule('品牌', 50),
}, },
{ {
@@ -84,60 +191,74 @@ export const option = createCrudOption([
prop: 'packageType', prop: 'packageType',
type: 'select', type: 'select',
dicData: packageOptions, dicData: packageOptions,
hide: true,
minWidth: 100, minWidth: 100,
}, },
{
label: '货值',
prop: 'cargoValue',
type: 'number',
precision: 2,
min: 0,
minWidth: 120,
rules: [nonNegativeRule('货值')],
},
{ {
label: '规格', label: '规格',
prop: 'specification', prop: 'specification',
minWidth: 120, minWidth: 120,
placeholder: '请输入',
rules: textRule('规格', 50), rules: textRule('规格', 50),
}, },
{
label: '型号',
prop: 'model',
minWidth: 120,
placeholder: '请输入',
rules: textRule('型号', 50),
},
{
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: '计价单位', label: '计价单位',
prop: 'priceUnit', prop: 'priceUnit',
type: 'select', type: 'select',
dicData: priceUnitOptions, dicData: priceUnitOptions,
display: false,
minWidth: 120, minWidth: 120,
}, },
{
label: '型号',
prop: 'model',
minWidth: 120,
rules: textRule('型号', 50),
},
{
label: '说明1',
prop: 'descriptionOne',
minWidth: 160,
rules: textRule('说明1', 100),
},
{ {
label: '尺寸', label: '尺寸',
prop: 'sizeText', prop: 'sizeText',
minWidth: 120, minWidth: 120,
rules: textRule('尺寸', 50),
},
{
label: '说明2',
prop: 'descriptionTwo',
minWidth: 160,
rules: textRule('说明2', 100),
},
{
label: '数据来源',
prop: 'dataSource',
minWidth: 120,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
rules: textRule('尺寸', 100),
},
{
label: '其他说明1',
prop: 'descriptionOne',
minWidth: 160,
placeholder: '请输入',
rules: textRule('其他说明1', 100),
},
{
label: '其他说明2',
prop: 'descriptionTwo',
minWidth: 160,
placeholder: '请输入',
rules: textRule('其他说明2', 100),
}, },
{ {
label: '备注', label: '备注',
@@ -145,12 +266,25 @@ export const option = createCrudOption([
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 4,
span: 24, span: 24,
hide: true,
maxlength: 200, maxlength: 200,
showWordLimit: true, showWordLimit: true,
placeholder: '请输入',
rules: textRule('备注', 200), rules: textRule('备注', 200),
}, },
...auditColumns, {
label: '组织',
prop: 'deptName',
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
...auditColumns
.filter(column => ['updateTime', 'createTime'].includes(column.prop))
.sort(
(first, second) =>
['updateTime', 'createTime'].indexOf(first.prop) -
['updateTime', 'createTime'].indexOf(second.prop)
),
]); ]);
export const excelOption = { export const excelOption = {

View File

@@ -5,45 +5,41 @@ export const config = {
permission: 'common_route', permission: 'common_route',
exportUrl: '/blade-transport/common-route/export-common-route', exportUrl: '/blade-transport/common-route/export-common-route',
exportName: '常用线路', exportName: '常用线路',
enableAllDept: true, importUrl: '/blade-transport/common-route/import-common-route',
templateUrl: '/blade-transport/common-route/export-template',
enableAllDept: false,
}; };
export const option = createCrudOption([ export const option = createCrudOption([
{ {
label: '组织', label: '线路名称',
prop: 'deptName', prop: 'routeName',
search: true, span: 12,
minWidth: 150, minWidth: 150,
addDisplay: false, overHidden: true,
editDisplay: false, rules: textRule('线路名称', 100, true),
}, },
{ {
label: '线路编号', label: '线路编号',
prop: 'routeCode', prop: 'routeCode',
search: true,
minWidth: 120, minWidth: 120,
addDisplay: false, addDisplay: false,
editDisabled: true, editDisabled: true,
}, },
{
label: '线路名称',
prop: 'routeName',
search: true,
minWidth: 150,
rules: textRule('线路名称', 100, true),
},
{ {
label: '发货地', label: '发货地',
prop: 'departureName', prop: 'departureName',
search: true,
minWidth: 140, minWidth: 140,
rules: textRule('发货地', 100, true), addDisplay: false,
editDisplay: false,
}, },
{ {
label: '发货地址', label: '发货地址',
prop: 'departureAddress', prop: 'departureAddress',
search: true, formslot: true,
span: 24,
minWidth: 220, minWidth: 220,
overHidden: true,
rules: textRule('发货地址', 255, true), rules: textRule('发货地址', 255, true),
}, },
{ {
@@ -53,6 +49,8 @@ export const option = createCrudOption([
precision: 6, precision: 6,
minWidth: 120, minWidth: 120,
hide: true, hide: true,
addDisplay: false,
editDisplay: false,
}, },
{ {
label: '发货纬度', label: '发货纬度',
@@ -61,6 +59,8 @@ export const option = createCrudOption([
precision: 6, precision: 6,
minWidth: 120, minWidth: 120,
hide: true, hide: true,
addDisplay: false,
editDisplay: false,
}, },
{ {
label: '发货联系人', label: '发货联系人',
@@ -77,15 +77,17 @@ export const option = createCrudOption([
{ {
label: '收货地', label: '收货地',
prop: 'arrivalName', prop: 'arrivalName',
search: true,
minWidth: 140, minWidth: 140,
rules: textRule('收货地', 100, true), addDisplay: false,
editDisplay: false,
}, },
{ {
label: '收货地址', label: '收货地址',
prop: 'arrivalAddress', prop: 'arrivalAddress',
search: true, formslot: true,
span: 24,
minWidth: 220, minWidth: 220,
overHidden: true,
rules: textRule('收货地址', 255, true), rules: textRule('收货地址', 255, true),
}, },
{ {
@@ -95,6 +97,8 @@ export const option = createCrudOption([
precision: 6, precision: 6,
minWidth: 120, minWidth: 120,
hide: true, hide: true,
addDisplay: false,
editDisplay: false,
}, },
{ {
label: '收货纬度', label: '收货纬度',
@@ -103,6 +107,8 @@ export const option = createCrudOption([
precision: 6, precision: 6,
minWidth: 120, minWidth: 120,
hide: true, hide: true,
addDisplay: false,
editDisplay: false,
}, },
{ {
label: '收货联系人', label: '收货联系人',
@@ -122,10 +128,154 @@ export const option = createCrudOption([
type: 'textarea', type: 'textarea',
minRows: 4, minRows: 4,
span: 24, span: 24,
hide: true, minWidth: 180,
maxlength: 500, maxlength: 500,
showWordLimit: true, showWordLimit: true,
rules: textRule('备注', 500), rules: textRule('备注', 500),
}, },
...auditColumns, {
label: '组织',
prop: 'deptName',
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
// 搜索字段独立于表格和表单字段,避免筛选配置影响数据展示和编辑布局。
{
label: '线路名称',
prop: 'searchRouteName',
searchProp: 'routeName',
search: true,
searchOrder: 7,
searchPlaceholder: '请输入',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '线路编号',
prop: 'searchRouteCode',
searchProp: 'routeCode',
search: true,
searchOrder: 6,
searchPlaceholder: '请输入',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '发货地',
prop: 'searchDepartureName',
searchProp: 'departureName',
search: true,
searchOrder: 5,
searchPlaceholder: '请输入',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '发货地址',
prop: 'searchDepartureAddress',
searchProp: 'departureAddress',
search: true,
searchOrder: 4,
searchPlaceholder: '请输入',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '收货地',
prop: 'searchArrivalName',
searchProp: 'arrivalName',
search: true,
searchOrder: 3,
searchPlaceholder: '请输入',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '收货地址',
prop: 'searchArrivalAddress',
searchProp: 'arrivalAddress',
search: true,
searchOrder: 2,
searchPlaceholder: '请输入',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '组织',
prop: 'searchDeptId',
searchProp: 'deptId',
search: true,
searchOrder: 1,
searchType: 'cascader',
searchPlaceholder: '请选择',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
dicData: [],
props: {
label: 'label',
value: 'value',
children: 'children',
},
checkStrictly: true,
emitPath: false,
showAllLevels: false,
filterable: true,
},
...auditColumns
.filter(column => column.prop !== 'createUserName')
.map(column =>
['createTime', 'updateTime'].includes(column.prop) ? { ...column, minWidth: 190 } : column
)
.sort(
(first, second) =>
['updateUserName', 'updateTime', 'createTime'].indexOf(first.prop) -
['updateUserName', 'updateTime', 'createTime'].indexOf(second.prop)
),
]); ]);
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 标准格式文件',
},
],
};

View File

@@ -1,9 +1,7 @@
export const transportTypeOptions = [ export const transportTypeOptions = [
{ label: '公路整车', value: '公路整车' }, { label: '公路运输', value: '公路运输' },
{ label: '公路零担', value: '公路零担' },
{ label: '铁路运输', value: '铁路运输' }, { label: '铁路运输', value: '铁路运输' },
{ label: '水路运输', value: '水路运输' }, { label: '水路运输', value: '水路运输' },
{ label: '跨境海运', value: '跨境海运' },
{ label: '航空运输', value: '航空运输' }, { label: '航空运输', value: '航空运输' },
]; ];
@@ -89,8 +87,10 @@ export const approvalStatusOptions = [
]; ];
export const effectiveTypeOptions = [ export const effectiveTypeOptions = [
{ label: '临时', value: 'temporary' }, { label: '未生效', value: 'not_effective' },
{ label: '正式', value: 'formal' }, { label: '临时生效', value: 'temporary_effective' },
{ label: '正式生效', value: 'formal_effective' },
{ label: '已过期', value: 'expired' },
]; ];
export const businessTypeOptions = [ export const businessTypeOptions = [
@@ -156,7 +156,9 @@ export const textRule = (label, max, required = false) => {
return rules; return rules;
}; };
export const selectRule = label => [{ required: true, message: `请选择${label}`, trigger: 'change' }]; export const selectRule = label => [
{ required: true, message: `请选择${label}`, trigger: 'change' },
];
export const nonNegativeRule = label => ({ export const nonNegativeRule = label => ({
validator: (rule, value, callback) => { validator: (rule, value, callback) => {
@@ -189,7 +191,7 @@ export const createCrudOption = columns => ({
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
@@ -202,7 +204,8 @@ export const createCrudOption = columns => ({
delBtn: false, delBtn: false,
dialogClickModal: false, dialogClickModal: false,
menuFixed: 'right', menuFixed: 'right',
menuWidth: 240, menuWidth: 180,
showOverflowTooltip: true,
column: columns, column: columns,
}); });

View File

@@ -4,103 +4,188 @@ import {
contractCategoryOptions, contractCategoryOptions,
contractStageOptions, contractStageOptions,
createCrudOption, createCrudOption,
effectiveTypeOptions,
selectRule, selectRule,
settlementModeOptions,
signTypeOptions, signTypeOptions,
textRule, textRule,
} from './common'; } from './common';
const contractSettlementModeOptions = [
{ label: '现结', value: '现结' },
{ label: '日结', value: '日结' },
{ label: '周结', value: '周结' },
{ label: '月结', value: '月结' },
{ label: '按固定天数周期', value: '按固定天数周期' },
];
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 = { export const config = {
title: '合同管理', title: '合同管理',
permission: 'contract_manage', permission: 'contract_manage',
exportUrl: '/blade-transport/contract-manage/export-contract-manage', exportUrl: '/blade-transport/contract-manage/export-contract-manage',
exportName: '合同管理', exportName: '合同管理',
defaultForm: {
contractCategory: '客户合同',
},
projectPlaceholder: '请选择',
organizationPlaceholder: '请选择',
enableAllDept: true, enableAllDept: true,
allDeptReadonly: 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,
enableContractExpiryTags: true,
actions: ['copy'], actions: ['copy'],
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
statusTextProp: 'approvalStatusName', statusTextProp: 'approvalStatusName',
customMenuActions: true,
editLabelStatusMap: {
change_rejected: '编辑变更内容',
},
deleteStatus: ['draft'], deleteStatus: ['draft'],
deleteStage: ['draft'],
editStatus: ['draft', 'rejected', 'change_rejected'], editStatus: ['draft', 'rejected', 'change_rejected'],
operations: [ operations: [
{ {
action: 'toTemporary', action: 'flow',
label: '转临时', label: '查看流程',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['draft'], status: ['reviewing', 'change_reviewing'],
stage: ['draft'], stage: ['temporary', 'formal'],
permission: 'contract_manage_temp', permission: 'contract_manage_view',
},
{
action: 'submitFormal',
label: '转正式',
statusProp: 'approvalStatus',
status: ['draft', 'rejected', 'approved'],
stage: ['temporary'],
permission: 'contract_manage_formal',
}, },
{ {
action: 'withdraw', action: 'withdraw',
label: '撤回', label: '撤回',
icon: 'el-icon-refresh-left',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'], status: ['reviewing'],
stage: ['temporary', 'formal'],
permission: 'contract_manage_withdraw', permission: 'contract_manage_withdraw',
}, },
{ {
action: 'approve', action: 'approve',
label: '审批通过', label: '通过',
type: 'success',
icon: 'el-icon-check',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'], status: ['reviewing'],
stage: ['temporary', 'formal'],
permission: 'contract_manage_approve', permission: 'contract_manage_approve',
}, },
{ {
action: 'reject', action: 'reject',
label: '审批驳回', label: '驳回',
type: 'warning',
icon: 'el-icon-close',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'], status: ['reviewing'],
stage: ['temporary', 'formal'],
permission: 'contract_manage_reject', permission: 'contract_manage_reject',
}, },
{
action: 'submitFormal',
label: '重新提交转正',
statusProp: 'approvalStatus',
status: ['rejected'],
stage: ['temporary'],
permission: 'contract_manage_formal',
},
{ {
action: 'startChange', action: 'startChange',
label: '发起变更', label: '发起变更',
icon: 'el-icon-edit-outline',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['approved', 'change_approved'], status: ['approved'],
stage: ['formal'], stage: ['formal'],
permission: 'contract_manage_change', permission: 'contract_manage_change',
prompt: '请输入变更内容与原因', prompt: '请输入变更内容与原因',
}, },
{ {
action: 'terminate', action: 'startChange',
label: '终止', label: '再次发起变更',
type: 'danger', statusProp: 'approvalStatus',
icon: 'el-icon-close', status: ['change_approved'],
stage: ['formal'],
permission: 'contract_manage_change',
prompt: '请输入变更内容与原因',
},
{
action: 'attachmentUpload',
label: '附件上传',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['approved', 'change_approved'], status: ['approved', 'change_approved'],
stage: ['formal'], stage: ['formal'],
permission: 'contract_manage_terminate', permission: 'contract_manage_edit',
prompt: '请输入终止原因', },
{
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([ export const option = createCrudOption([
{
label: '',
prop: 'basicInfoTitle',
formslot: true,
span: 24,
order: 200,
hide: true,
labelWidth: 0,
},
{ {
label: '合同编号', label: '合同编号',
prop: 'contractNo', prop: 'contractNo',
search: true, search: true,
minWidth: 160, searchOrder: 6,
addDisplay: false, searchPlaceholder: '请输入',
editDisabled: true, order: 185,
disabled: true,
placeholder: '不填写,则系统自动生成',
minWidth: 200,
}, },
{ {
label: '合同名称', label: '合同名称',
prop: 'contractName', prop: 'contractName',
search: true, search: true,
searchOrder: 7,
searchPlaceholder: '请输入',
order: 180,
minWidth: 180, minWidth: 180,
rules: textRule('合同名称', 100, true), rules: textRule('合同名称', 100, true),
}, },
@@ -108,26 +193,57 @@ export const option = createCrudOption([
label: '所属项目', label: '所属项目',
prop: 'projectName', prop: 'projectName',
search: true, search: true,
searchOrder: 8,
searchType: 'select',
searchPlaceholder: '请选择',
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, minWidth: 160,
rules: selectRule('所属项目'),
}, },
{ {
label: '所属项目ID', label: '所属项目ID',
prop: 'projectId', prop: 'projectId',
hide: true, hide: true,
display: false,
}, },
{ {
label: '所属组织', label: '所属组织',
prop: 'organizationName', prop: 'organizationName',
search: true, search: true,
searchOrder: 3,
searchType: 'cascader',
searchPlaceholder: '全部',
formslot: true,
order: 120,
dicData: [],
props: {
label: 'label',
value: 'id',
children: 'children',
},
checkStrictly: true,
emitPath: false,
showAllLevels: false,
filterable: true,
minWidth: 150, minWidth: 150,
addDisplay: false, rules: selectRule('所属组织'),
editDisabled: true,
}, },
{ {
label: '合同类别', label: '合同类别',
prop: 'contractCategory', prop: 'contractCategory',
type: 'select', type: 'select',
search: true, search: true,
searchOrder: 9,
searchPlaceholder: '请选择',
order: 170,
dicData: contractCategoryOptions, dicData: contractCategoryOptions,
minWidth: 130, minWidth: 130,
rules: selectRule('合同类别'), rules: selectRule('合同类别'),
@@ -136,19 +252,63 @@ export const option = createCrudOption([
label: '签约类型', label: '签约类型',
prop: 'signType', prop: 'signType',
type: 'select', type: 'select',
search: true, search: false,
span: 6,
order: 190,
dicData: signTypeOptions, dicData: signTypeOptions,
minWidth: 120, minWidth: 120,
rules: selectRule('签约类型'),
},
{
label: '生效类型',
prop: 'effectiveType',
type: 'select',
search: true,
searchOrder: 5,
searchPlaceholder: '请选择',
dicData: effectiveTypeOptions,
hide: true,
display: false,
}, },
{ {
label: '甲方', label: '甲方',
prop: 'partyA', prop: 'partyA',
type: 'select',
order: 160,
dicUrl:
'/blade-transport/customer-archive/list?current=1&size=9999&customerType=客户&approvalStatus=approved&status=1',
dicFormatter: listDicFormatter,
props: {
label: 'fullName',
value: 'fullName',
},
filterable: true,
minWidth: 160, minWidth: 160,
rules: selectRule('甲方'),
}, },
{ {
label: '乙方', label: '乙方',
prop: 'partyB', prop: 'partyB',
type: 'select',
order: 150,
dicUrl:
'/blade-transport/customer-archive/list?current=1&size=9999&customerType=承运商&approvalStatus=approved&status=1',
dicFormatter: listDicFormatter,
props: {
label: 'fullName',
value: 'fullName',
},
filterable: true,
minWidth: 160, minWidth: 160,
rules: selectRule('乙方'),
},
{
label: '合同期限',
prop: 'contractPeriod',
formslot: true,
order: 130,
hide: true,
rules: [{ required: true, message: '请选择合同期限', trigger: 'change' }],
}, },
{ {
label: '开始日期', label: '开始日期',
@@ -157,6 +317,8 @@ export const option = createCrudOption([
format: 'YYYY-MM-DD', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
minWidth: 130, minWidth: 130,
addDisplay: false,
editDisplay: false,
}, },
{ {
label: '结束日期', label: '结束日期',
@@ -165,6 +327,8 @@ export const option = createCrudOption([
format: 'YYYY-MM-DD', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
minWidth: 130, minWidth: 130,
addDisplay: false,
editDisplay: false,
}, },
{ {
label: '临时效力起', label: '临时效力起',
@@ -173,6 +337,8 @@ export const option = createCrudOption([
format: 'YYYY-MM-DD', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
minWidth: 130, minWidth: 130,
addDisplay: false,
editDisplay: false,
}, },
{ {
label: '临时效力止', label: '临时效力止',
@@ -181,11 +347,16 @@ export const option = createCrudOption([
format: 'YYYY-MM-DD', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
minWidth: 130, minWidth: 130,
addDisplay: false,
editDisplay: false,
}, },
{ {
label: '经办人', label: '经办人',
prop: 'handlerUserName', prop: 'handlerUserName',
order: 110,
disabled: true,
minWidth: 120, minWidth: 120,
rules: textRule('经办人', 50, true),
}, },
{ {
label: '签订日期', label: '签订日期',
@@ -193,14 +364,20 @@ export const option = createCrudOption([
type: 'date', type: 'date',
format: 'YYYY-MM-DD', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
hide: true,
order: 100,
minWidth: 130, minWidth: 130,
rules: [{ required: true, message: '请选择签订日期', trigger: 'change' }],
}, },
{ {
label: '结算方式', label: '结算类型',
prop: 'settlementMode', prop: 'settlementMode',
type: 'select', type: 'select',
dicData: settlementModeOptions, dicData: contractSettlementModeOptions,
hide: true,
order: 90,
minWidth: 120, minWidth: 120,
rules: selectRule('结算类型'),
}, },
{ {
label: '合同格式', label: '合同格式',
@@ -210,54 +387,76 @@ export const option = createCrudOption([
{ label: '电子合同', value: '电子合同' }, { label: '电子合同', value: '电子合同' },
{ label: '纸质合同', value: '纸质合同' }, { label: '纸质合同', value: '纸质合同' },
], ],
hide: true,
order: 80,
minWidth: 120, minWidth: 120,
rules: selectRule('合同格式'),
}, },
{ {
label: '法人章', label: '是否需要加盖法人章',
prop: 'legalSealFlag', prop: 'legalSealFlag',
type: 'switch', type: 'select',
dicData: [ dicData: [
{ label: '否', value: 0 }, { label: '否', value: 0 },
{ label: '是', value: 1 }, { label: '是', value: 1 },
], ],
value: 0, value: 0,
hide: true,
order: 70,
minWidth: 100, minWidth: 100,
rules: selectRule('是否需要加盖法人章'),
}, },
{ {
label: '一式份数', label: '一式',
prop: 'copyCount', prop: 'copyCount',
type: 'number', formslot: true,
hide: true,
order: 60,
minWidth: 110, minWidth: 110,
}, },
{ {
label: '回款账期(天)', label: '回款账期',
prop: 'paymentDays', prop: 'paymentDays',
type: 'number', formslot: true,
hide: true,
order: 50,
minWidth: 130, minWidth: 130,
}, },
{
label: '创建时间',
prop: 'createTime',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
minWidth: 190,
addDisplay: false,
editDisplay: false,
},
{ {
label: '合同阶段', label: '合同阶段',
prop: 'contractStage', prop: 'contractStage',
type: 'select', type: 'select',
search: true, search: true,
searchOrder: 2,
searchPlaceholder: '请选择',
slot: true, slot: true,
dicData: contractStageOptions, dicData: contractStageOptions,
minWidth: 120, minWidth: 120,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
fixed: 'right',
}, },
{ {
label: '审核状态', label: '审核状态',
prop: 'approvalStatus', prop: 'approvalStatus',
type: 'select', type: 'select',
search: true, search: true,
searchOrder: 4,
searchPlaceholder: '请选择',
slot: true, slot: true,
dicData: contractApprovalStatusOptions, dicData: contractApprovalStatusOptions,
minWidth: 130, minWidth: 130,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
fixed: 'right',
}, },
{ {
label: '当前节点', label: '当前节点',
@@ -281,53 +480,136 @@ export const option = createCrudOption([
{ label: '关闭', value: 0 }, { label: '关闭', value: 0 },
{ label: '开启', value: 1 }, { label: '开启', value: 1 },
], ],
value: 0, value: 1,
hide: true,
display: false,
minWidth: 110, minWidth: 110,
}, },
{
label: '合同主文件JSON',
prop: 'contractFileJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '其它附件JSON',
prop: 'attachmentsJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '计费方案JSON',
prop: 'billingPlanJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '结算生成规则JSON',
prop: 'settlementRuleJson',
type: 'textarea',
span: 24,
hide: true,
},
{
label: '对账配置JSON',
prop: 'reconciliationJson',
type: 'textarea',
span: 24,
hide: true,
},
{ {
label: '备注', label: '备注',
prop: 'remark', prop: 'remark',
type: 'textarea', type: 'textarea',
span: 24, span: 24,
hide: true, hide: true,
order: 40,
maxlength: 2000, maxlength: 2000,
showWordLimit: true, showWordLimit: true,
rules: textRule('备注', 2000), rules: textRule('备注', 2000),
}, },
...auditColumns, {
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;
option.dialogTop = '10px';
option.dialogCloseBtn = true;
option.menuWidth = 320;

View 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,
};

View File

@@ -1,4 +1,11 @@
import { auditColumns, createCrudOption, nodeOptions, processStatusOptions, selectRule, textRule } from './common'; import {
auditColumns,
createCrudOption,
nodeOptions,
processStatusOptions,
selectRule,
textRule,
} from './common';
export const config = { export const config = {
title: '过程配置', title: '过程配置',
@@ -12,92 +19,164 @@ export const config = {
deleteStatus: [0, 2], deleteStatus: [0, 2],
}; };
export const option = createCrudOption([ export const option = {
{ ...createCrudOption([
label: '配置编号', {
prop: 'configCode', label: '',
search: true, prop: 'basicInfo',
minWidth: 130, formslot: true,
addDisplay: false, span: 24,
editDisabled: true, hide: true,
}, },
{ {
label: '配置名称', label: '配置名称',
prop: 'configName', prop: 'configName',
search: true, search: true,
minWidth: 150, searchOrder: 6,
rules: textRule('配置名称', 100, true), searchSpan: 6,
}, searchPlaceholder: '请输入',
{ span: 12,
label: '项目ID集合', minWidth: 150,
prop: 'projectIds', addDisplay: false,
hide: true, editDisplay: false,
rules: textRule('项目ID集合', 1000, true), rules: textRule('配置名称', 100, true),
}, },
{ {
label: '项目', label: '配置编号',
prop: 'projectNames', prop: 'configCode',
search: true, search: true,
type: 'textarea', searchOrder: 4,
minRows: 2, searchSpan: 6,
minWidth: 180, searchPlaceholder: '请输入',
rules: textRule('项目', 1000, true), minWidth: 130,
}, addDisplay: false,
{ editDisplay: false,
label: '包含过程节点', editDisabled: true,
prop: 'includedNodes', },
search: true, {
type: 'select', label: '项目',
multiple: true, prop: 'projectNames',
dicData: nodeOptions, formslot: true,
minWidth: 180, search: true,
rules: selectRule('包含过程节点'), searchOrder: 5,
}, searchType: 'input',
{ searchSpan: 6,
label: '默认完成运输天数', searchPlaceholder: '请输入',
prop: 'defaultFinishDays', type: 'textarea',
type: 'number', minRows: 2,
min: 1, span: 12,
max: 999, minWidth: 180,
minWidth: 150, dicData: [],
}, filterable: true,
{ addDisplay: false,
label: '状态', editDisplay: false,
prop: 'status', rules: textRule('项目', 1000, true),
type: 'select', },
search: true, {
dicData: processStatusOptions, label: '过程节点',
slot: true, prop: 'includedNodes',
minWidth: 100, type: 'select',
addDisplay: false, multiple: true,
editDisplay: false, dicData: nodeOptions,
}, minWidth: 260,
{ overHidden: false,
label: '所属组织', slot: true,
prop: 'deptName', addDisplay: false,
search: true, editDisplay: false,
minWidth: 150, rules: selectRule('过程节点'),
addDisplay: false, },
editDisplay: false, {
}, label: '默认运输完成天数',
{ prop: 'defaultFinishDays',
label: '节点配置JSON', formslot: true,
prop: 'nodeConfigJson', type: 'number',
type: 'textarea', min: 0,
minRows: 6, max: 999,
span: 24, span: 12,
hide: true, minWidth: 170,
}, addDisplay: false,
{ editDisplay: false,
label: '备注', },
prop: 'remark', {
type: 'textarea', label: '备注',
minRows: 4, prop: 'remark',
span: 24, type: 'textarea',
hide: true, minRows: 4,
maxlength: 500, span: 24,
showWordLimit: true, minWidth: 180,
rules: textRule('备注', 500), addDisplay: false,
}, editDisplay: false,
...auditColumns, maxlength: 500,
]); showWordLimit: true,
rules: textRule('备注', 500),
},
{
label: '组织',
prop: 'deptName',
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
...auditColumns
.filter(column => ['updateTime', 'createTime'].includes(column.prop))
.map(column => ({ ...column, minWidth: 190 }))
.sort(
(first, second) =>
['updateTime', 'createTime'].indexOf(first.prop) -
['updateTime', 'createTime'].indexOf(second.prop)
),
{
label: '项目ID集合',
prop: 'projectIds',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
rules: textRule('项目ID集合', 1000, true),
},
{
label: '状态',
prop: 'status',
type: 'select',
search: true,
searchOrder: 1,
searchSpan: 6,
searchPlaceholder: '请选择',
dicData: processStatusOptions,
slot: true,
hide: true,
fixed: false,
addDisplay: false,
editDisplay: false,
},
{
label: '组织',
prop: 'searchDeptId',
searchProp: 'deptId',
type: 'select',
search: true,
searchOrder: 2,
searchSpan: 6,
searchPlaceholder: '请选择',
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
dicData: [],
filterable: true,
},
{
label: '',
prop: 'nodeConfigJson',
formslot: true,
span: 24,
hide: true,
},
]),
saveBtnText: '保存',
updateBtnText: '保存',
dialogTop: '10px',
dialogWidth: '96%',
menuWidth: 220,
};

View File

@@ -10,7 +10,6 @@ import {
selectRule, selectRule,
settlementModeOptions, settlementModeOptions,
textRule, textRule,
transportTypeOptions,
} from './common'; } from './common';
const amountRules = label => [ const amountRules = label => [
@@ -18,12 +17,32 @@ const amountRules = label => [
nonNegativeRule(label), 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,
}));
};
const formatUserRealName = (row, role) =>
row[`${role}RealName`] ||
row[`${role}UserRealName`] ||
row[`${role}User`]?.realName ||
row[role]?.realName ||
row[`${role}UserName`] ||
'';
export const config = { export const config = {
title: '项目管理', title: '项目管理',
permission: 'project_apply', permission: 'project_apply',
exportUrl: '/blade-transport/project-apply/export-project-apply', exportUrl: '/blade-transport/project-apply/export-project-apply',
exportName: '项目立项', exportName: '项目立项',
enableAllDept: true, enableAllDept: false,
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
statusTextProp: 'approvalStatusName', statusTextProp: 'approvalStatusName',
deleteStatus: ['draft', 'withdrawn', 'rejected'], deleteStatus: ['draft', 'withdrawn', 'rejected'],
@@ -31,25 +50,22 @@ export const config = {
operations: [ operations: [
{ {
action: 'submitApproval', action: 'submitApproval',
label: '提交审批', label: '提交',
icon: 'el-icon-position',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['draft', 'withdrawn', 'rejected'], status: ['draft'],
permission: 'project_apply_submit', permission: 'project_apply_submit',
}, },
{ {
action: 'withdraw', action: 'withdraw',
label: '撤回', label: '撤回',
icon: 'el-icon-refresh-left',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing'], status: ['reviewing'],
permission: 'project_apply_withdraw', permission: 'project_apply_withdraw',
}, },
{ {
action: 'approve', action: 'approve',
label: '审批通过', label: '通过',
type: 'success', type: 'success',
icon: 'el-icon-check',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'], status: ['reviewing', 'change_reviewing'],
permission: 'project_apply_approve', permission: 'project_apply_approve',
@@ -58,25 +74,21 @@ export const config = {
action: 'reject', action: 'reject',
label: '审批驳回', label: '审批驳回',
type: 'warning', type: 'warning',
icon: 'el-icon-close',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing', 'change_reviewing'], status: ['reviewing', 'change_reviewing'],
permission: 'project_apply_reject', permission: 'project_apply_reject',
}, },
{ {
action: 'startChange', action: 'startChange',
label: '发起变更', label: '变更',
icon: 'el-icon-edit-outline',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['approved', 'change_approved'], status: ['approved'],
permission: 'project_apply_change', permission: 'project_apply_change',
prompt: '请输入变更内容与原因',
}, },
{ {
action: 'voidProject', action: 'voidProject',
label: '作废', label: '作废',
type: 'danger', type: 'danger',
icon: 'el-icon-delete',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['approved', 'change_approved'], status: ['approved', 'change_approved'],
permission: 'project_apply_void', permission: 'project_apply_void',
@@ -90,7 +102,9 @@ export const option = createCrudOption([
label: '立项申请单号', label: '立项申请单号',
prop: 'applyNo', prop: 'applyNo',
search: true, search: true,
minWidth: 160, searchPlaceholder: '请输入',
searchOrder: 7,
minWidth: 220,
addDisplay: false, addDisplay: false,
editDisabled: true, editDisabled: true,
}, },
@@ -105,6 +119,8 @@ export const option = createCrudOption([
label: '项目名称', label: '项目名称',
prop: 'projectName', prop: 'projectName',
search: true, search: true,
searchPlaceholder: '请输入',
searchOrder: 6,
minWidth: 180, minWidth: 180,
maxlength: 50, maxlength: 50,
rules: textRule('项目名称', 50, true), rules: textRule('项目名称', 50, true),
@@ -112,6 +128,7 @@ export const option = createCrudOption([
{ {
label: '项目简称', label: '项目简称',
prop: 'projectShortName', prop: 'projectShortName',
hide: true,
minWidth: 140, minWidth: 140,
maxlength: 20, maxlength: 20,
rules: textRule('项目简称', 20, true), rules: textRule('项目简称', 20, true),
@@ -121,13 +138,28 @@ export const option = createCrudOption([
prop: 'projectType', prop: 'projectType',
type: 'select', type: 'select',
search: true, search: true,
searchPlaceholder: '请选择',
searchOrder: 3,
dicData: projectTypeOptions, dicData: projectTypeOptions,
minWidth: 120, minWidth: 120,
rules: selectRule('项目类型'), rules: selectRule('项目类型'),
}, },
{
label: '客户名称',
prop: 'customerNames',
minWidth: 180,
rules: textRule('客户名称', 255, true),
},
{
label: '下游承运商',
prop: 'carrierNames',
minWidth: 180,
rules: textRule('下游承运商', 255, true),
},
{ {
label: '业务部门', label: '业务部门',
prop: 'businessDeptName', prop: 'businessDeptName',
hide: true,
minWidth: 150, minWidth: 150,
rules: textRule('业务部门', 50, true), rules: textRule('业务部门', 50, true),
}, },
@@ -135,6 +167,8 @@ export const option = createCrudOption([
label: '承办部门', label: '承办部门',
prop: 'undertakeDeptName', prop: 'undertakeDeptName',
search: true, search: true,
searchPlaceholder: '请输入',
searchOrder: 5,
minWidth: 150, minWidth: 150,
rules: textRule('承办部门', 50, true), rules: textRule('承办部门', 50, true),
}, },
@@ -146,14 +180,33 @@ export const option = createCrudOption([
{ {
label: '项目负责人', label: '项目负责人',
prop: 'principalUserName', prop: 'principalUserName',
search: true,
minWidth: 130, minWidth: 130,
formatter: row => formatUserRealName(row, 'principal'),
rules: textRule('项目负责人', 50, true), rules: textRule('项目负责人', 50, true),
}, },
{
label: '项目负责人',
prop: 'principalUserId',
type: 'select',
search: true,
searchPlaceholder: '请选择',
searchOrder: 4,
filterable: true,
dicUrl: '/blade-system/user/user-list',
dicFormatter: userDicFormatter,
props: {
label: 'realName',
value: 'id',
},
hide: true,
display: false,
},
{ {
label: '项目经办人', label: '项目经办人',
prop: 'handlerUserName', prop: 'handlerUserName',
hide: true,
minWidth: 130, minWidth: 130,
formatter: row => formatUserRealName(row, 'handler'),
rules: textRule('项目经办人', 50, true), rules: textRule('项目经办人', 50, true),
}, },
{ {
@@ -162,6 +215,7 @@ export const option = createCrudOption([
type: 'select', type: 'select',
dicData: projectSourceOptions, dicData: projectSourceOptions,
value: '商务洽谈', value: '商务洽谈',
hide: true,
minWidth: 120, minWidth: 120,
}, },
{ {
@@ -169,6 +223,7 @@ export const option = createCrudOption([
prop: 'fundLimit', prop: 'fundLimit',
type: 'number', type: 'number',
precision: 2, precision: 2,
hide: true,
minWidth: 190, minWidth: 190,
rules: amountRules('项目资金使用额度'), rules: amountRules('项目资金使用额度'),
}, },
@@ -177,6 +232,7 @@ export const option = createCrudOption([
prop: 'receivableLimit', prop: 'receivableLimit',
type: 'number', type: 'number',
precision: 2, precision: 2,
hide: true,
minWidth: 200, minWidth: 200,
rules: amountRules('项目应收账款额度'), rules: amountRules('项目应收账款额度'),
}, },
@@ -184,6 +240,7 @@ export const option = createCrudOption([
label: '应收账款回款期限(天)', label: '应收账款回款期限(天)',
prop: 'receivableDays', prop: 'receivableDays',
type: 'number', type: 'number',
hide: true,
minWidth: 190, minWidth: 190,
rules: [{ required: true, message: '请输入应收账款回款期限', trigger: 'blur' }], rules: [{ required: true, message: '请输入应收账款回款期限', trigger: 'blur' }],
}, },
@@ -191,30 +248,20 @@ export const option = createCrudOption([
label: '回款账期(天)', label: '回款账期(天)',
prop: 'paymentDays', prop: 'paymentDays',
type: 'number', type: 'number',
hide: true,
minWidth: 140, minWidth: 140,
rules: [{ required: true, message: '请输入回款账期', trigger: 'blur' }], rules: [{ required: true, message: '请输入回款账期', trigger: 'blur' }],
}, },
{
label: '客户名称',
prop: 'customerNames',
search: true,
minWidth: 180,
rules: textRule('客户名称', 255, true),
},
{
label: '下游承运商',
prop: 'carrierNames',
minWidth: 180,
rules: textRule('下游承运商', 255, true),
},
{ {
label: '货物类型', label: '货物类型',
prop: 'cargoType', prop: 'cargoType',
hide: true,
minWidth: 120, minWidth: 120,
}, },
{ {
label: '预估货物数量', label: '预估货物数量',
prop: 'cargoQuantity', prop: 'cargoQuantity',
hide: true,
minWidth: 150, minWidth: 150,
maxlength: 100, maxlength: 100,
}, },
@@ -224,6 +271,7 @@ export const option = createCrudOption([
type: 'date', type: 'date',
format: 'YYYY-MM-DD', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
hide: true,
minWidth: 130, minWidth: 130,
}, },
{ {
@@ -232,11 +280,13 @@ export const option = createCrudOption([
type: 'date', type: 'date',
format: 'YYYY-MM-DD', format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
hide: true,
minWidth: 130, minWidth: 130,
}, },
{ {
label: '运输线路', label: '运输线路',
prop: 'transportRoute', prop: 'transportRoute',
hide: true,
minWidth: 180, minWidth: 180,
maxlength: 100, maxlength: 100,
}, },
@@ -244,7 +294,12 @@ export const option = createCrudOption([
label: '运输类型', label: '运输类型',
prop: 'transportType', prop: 'transportType',
type: 'select', type: 'select',
dicData: transportTypeOptions, dicUrl: '/blade-system/dict-biz/dictionary?code=transport_type',
props: {
label: 'dictValue',
value: 'dictKey',
},
hide: true,
minWidth: 120, minWidth: 120,
}, },
{ {
@@ -252,6 +307,7 @@ export const option = createCrudOption([
prop: 'businessType', prop: 'businessType',
type: 'select', type: 'select',
dicData: businessTypeOptions, dicData: businessTypeOptions,
hide: true,
minWidth: 130, minWidth: 130,
}, },
{ {
@@ -259,6 +315,7 @@ export const option = createCrudOption([
prop: 'projectScale', prop: 'projectScale',
type: 'number', type: 'number',
precision: 2, precision: 2,
hide: true,
minWidth: 150, minWidth: 150,
rules: [nonNegativeRule('项目规模')], rules: [nonNegativeRule('项目规模')],
}, },
@@ -267,6 +324,7 @@ export const option = createCrudOption([
prop: 'estimatedProfit', prop: 'estimatedProfit',
type: 'number', type: 'number',
precision: 2, precision: 2,
hide: true,
minWidth: 150, minWidth: 150,
rules: [nonNegativeRule('预计利润')], rules: [nonNegativeRule('预计利润')],
}, },
@@ -275,6 +333,7 @@ export const option = createCrudOption([
prop: 'fundDemand', prop: 'fundDemand',
type: 'number', type: 'number',
precision: 2, precision: 2,
hide: true,
minWidth: 150, minWidth: 150,
rules: [nonNegativeRule('资金需求')], rules: [nonNegativeRule('资金需求')],
}, },
@@ -283,6 +342,7 @@ export const option = createCrudOption([
prop: 'settlementMode', prop: 'settlementMode',
type: 'select', type: 'select',
dicData: settlementModeOptions, dicData: settlementModeOptions,
hide: true,
minWidth: 120, minWidth: 120,
}, },
{ {
@@ -290,12 +350,13 @@ export const option = createCrudOption([
prop: 'approvalStatus', prop: 'approvalStatus',
type: 'select', type: 'select',
search: true, search: true,
searchPlaceholder: '请选择',
searchOrder: 2,
slot: true, slot: true,
dicData: projectApprovalStatusOptions, dicData: projectApprovalStatusOptions,
minWidth: 130, minWidth: 130,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
fixed: 'right',
}, },
{ {
label: '当前节点', label: '当前节点',
@@ -316,6 +377,8 @@ export const option = createCrudOption([
prop: 'effectiveType', prop: 'effectiveType',
type: 'select', type: 'select',
search: true, search: true,
searchPlaceholder: '请选择',
searchOrder: 1,
dicData: effectiveTypeOptions, dicData: effectiveTypeOptions,
value: 'temporary', value: 'temporary',
minWidth: 110, minWidth: 110,
@@ -355,5 +418,5 @@ export const option = createCrudOption([
span: 24, span: 24,
hide: true, hide: true,
}, },
...auditColumns, ...auditColumns.map(column => ({ ...column, hide: true })),
]); ]);

View File

@@ -1,167 +1,213 @@
import { import { auditColumns, createCrudOption, selectRule, textRule, transportTypeOptions } from './common';
auditColumns,
createCrudOption, const templateTypeOptions = [
templateTypeOptions, { label: '运输计划', value: '运输计划' },
transportTypeOptions, { label: '运单', value: '运单' },
selectRule, ];
textRule,
} from './common';
export const config = { export const config = {
title: '发货模板', title: '发货模板',
permission: 'shipping_template', permission: 'shipping_template',
exportUrl: '/blade-transport/shipping-template/export-shipping-template', exportUrl: '/blade-transport/shipping-template/export-shipping-template',
exportName: '发货模板', exportName: '发货模板',
enableAllDept: true, enableAllDept: false,
enableProjectSelect: true,
enableAttachmentTable: true,
enableTransportPlanForm: true,
enableTemplateCodePreview: true,
attachmentTitle: '附件',
defaultForm: {
templateType: '运输计划',
},
transportFormRequiredFields: [
['projectName', '项目'],
['contractName', '客户合同'],
['transportType', '运输方式'],
['departureAddress', '发货地址'],
['arrivalAddress', '收货地址'],
],
actions: ['copy'], actions: ['copy'],
operations: [
{
action: 'createFromTemplate',
label: '从模板新建',
permission: 'shipping_template_add',
},
],
}; };
export const option = createCrudOption([ export const option = {
{ ...createCrudOption([
label: '模板编号', {
prop: 'templateCode', label: '',
search: true, prop: 'templateInfoTitle',
minWidth: 150, formslot: true,
addDisplay: false, span: 24,
editDisabled: true, order: 400,
}, hide: true,
{ labelWidth: 0,
label: '模板名称', },
prop: 'templateName', {
search: true, label: '模板编号',
minWidth: 150, prop: 'templateCode',
rules: textRule('模板名称', 50, true), search: true,
}, searchOrder: 4,
{ span: 8,
label: '模板类型', order: 390,
prop: 'templateType', minWidth: 170,
type: 'select', disabled: true,
search: true, placeholder: '系统自动生成',
dicData: templateTypeOptions, },
minWidth: 120, {
value: '运输计划', label: '模板名称',
rules: selectRule('模板类型'), prop: 'templateName',
}, search: true,
{ searchOrder: 3,
label: '项目', span: 8,
prop: 'projectName', order: 380,
search: true, minWidth: 150,
minWidth: 150, rules: textRule('模板名称', 50, true),
rules: textRule('项目', 100, true), },
}, {
{ label: '模板类型',
label: '项目ID', prop: 'templateType',
prop: 'projectId', type: 'select',
hide: true, search: true,
}, searchOrder: 2,
{ span: 8,
label: '客户合同', order: 370,
prop: 'contractName', dicData: templateTypeOptions,
minWidth: 160, minWidth: 120,
rules: textRule('客户合同', 100, true), rules: selectRule('模板类型'),
}, },
{ {
label: '客户合同ID', label: '备注',
prop: 'contractId', prop: 'remark',
hide: true, type: 'textarea',
}, minRows: 3,
{ span: 24,
label: '运输类型', order: 360,
prop: 'transportType', minWidth: 180,
type: 'select', maxlength: 200,
dicData: transportTypeOptions, showWordLimit: true,
minWidth: 130, rules: textRule('备注', 200),
rules: selectRule('运输类型'), },
}, {
{ label: '',
label: '发货地', prop: 'basicInfoTitle',
prop: 'departureName', formslot: true,
minWidth: 140, span: 24,
rules: textRule('发货地', 100, true), order: 350,
}, hide: true,
{ labelWidth: 0,
label: '发货地址', },
prop: 'departureAddress', {
minWidth: 220, label: '项目',
rules: textRule('发货地址', 255, true), prop: 'projectName',
}, formslot: true,
{ search: true,
label: '发货联系人', searchOrder: 1,
prop: 'departureContact', span: 8,
minWidth: 120, order: 340,
rules: textRule('发货联系人', 20), minWidth: 150,
}, rules: textRule('项目', 100, true),
{ },
label: '发货联系方式', {
prop: 'departurePhone', label: '客户合同',
minWidth: 140, prop: 'contractName',
rules: textRule('发货联系方式', 20), formslot: true,
}, span: 8,
{ order: 330,
label: '收货地', minWidth: 160,
prop: 'arrivalName', rules: textRule('客户合同', 100, true),
minWidth: 140, },
rules: textRule('收货地', 100, true), {
}, label: '运输方式',
{ prop: 'transportType',
label: '收货地址', type: 'select',
prop: 'arrivalAddress', span: 8,
minWidth: 220, order: 320,
rules: textRule('收货地址', 255, true), dicData: transportTypeOptions,
}, minWidth: 130,
{ rules: selectRule('运输方式'),
label: '收货联系人', },
prop: 'arrivalContact', {
minWidth: 120, label: '',
rules: textRule('收货联系人', 20), prop: 'shippingInfoTitle',
}, formslot: true,
{ span: 24,
label: '收货联系方式', order: 310,
prop: 'arrivalPhone', hide: true,
minWidth: 140, labelWidth: 0,
rules: textRule('收货联系方式', 20), },
}, {
{ label: '发货地址',
label: '货物信息JSON', prop: 'departureAddress',
prop: 'goodsJson', formslot: true,
type: 'textarea', span: 24,
minRows: 5, order: 300,
span: 24, minWidth: 220,
hide: true, rules: textRule('发货地址', 255, true),
}, },
{ {
label: '运费信息JSON', label: '收货地址',
prop: 'freightJson', prop: 'arrivalAddress',
type: 'textarea', formslot: true,
minRows: 4, span: 24,
span: 24, order: 290,
hide: true, minWidth: 220,
}, rules: textRule('收货地址', 255, true),
{ },
label: '附件JSON', {
prop: 'attachmentsJson', label: '',
type: 'textarea', prop: 'goodsInfoTitle',
minRows: 3, formslot: true,
span: 24, span: 24,
hide: true, order: 280,
}, hide: true,
{ labelWidth: 0,
label: '所属组织', },
prop: 'deptName', {
minWidth: 150, label: '',
addDisplay: false, prop: 'goodsJson',
editDisplay: false, type: 'textarea',
}, formslot: true,
{ span: 24,
label: '备注', order: 270,
prop: 'remark', hide: true,
type: 'textarea', labelWidth: '0px',
minRows: 4, className: 'business-crud-page__full-form-item',
span: 24, },
hide: true, {
maxlength: 200, label: '',
showWordLimit: true, prop: 'attachmentTitle',
rules: textRule('备注', 200), formslot: true,
}, span: 24,
...auditColumns, 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%',
};

View File

@@ -1,27 +1,67 @@
import { approvalStatusOptions, auditColumns, createCrudOption, nonNegativeRule, textRule } from './common'; 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 = { export const config = {
title: '临时额度管理', title: '临时额度管理',
permission: 'temporary_credit_limit', permission: 'temporary_credit_limit',
exportUrl: '/blade-transport/temporary-credit-limit/export-temporary-credit-limit', exportUrl: '/blade-transport/temporary-credit-limit/export-temporary-credit-limit',
exportName: '临时额度申请', exportName: '临时额度申请',
enableAllDept: true, enableAllDept: false,
enableProjectSelect: true,
projectQueryParams: {
temporaryCreditLimitSelectable: true,
},
enableAttachmentTable: true,
enableDraftSave: true,
saveAsDraft: true,
defaultForm: {
usedFundLimit: 0,
remainingFundLimit: 0,
},
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
statusTextProp: 'approvalStatusName', statusTextProp: 'approvalStatusName',
deleteStatus: ['draft', 'withdrawn', 'rejected'], deleteStatus: ['draft', 'withdrawn', 'rejected', '草稿'],
editStatus: ['draft', 'withdrawn', 'rejected'], editStatus: ['draft', 'withdrawn', 'rejected', '草稿', '已撤回'],
ignoreReadonlyEditStatus: ['draft', 'withdrawn', '草稿', '已撤回'],
ignoreReadonlyDeleteStatus: ['draft', '草稿'],
operations: [ operations: [
{ {
action: 'submitApproval', action: 'submitApproval',
label: '提交审批', label: '提交',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['draft', 'withdrawn', 'rejected'], status: ['draft', 'withdrawn', 'rejected'],
permission: 'temporary_credit_limit_submit', permission: 'temporary_credit_limit_submit',
}, },
{
action: 'flow',
label: '流程',
statusProp: 'approvalStatus',
status: ['reviewing'],
permission: 'temporary_credit_limit_view',
},
{ {
action: 'withdraw', action: 'withdraw',
label: '撤回', label: '撤回',
icon: 'el-icon-refresh-left',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing'], status: ['reviewing'],
permission: 'temporary_credit_limit_withdraw', permission: 'temporary_credit_limit_withdraw',
@@ -30,7 +70,6 @@ export const config = {
action: 'approve', action: 'approve',
label: '审批通过', label: '审批通过',
type: 'success', type: 'success',
icon: 'el-icon-check',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing'], status: ['reviewing'],
permission: 'temporary_credit_limit_approve', permission: 'temporary_credit_limit_approve',
@@ -39,7 +78,6 @@ export const config = {
action: 'reject', action: 'reject',
label: '审批驳回', label: '审批驳回',
type: 'warning', type: 'warning',
icon: 'el-icon-close',
statusProp: 'approvalStatus', statusProp: 'approvalStatus',
status: ['reviewing'], status: ['reviewing'],
permission: 'temporary_credit_limit_reject', permission: 'temporary_credit_limit_reject',
@@ -47,145 +85,192 @@ export const config = {
], ],
}; };
export const option = createCrudOption([ export const option = {
{ ...createCrudOption([
label: '申请单号', {
prop: 'applicationNo', label: '申请单号',
search: true, prop: 'applicationNo',
minWidth: 160, search: true,
addDisplay: false, searchOrder: 5,
editDisabled: true, minWidth: 160,
}, addDisplay: false,
{ editDisplay: false,
label: '项目名称', editDisabled: true,
prop: 'projectName', },
search: true, {
minWidth: 180, label: '项目名称',
rules: textRule('项目名称', 100, true), prop: 'projectName',
}, search: true,
{ searchOrder: 4,
label: '项目ID', searchType: 'select',
prop: 'projectId', formslot: true,
hide: true, dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
}, dicFormatter: listDicFormatter,
{ props: {
label: '项目编号', label: 'projectName',
prop: 'projectCode', value: 'projectName',
minWidth: 150, },
rules: textRule('项目编号', 50, true), filterable: true,
}, span: 12,
{ minWidth: 180,
label: '承办部门', rules: textRule('项目名称', 100, true),
prop: 'undertakeDeptName', },
minWidth: 150, {
rules: textRule('承办部门', 50, true), label: '项目ID',
}, prop: 'projectId',
{ hide: true,
label: '项目资金使用额度(万元)', display: false,
prop: 'projectFundLimit', },
type: 'number', {
precision: 2, label: '项目编号',
minWidth: 200, prop: 'projectCode',
editDisabled: true, hide: true,
rules: [nonNegativeRule('项目资金使用额度')], disabled: true,
}, span: 12,
{ minWidth: 150,
label: '已使用项目资金额度(万元)', rules: textRule('项目编号', 50),
prop: 'usedFundLimit', },
type: 'number', {
precision: 2, label: '承办部门',
minWidth: 220, prop: 'undertakeDeptName',
value: 0, hide: true,
editDisabled: true, disabled: true,
rules: [nonNegativeRule('已使用项目资金额度')], span: 12,
}, minWidth: 150,
{ rules: textRule('承办部门', 50, true),
label: '剩余项目资金使用额度(万元)', },
prop: 'remainingFundLimit', {
type: 'number', label: '项目资金使用额度(万元)',
precision: 2, prop: 'projectFundLimit',
minWidth: 230, hide: true,
editDisabled: true, disabled: true,
rules: [nonNegativeRule('剩余项目资金使用额度')], span: 12,
}, minWidth: 200,
{ rules: [nonNegativeRule('项目资金使用额度')],
label: '申请临时额度(万元)', },
prop: 'applyLimit', {
type: 'number', label: '已使用项目资金使用额度(万元)',
precision: 2, prop: 'usedFundLimit',
minWidth: 180, hide: true,
rules: [ disabled: true,
{ required: true, message: '请输入申请临时额度', trigger: 'blur' }, span: 12,
nonNegativeRule('申请临时额度'), minWidth: 220,
], value: 0,
}, rules: [nonNegativeRule('已使用项目资金额度')],
{ },
label: '申请有效期至', {
prop: 'validUntil', label: '剩余项目资金使用额度(万元)',
type: 'date', prop: 'remainingFundLimit',
format: 'YYYY-MM-DD', hide: true,
valueFormat: 'YYYY-MM-DD', disabled: true,
minWidth: 140, span: 12,
rules: [{ required: true, message: '请选择申请有效期至', trigger: 'change' }], minWidth: 230,
}, value: 0,
{ rules: [nonNegativeRule('剩余项目资金使用额度')],
label: '申请部门', },
prop: 'applyDeptName', {
search: true, label: '申请临时额度(万元)',
minWidth: 150, prop: 'applyLimit',
addDisplay: false, formslot: true,
editDisabled: true, span: 12,
}, minWidth: 180,
{ rules: [
label: '申请人', { required: true, message: '请输入申请临时额度', trigger: 'blur' },
prop: 'applicantName', nonNegativeRule('申请临时额度'),
search: true, ],
minWidth: 120, },
addDisplay: false, {
editDisabled: true, label: '申请有效期至',
}, prop: 'validUntil',
{ type: 'date',
label: '审批状态', format: 'YYYY-MM-DD',
prop: 'approvalStatus', valueFormat: 'YYYY-MM-DD',
type: 'select', span: 12,
search: true, minWidth: 140,
slot: true, rules: [{ required: true, message: '请选择申请有效期至', trigger: 'change' }],
dicData: approvalStatusOptions, },
minWidth: 130, {
addDisplay: false, label: '申请部门',
editDisplay: false, prop: 'applyDeptName',
fixed: 'right', search: true,
}, searchOrder: 2,
{ searchType: 'select',
label: '当前节点', dicUrl: '/blade-system/dept/select',
prop: 'currentNode', props: {
minWidth: 140, label: 'deptName',
addDisplay: false, value: 'deptName',
editDisplay: false, },
}, filterable: true,
{ minWidth: 150,
label: '当前处理人', addDisplay: false,
prop: 'currentProcessor', editDisplay: false,
minWidth: 130, editDisabled: true,
addDisplay: false, },
editDisplay: false, {
}, label: '申请人',
{ prop: 'applicantName',
label: '附件JSON', search: true,
prop: 'attachmentsJson', searchOrder: 3,
type: 'textarea', searchType: 'select',
span: 24, dicUrl: '/blade-system/user/user-list',
hide: true, dicFormatter: userDicFormatter,
}, props: {
{ label: 'realName',
label: '备注', value: 'realName',
prop: 'remark', },
type: 'textarea', filterable: true,
span: 24, minWidth: 120,
hide: true, addDisplay: false,
maxlength: 500, editDisplay: false,
showWordLimit: true, editDisabled: true,
rules: textRule('备注', 500), },
}, {
...auditColumns, 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: 1010,
index: false,
};

View File

@@ -2,174 +2,548 @@ import {
auditColumns, auditColumns,
createCrudOption, createCrudOption,
dataSourceOptions, dataSourceOptions,
phoneRule,
planStatusOptions, planStatusOptions,
selectRule, selectRule,
textRule, textRule,
transportTypeOptions,
} from './common'; } 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 = { export const config = {
title: '运输计划', title: '运输计划',
permission: 'transport_plan', permission: 'transport_plan',
exportUrl: '/blade-transport/transport-plan/export-transport-plan', exportUrl: '/blade-transport/transport-plan/export-transport-plan',
exportName: '运输计划', exportName: '运输计划',
enableAllDept: true, 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'], actions: ['copy', 'cancel', 'complete'],
statusProp: 'businessStatus', statusProp: 'businessStatus',
statusTextProp: 'businessStatusName', statusTextProp: 'businessStatusName',
deleteStatus: ['draft'], deleteStatus: ['draft'],
editStatus: ['draft', 'waiting_dispatch'], 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([ export const option = {
{ ...createCrudOption([
label: '计划单号', {
prop: 'planNo', label: '',
search: true, prop: 'basicInfoTitle',
minWidth: 150, formslot: true,
addDisplay: false, span: 24,
editDisabled: true, order: 400,
}, hide: true,
{ labelWidth: 0,
label: '计划名称', },
prop: 'planName', {
search: true, label: '计划单号',
minWidth: 150, prop: 'planNo',
rules: textRule('计划名称', 50, true), search: true,
}, searchOrder: 13,
{ span: 6,
label: '项目', order: 370,
prop: 'projectName', minWidth: 150,
minWidth: 150, disabled: true,
rules: textRule('项目', 100, true), placeholder: '系统自动生成',
}, },
{ {
label: '项目ID', label: '计划名称',
prop: 'projectId', prop: 'planName',
hide: true, search: true,
}, searchOrder: 12,
{ span: 6,
label: '客户合同', order: 380,
prop: 'contractName', minWidth: 150,
minWidth: 160, rules: textRule('计划名称', 50, true),
rules: textRule('客户合同', 100, true), },
}, {
{ label: '运输方式',
label: '客户合同ID', prop: 'transportType',
prop: 'contractId', type: 'select',
hide: true, search: true,
}, searchOrder: 10,
{ span: 6,
label: '客户名称', order: 360,
prop: 'customerName', dicUrl: '/blade-system/dict-biz/dictionary?code=transport_type',
search: true, props: {
minWidth: 150, label: 'dictValue',
}, value: 'dictKey',
{ },
label: '运输类型', minWidth: 130,
prop: 'transportType', rules: selectRule('运输类型'),
type: 'select', },
search: true, {
dicData: transportTypeOptions, label: '货物信息',
minWidth: 130, prop: 'goodsInfo',
rules: selectRule('运输类型'), formatter: row => formatGoodsInfo(row),
}, minWidth: 320,
{ className: 'business-crud-page__goods-info-cell',
label: '计划开始日期', overHidden: false,
prop: 'planStartDate', showOverflowTooltip: false,
type: 'date', addDisplay: false,
format: 'YYYY-MM-DD', editDisplay: false,
valueFormat: 'YYYY-MM-DD', viewDisplay: false,
search: true, },
minWidth: 130, {
}, label: '调度进度',
{ prop: 'dispatchProgress',
label: '计划结束日期', formatter: row => formatDispatchProgress(row),
prop: 'planEndDate', minWidth: 120,
type: 'date', addDisplay: false,
format: 'YYYY-MM-DD', editDisplay: false,
valueFormat: 'YYYY-MM-DD', viewDisplay: false,
search: true, },
minWidth: 130, {
}, label: '发货地址',
{ prop: 'departureAddress',
label: '发货地', formslot: true,
prop: 'departureName', search: true,
minWidth: 140, searchOrder: 7,
rules: textRule('发货地', 100, true), span: 24,
}, order: 310,
{ minWidth: 220,
label: '发货地址', rules: textRule('发货地址', 255, true),
prop: 'departureAddress', },
search: true, {
minWidth: 220, label: '到货地址',
rules: textRule('发货地址', 255, true), prop: 'arrivalAddress',
}, formslot: true,
{ search: true,
label: '收货地', searchOrder: 6,
prop: 'arrivalName', span: 24,
minWidth: 140, order: 300,
rules: textRule('收货地', 100, true), minWidth: 220,
}, rules: textRule('收货地址', 255, true),
{ },
label: '收货地址', {
prop: 'arrivalAddress', label: '项目名称',
search: true, prop: 'projectName',
minWidth: 220, formslot: true,
rules: textRule('收货地址', 255, true), search: true,
}, searchOrder: 11,
{ searchType: 'select',
label: '货物信息JSON', span: 6,
prop: 'goodsJson', order: 400,
type: 'textarea', dicUrl: '/blade-transport/project-apply/list?current=1&size=9999',
minRows: 5, dicFormatter: listDicFormatter,
span: 24, props: {
hide: true, label: 'projectName',
}, value: 'projectName',
{ },
label: '附件JSON', filterable: true,
prop: 'attachmentsJson', minWidth: 150,
type: 'textarea', rules: textRule('项目', 100, true),
minRows: 3, },
span: 24, {
hide: true, label: '客户名称',
}, prop: 'customerName',
{ search: true,
label: '数据来源', searchOrder: 5,
prop: 'dataSource', minWidth: 150,
type: 'select', addDisplay: false,
search: true, editDisplay: false,
dicData: dataSourceOptions, },
minWidth: 120, {
}, label: '计划开始日期',
{ prop: 'planStartDate',
label: '业务状态', type: 'date',
prop: 'businessStatus', format: 'YYYY-MM-DD',
type: 'select', valueFormat: 'YYYY-MM-DD',
slot: true, span: 6,
search: true, order: 350,
dicData: planStatusOptions, minWidth: 130,
minWidth: 120, },
addDisplay: false, {
editDisplay: false, label: '计划结束日期',
}, prop: 'planEndDate',
{ type: 'date',
label: '所属组织', format: 'YYYY-MM-DD',
prop: 'deptName', valueFormat: 'YYYY-MM-DD',
minWidth: 150, span: 6,
addDisplay: false, order: 340,
editDisplay: false, minWidth: 130,
}, },
{ {
label: '备注', label: '数据来源',
prop: 'remark', prop: 'dataSource',
type: 'textarea', type: 'select',
minRows: 4, search: true,
span: 24, searchOrder: 1,
hide: true, dicData: dataSourceOptions,
maxlength: 200, minWidth: 120,
showWordLimit: true, addDisplay: false,
rules: textRule('备注', 200), editDisplay: false,
}, },
...auditColumns, {
]); 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%',
};

View File

@@ -2,18 +2,119 @@ import {
auditColumns, auditColumns,
createCrudOption, createCrudOption,
dataSourceOptions, dataSourceOptions,
phoneRule,
selectRule, selectRule,
textRule, textRule,
transportTypeOptions,
waybillStatusOptions, waybillStatusOptions,
} from './common'; } 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 = { export const config = {
title: '运单管理', title: '运单管理',
permission: 'waybill_manage', permission: 'waybill_manage',
exportUrl: '/blade-transport/waybill-manage/export-waybill-manage', exportUrl: '/blade-transport/waybill-manage/export-waybill-manage',
exportName: '运单管理', exportName: '运单管理',
enableAllDept: true, 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'], actions: ['copy', 'cancel', 'reassign', 'complete', 'batchComplete'],
statusProp: 'businessStatus', statusProp: 'businessStatus',
statusTextProp: 'businessStatusName', statusTextProp: 'businessStatusName',
@@ -21,234 +122,601 @@ export const config = {
editStatus: ['draft', 'pending'], editStatus: ['draft', 'pending'],
}; };
export const option = createCrudOption([ export const option = {
{ ...createCrudOption([
label: '运单号', {
prop: 'waybillNo', label: '',
search: true, prop: 'basicInfoTitle',
minWidth: 150, formslot: true,
addDisplay: false, span: 24,
editDisabled: true, order: 900,
}, hide: true,
{ labelWidth: 0,
label: '项目', },
prop: 'projectName', {
search: true, label: '运单号',
minWidth: 150, prop: 'waybillNo',
rules: textRule('项目', 100, true), search: true,
}, searchOrder: 23,
{ minWidth: 150,
label: '项目ID', addDisplay: false,
prop: 'projectId', editDisabled: true,
hide: true, },
}, {
{ label: '配载单号',
label: '客户合同', prop: 'loadingNo',
prop: 'contractName', search: true,
minWidth: 160, searchOrder: 5,
rules: textRule('客户合同', 100, true), span: 6,
}, order: 840,
{ minWidth: 140,
label: '客户合同ID', },
prop: 'contractId', {
hide: true, label: '总单号',
}, prop: 'masterNo',
{ search: true,
label: '客户名称', searchLabel: '多联总单',
prop: 'customerName', searchOrder: 6,
search: true, span: 6,
minWidth: 150, order: 830,
}, minWidth: 140,
{ },
label: '运输类型', {
prop: 'transportType', label: '项目',
type: 'select', prop: 'projectName',
search: true, formslot: true,
dicData: transportTypeOptions, search: true,
minWidth: 130, searchOrder: 22,
rules: selectRule('运输类型'), span: 6,
}, order: 890,
{ minWidth: 150,
label: '货物名称', rules: textRule('项目', 100, true),
prop: 'cargoName', },
search: true, {
minWidth: 150, label: '客户',
rules: textRule('货物名称', 100, true), prop: 'customerName',
}, search: true,
{ searchLabel: '客户名称',
label: '货物类型', searchOrder: 21,
prop: 'cargoType', minWidth: 150,
search: true, addDisplay: false,
minWidth: 130, editDisplay: false,
rules: textRule('货物类型', 100, true), viewDisplay: false,
}, display: false,
{ },
label: '发货地址', {
prop: 'departureAddress', label: '车牌号/航班号/船号/班列号',
search: true, prop: 'vehicleNo',
minWidth: 220, search: true,
rules: textRule('发货地址', 255, true), searchLabel: '车/船/航班/班列',
}, searchOrder: 13,
{ minWidth: 210,
label: '收货地址', display: false,
prop: 'arrivalAddress', },
search: true, {
minWidth: 220, label: '司机',
rules: textRule('收货地址', 255, true), prop: 'driverName',
}, search: true,
{ searchLabel: '司机名称',
label: '承运商名称', searchOrder: 14,
prop: 'carrierName', minWidth: 120,
search: true, display: false,
minWidth: 150, },
}, {
{ label: '联系方式',
label: '司机姓名', prop: 'driverPhone',
prop: 'driverName', formatter: row => getFirstValue(row, ['driverPhone', 'driverMobile', 'driverTel']),
search: true, minWidth: 140,
minWidth: 120, addDisplay: false,
}, editDisplay: false,
{ viewDisplay: false,
label: '车/船/航班/班列号', display: false,
prop: 'vehicleNo', },
search: true, {
minWidth: 170, label: '运输方式',
}, prop: 'transportMode',
{ type: 'select',
label: '原始单号', search: true,
prop: 'originalNo', searchOrder: 1,
search: true, formatter: row => formatTransportMode(row),
minWidth: 140, ...transportTypeDict,
}, minWidth: 130,
{ addDisplay: false,
label: '业务状态', editDisplay: false,
prop: 'businessStatus', viewDisplay: false,
type: 'select', },
slot: true, {
search: true, label: '运输类型',
dicData: waybillStatusOptions, prop: 'transportType',
minWidth: 120, type: 'select',
addDisplay: false, search: true,
editDisplay: false, searchOrder: 20,
}, span: 6,
{ order: 850,
label: '数据来源', ...transportTypeDict,
prop: 'dataSource', minWidth: 130,
type: 'select', rules: selectRule('运输类型'),
search: true, },
dicData: dataSourceOptions, {
minWidth: 120, label: '过程节点',
}, prop: 'currentProcessNode',
{ minWidth: 140,
label: '开始日期', addDisplay: false,
prop: 'startDate', editDisplay: false,
type: 'date', viewDisplay: false,
format: 'YYYY-MM-DD', display: false,
valueFormat: 'YYYY-MM-DD', },
search: true, {
minWidth: 130, label: '承运类型',
}, prop: 'carrierType',
{ formatter: row => getFirstValue(row, ['carrierTypeName', 'carrierType']),
label: '结束日期', minWidth: 120,
prop: 'endDate', addDisplay: false,
type: 'date', editDisplay: false,
format: 'YYYY-MM-DD', viewDisplay: false,
valueFormat: 'YYYY-MM-DD', display: false,
search: true, },
minWidth: 130, {
}, label: '承运商',
{ prop: 'carrierName',
label: '计划名称', search: true,
prop: 'planName', searchLabel: '承运商名称',
search: true, searchOrder: 15,
minWidth: 150, minWidth: 150,
}, display: false,
{ },
label: '多联总单', {
prop: 'masterNo', label: '货物信息',
search: true, prop: 'goodsInfo',
minWidth: 140, formatter: row => formatGoodsInfo(row),
}, minWidth: 260,
{ overHidden: true,
label: '配载单号', addDisplay: false,
prop: 'loadingNo', editDisplay: false,
search: true, viewDisplay: false,
minWidth: 140, },
}, {
{ label: '发货地址',
label: '运单批次号', prop: 'departureAddress',
prop: 'batchNo', formslot: true,
search: true, search: true,
minWidth: 140, searchOrder: 17,
}, span: 24,
{ order: 790,
label: '关联单号', minWidth: 220,
prop: 'relationNo', rules: textRule('发货地址', 255, true),
search: true, },
minWidth: 140, {
}, label: '到货地址',
{ prop: 'arrivalAddress',
label: '当前过程节点', formslot: true,
prop: 'currentProcessNode', search: true,
minWidth: 140, searchLabel: '收货地址',
}, searchOrder: 16,
{ span: 24,
label: '货物信息JSON', order: 780,
prop: 'goodsJson', minWidth: 220,
type: 'textarea', rules: textRule('收货地址', 255, true),
minRows: 5, },
span: 24, {
hide: true, label: '发货联系人',
}, prop: 'departureContact',
{ minWidth: 120,
label: '承运信息JSON', addDisplay: false,
prop: 'carrierJson', editDisplay: false,
type: 'textarea', viewDisplay: false,
minRows: 4, },
span: 24, {
hide: true, label: '收货联系人',
}, prop: 'arrivalContact',
{ minWidth: 120,
label: '过程配置JSON', addDisplay: false,
prop: 'processJson', editDisplay: false,
type: 'textarea', viewDisplay: false,
minRows: 4, },
span: 24, {
hide: true, label: '单价(计价单位)',
}, prop: 'unitPrice',
{ formatter: row => formatUnitPrice(row),
label: '运费信息JSON', minWidth: 140,
prop: 'freightJson', addDisplay: false,
type: 'textarea', editDisplay: false,
minRows: 4, viewDisplay: false,
span: 24, },
hide: true, {
}, label: '运费',
{ prop: 'freight',
label: '附件JSON', formatter: row => formatAmount(row, ['freight', 'freightAmount', 'transportFee']),
prop: 'attachmentsJson', minWidth: 120,
type: 'textarea', addDisplay: false,
minRows: 3, editDisplay: false,
span: 24, viewDisplay: false,
hide: true, },
}, {
{ label: '其他费用合计',
label: '所属组织', prop: 'otherFeeTotal',
prop: 'deptName', formatter: row => formatAmount(row, ['otherFeeTotal', 'otherAmount', 'otherFeeAmount']),
minWidth: 150, minWidth: 140,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
}, viewDisplay: false,
{ },
label: '备注', {
prop: 'remark', label: '运费合计',
type: 'textarea', prop: 'freightTotal',
minRows: 4, formatter: row => formatAmount(row, ['freightTotal', 'totalFreight', 'totalAmount']),
span: 24, minWidth: 120,
hide: true, addDisplay: false,
maxlength: 500, editDisplay: false,
showWordLimit: true, viewDisplay: false,
rules: textRule('备注', 500), },
}, {
...auditColumns, 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: 280,
};

View File

@@ -130,7 +130,7 @@ export default {
selection: true, selection: true,
grid: true, grid: true,
labelWidth: 'auto', labelWidth: 'auto',
menuWidth: 350, menuWidth: 180,
dialogWidth: 1200, dialogWidth: 1200,
dialogClickModal: false, dialogClickModal: false,
tabs: true, tabs: true,

View File

@@ -13,7 +13,7 @@ export default {
selection: true, selection: true,
grid: true, grid: true,
labelWidth: 'auto', labelWidth: 'auto',
menuWidth: 350, menuWidth: 180,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [
{ {

View File

@@ -22,7 +22,7 @@ export const authLockOption = {
viewBtn: false, viewBtn: false,
editBtn: false, editBtn: false,
delBtn: false, delBtn: false,
menuWidth: 160, menuWidth: 180,
dialogType: 'drawer', dialogType: 'drawer',
dialogWidth: 800, dialogWidth: 800,
dialogClickModal: false, dialogClickModal: false,

View File

@@ -21,7 +21,7 @@ export const authLogOption = {
editBtn: false, editBtn: false,
delBtn: false, delBtn: false,
menu: true, menu: true,
menuWidth: 100, menuWidth: 180,
dialogType: 'drawer', dialogType: 'drawer',
dialogWidth: 800, dialogWidth: 800,
dialogClickModal: false, dialogClickModal: false,

View File

@@ -11,7 +11,7 @@ export const optionParent = {
index: true, index: true,
selection: true, selection: true,
viewBtn: true, viewBtn: true,
menuWidth: 250, menuWidth: 180,
dialogWidth: 880, dialogWidth: 880,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [
@@ -104,7 +104,7 @@ export const optionChild = {
index: true, index: true,
selection: true, selection: true,
viewBtn: true, viewBtn: true,
menuWidth: 300, menuWidth: 180,
dialogWidth: 880, dialogWidth: 880,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [

View File

@@ -11,7 +11,7 @@ export const optionParent = {
index: true, index: true,
selection: true, selection: true,
viewBtn: true, viewBtn: true,
menuWidth: 250, menuWidth: 180,
dialogWidth: 880, dialogWidth: 880,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [
@@ -105,7 +105,7 @@ export const optionChild = {
index: true, index: true,
selection: true, selection: true,
viewBtn: true, viewBtn: true,
menuWidth: 300, menuWidth: 180,
dialogWidth: 880, dialogWidth: 880,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [

View File

@@ -1,4 +1,3 @@
import website from '@/config/website';
import { getDeptLazyTree } from '@/api/system/dept'; import { getDeptLazyTree } from '@/api/system/dept';
export const userOption = safe => { export const userOption = safe => {
@@ -25,42 +24,41 @@ export const userOption = safe => {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
selection: true, selection: true,
addBtn: false, addBtn: false,
viewBtn: true, viewBtn: true,
dialogType: 'drawer', dialogType: 'dialog',
dialogWidth: 1000, dialogWidth: '90%',
labelPosition: 'right',
labelWidth: 120,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [
{ {
label: '登录账号', label: '账号',
prop: 'account', prop: 'account',
search: true, search: true,
searchOrder: 2,
display: false, display: false,
}, },
{ {
label: '所属租户', label: '姓名',
prop: 'tenantName',
slot: true,
display: false,
},
{
label: '用户姓名',
prop: 'realName', prop: 'realName',
search: true, search: true,
searchOrder: 4,
display: false, display: false,
}, },
{ {
label: '所属角色', label: '手机号',
prop: 'roleName', prop: 'phone',
slot: true, search: true,
overHidden: true, searchOrder: 3,
display: false, display: false,
}, },
{ label: '工号', prop: 'code', display: false },
{ {
label: '所属部门', label: '所属部门',
prop: 'deptName', prop: 'deptName',
@@ -68,33 +66,22 @@ export const userOption = safe => {
overHidden: true, overHidden: true,
display: false, display: false,
}, },
{ label: '岗位', prop: 'postName', overHidden: true, display: false },
{ label: '性别', prop: 'sexName', width: 80, display: false },
{ label: 'OA人员id', prop: 'oaPersonId', minWidth: 120, overHidden: true, display: false },
{ label: '备注', prop: 'remark', minWidth: 160, overHidden: true, display: false },
{ {
label: '用户平台', label: '状态',
prop: 'userTypeName', prop: 'status',
width: 100,
slot: true,
display: false,
},
{
label: '用户平台',
type: 'select', type: 'select',
dicUrl: '/blade-system/dict/dictionary?code=user_type', dicData: [
props: { { label: '启用', value: 1 },
label: 'dictValue', { label: '禁用', value: 0 },
value: 'dictKey', ],
},
dataType: 'number', dataType: 'number',
search: true, search: true,
hide: true, searchOrder: 1,
display: false, display: false,
prop: 'userType',
rules: [
{
required: true,
message: '请选择用户平台',
trigger: 'blur',
},
],
}, },
], ],
group: [ group: [
@@ -104,53 +91,13 @@ export const userOption = safe => {
icon: 'el-icon-user-solid', icon: 'el-icon-user-solid',
column: [ column: [
{ {
label: '所属租户', label: '账号名',
prop: 'tenantId',
type: 'tree',
dicUrl: '/blade-system/tenant/select',
props: {
label: 'tenantName',
value: 'tenantId',
},
hide: !website.tenantMode,
addDisplay: website.tenantMode,
editDisplay: website.tenantMode,
viewDisplay: website.tenantMode,
rules: [
{
required: true,
message: '请输入所属租户',
trigger: 'click',
},
],
span: 24,
},
{
label: '登录账号',
prop: 'account', prop: 'account',
span: 6,
rules: [ rules: [
{ {
required: true, required: true,
message: '请输入登录账号', message: '请输入账号',
trigger: 'blur',
},
],
},
{
label: '用户平台',
type: 'select',
dicUrl: '/blade-system/dict/dictionary?code=user_type',
props: {
label: 'dictValue',
value: 'dictKey',
},
dataType: 'number',
slot: true,
prop: 'userType',
rules: [
{
required: true,
message: '请选择用户平台',
trigger: 'blur', trigger: 'blur',
}, },
], ],
@@ -161,6 +108,7 @@ export const userOption = safe => {
hide: true, hide: true,
editDisplay: false, editDisplay: false,
viewDisplay: false, viewDisplay: false,
addDisplay: false,
rules: [{ required: true, validator: validatePass, trigger: 'blur' }], rules: [{ required: true, validator: validatePass, trigger: 'blur' }],
}, },
{ {
@@ -169,6 +117,7 @@ export const userOption = safe => {
hide: true, hide: true,
editDisplay: false, editDisplay: false,
viewDisplay: false, viewDisplay: false,
addDisplay: false,
rules: [{ required: true, validator: validatePass2, trigger: 'blur' }], rules: [{ required: true, validator: validatePass2, trigger: 'blur' }],
}, },
], ],
@@ -191,12 +140,13 @@ export const userOption = safe => {
], ],
}, },
{ {
label: '用户姓名', label: '姓名',
prop: 'realName', prop: 'realName',
span: 6,
rules: [ rules: [
{ {
required: true, required: true,
message: '请输入用户姓名', message: '请输入姓名',
trigger: 'blur', trigger: 'blur',
}, },
{ {
@@ -209,12 +159,14 @@ export const userOption = safe => {
{ {
label: '手机号码', label: '手机号码',
prop: 'phone', prop: 'phone',
span: 6,
rules: [{ required: true, message: '请输入手机号码', trigger: 'blur' }],
overHidden: true, overHidden: true,
}, },
{ {
label: '电子邮箱', label: '电子邮箱',
prop: 'email', prop: 'email',
hide: true, span: 6,
overHidden: true, overHidden: true,
}, },
{ {
@@ -235,7 +187,7 @@ export const userOption = safe => {
value: 3, value: 3,
}, },
], ],
hide: true, span: 6,
}, },
{ {
label: '用户生日', label: '用户生日',
@@ -261,6 +213,8 @@ export const userOption = safe => {
{ {
label: '用户编号', label: '用户编号',
prop: 'code', prop: 'code',
label: '工号',
span: 6,
}, },
{ {
label: '所属角色', label: '所属角色',
@@ -273,13 +227,7 @@ export const userOption = safe => {
}, },
checkStrictly: true, checkStrictly: true,
slot: true, slot: true,
rules: [ display: false,
{
required: true,
message: '请选择所属角色',
trigger: 'click',
},
],
}, },
{ {
label: '所属部门', label: '所属部门',
@@ -292,6 +240,7 @@ export const userOption = safe => {
}, },
checkStrictly: true, checkStrictly: true,
slot: true, slot: true,
span: 6,
rules: [ rules: [
{ {
required: true, required: true,
@@ -304,7 +253,7 @@ export const userOption = safe => {
label: '所属岗位', label: '所属岗位',
prop: 'postId', prop: 'postId',
type: 'tree', type: 'tree',
multiple: true, multiple: false,
dicData: [], dicData: [],
props: { props: {
label: 'postName', label: 'postName',
@@ -317,6 +266,7 @@ export const userOption = safe => {
trigger: 'click', trigger: 'click',
}, },
], ],
span: 6,
}, },
{ {
label: '直属主管', label: '直属主管',
@@ -330,6 +280,7 @@ export const userOption = safe => {
value: 'id', value: 'id',
}, },
clearable: true, clearable: true,
display: false,
}, },
{ {
label: '是否主管', label: '是否主管',
@@ -346,6 +297,49 @@ export const userOption = safe => {
}, },
], ],
value: 0, value: 0,
display: false,
},
{
label: '人员类别',
prop: 'personCategory',
type: 'select',
span: 6,
value: 1,
dicData: [
{ label: '内部员工', value: 1 },
{ label: '承运商', value: 2 },
],
},
{
label: '数据权限范围',
prop: 'dataScopeRange',
type: 'radio',
span: 24,
value: 1,
dicData: [
{ label: '仅所属组织', value: 1 },
{ label: '全部组织', value: 2 },
{ label: '自定义', value: 3 },
],
},
{
label: '数据层级范围',
prop: 'dataLevelRange',
type: 'radio',
span: 24,
value: 1,
dicData: [
{ label: '包含下级', value: 1 },
{ label: '仅本级', value: 2 },
],
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
span: 24,
maxlength: 200,
showWordLimit: true,
}, },
], ],
}, },
@@ -365,7 +359,7 @@ export const platformOption = {
selection: true, selection: true,
viewBtn: true, viewBtn: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
editBtnText: '配置', editBtnText: '配置',
column: [ column: [
{ {

View File

@@ -14,7 +14,7 @@ export const codeOption = {
index: true, index: true,
selection: true, selection: true,
labelWidth: 'auto', labelWidth: 'auto',
menuWidth: 350, menuWidth: 180,
viewBtn: true, viewBtn: true,
dialogClickModal: false, dialogClickModal: false,
tabs: true, tabs: true,

View File

@@ -14,7 +14,7 @@ export default {
selection: true, selection: true,
labelWidth: 'auto', labelWidth: 'auto',
searchLabelWidth: 160, searchLabelWidth: 160,
menuWidth: 320, menuWidth: 180,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [
{ {

View File

@@ -14,7 +14,7 @@ export default {
selection: true, selection: true,
labelWidth: 'auto', labelWidth: 'auto',
searchLabelWidth: 160, searchLabelWidth: 160,
menuWidth: 320, menuWidth: 180,
dialogWidth: 500, dialogWidth: 500,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [

View File

@@ -5,10 +5,12 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', 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,
@@ -18,23 +20,19 @@ export const option = {
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: 220,
},
{
label: '身份证号',
prop: 'idCardNo',
search: true,
width: 190,
}, },
{ {
label: '手机号码', label: '手机号码',
prop: 'mobile', prop: 'mobile',
search: true, search: true,
width: 130, searchOrder: 6,
minWidth: 130,
}, },
{ {
label: '性别', label: '性别',
@@ -46,51 +44,45 @@ export const option = {
label: '司机类型', label: '司机类型',
prop: 'driverType', prop: 'driverType',
search: true, search: true,
searchOrder: 3,
type: 'select', type: 'select',
dicData: [ dicData: [
{ {
label: '自有', label: '自有员工',
value: '自有', value: '自有',
}, },
{ {
label: '外协', label: '外协',
value: '外协', value: '外协',
}, },
{
label: '承运管理员',
value: '承运管理员',
},
], ],
width: 100, minWidth: 110,
align: 'center', align: 'center',
}, },
{ {
label: '岗位', label: '岗位',
prop: 'posts', prop: 'posts',
width: 150, minWidth: 150,
},
{
label: '准驾车型',
prop: 'drivingType',
search: true,
width: 110,
}, },
{ {
label: '所属组织', label: '所属组织',
prop: 'organizationName', prop: 'organizationName',
type: 'cascader',
search: true, search: true,
emitPath: false, searchOrder: 1,
checkStrictly: true, type: 'select',
filterable: true, filterable: true,
dicData: [], dicData: [],
props: { minWidth: 160,
label: 'label',
value: 'value',
children: 'children',
},
width: 140,
}, },
{ {
label: '状态', label: '状态',
prop: 'status', prop: 'status',
search: true, search: true,
searchOrder: 4,
type: 'select', type: 'select',
slot: true, slot: true,
dicData: [ dicData: [
@@ -107,18 +99,52 @@ export const option = {
align: 'center', align: 'center',
}, },
{ {
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: 160,
align: 'center', },
{
label: '身份证号',
prop: 'idCardNo',
search: true,
searchOrder: 2,
hide: true,
},
{
label: '准驾车型',
prop: 'drivingType',
search: true,
searchOrder: 5,
hide: true,
type: 'select',
dicData: [
{ label: 'A1', value: 'A1' },
{ label: 'A2', value: 'A2' },
{ label: 'A3', value: 'A3' },
{ label: 'B1', value: 'B1' },
{ label: 'B2', value: 'B2' },
{ label: 'C1', value: 'C1' },
{ label: 'C2', value: 'C2' },
],
},
{
label: '',
prop: 'expireStatus',
search: true,
searchOrder: 0,
searchSpan: 6,
hide: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
}, },
], ],
}; };

View File

@@ -5,7 +5,7 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
@@ -14,56 +14,94 @@ export const option = {
editBtn: false, editBtn: false,
delBtn: false, delBtn: false,
viewBtn: false, viewBtn: false,
menuWidth: 210, menuWidth: 180,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [
{ label: '船舶名', prop: 'shipName', search: true, slot: true, width: 130 }, {
{ label: '船舶识别号', prop: 'shipIdentifierNo', search: true, width: 140 }, label: '船舶名',
{ label: '所属组织', prop: 'organizationName', search: true, width: 160 }, prop: 'shipName',
{ label: '船检登记号', prop: 'shipInspectionNo', search: true, width: 130 }, search: true,
searchOrder: 5,
slot: true,
minWidth: 130,
},
{
label: '船舶识别号',
prop: 'shipIdentifierNo',
search: true,
searchOrder: 4,
minWidth: 140,
},
{
label: '所属组织',
prop: 'organizationName',
search: true,
searchOrder: 1,
type: 'select',
filterable: true,
dicData: [],
minWidth: 160,
},
{
label: '船检登记号',
prop: 'shipInspectionNo',
search: true,
searchOrder: 3,
minWidth: 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, minWidth: 110,
align: 'center', align: 'center',
}, },
{ {
label: '状态', label: '国籍证有效期至',
prop: 'status', prop: 'nationalityCertEndDate',
search: true,
type: 'select',
slot: true, slot: true,
dicData: [ minWidth: 150,
{ label: '启用', value: 1 },
{ label: '停用', value: 2 },
],
width: 90,
align: 'center', align: 'center',
}, },
{ label: '国籍证有效期至', prop: 'nationalityCertEndDate', slot: true, width: 150, align: 'center' },
{ {
label: '最低安全配员证书有效期至', label: '最低安全配员证书有效期至',
prop: 'safeManningCertEndDate', prop: 'safeManningCertEndDate',
slot: true, slot: true,
width: 210, minWidth: 210,
align: 'center', align: 'center',
}, },
{ {
label: '营业运输证有效期至', label: '营业运输证有效期至',
prop: 'businessTransportCertEndDate', prop: 'businessTransportCertEndDate',
slot: true, slot: true,
width: 170, minWidth: 170,
align: 'center', align: 'center',
}, },
{ label: '承租有效期至', prop: 'leaseEndDate', slot: true, width: 140, align: 'center' }, {
label: '承租有效期至',
prop: 'leaseEndDate',
slot: true,
minWidth: 140,
align: 'center',
},
{
label: '',
prop: 'expireStatus',
search: true,
searchOrder: 0,
searchSpan: 6,
hide: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
], ],
}; };

View File

@@ -5,112 +5,156 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
selection: true, selection: false,
addBtn: false, addBtn: false,
editBtn: false, editBtn: false,
delBtn: false, delBtn: false,
viewBtn: false, viewBtn: false,
menuWidth: 180, menuWidth: 320,
dialogClickModal: false, dialogClickModal: false,
column: [ column: [
{ {
label: '车牌号', label: '车牌号',
prop: 'plateNo', prop: 'plateNo',
search: true, search: true,
searchOrder: 6,
slot: true, slot: true,
width: 120, minWidth: 120,
},
{
label: '所属组织',
prop: 'organizationName',
search: true,
width: 150,
},
{
label: '车辆类型',
prop: 'vehicleType',
search: true,
type: 'select',
dicData: [
{ label: '厢式', value: '厢式' },
{ label: '高栏', value: '高栏' },
{ label: '平板', value: '平板' },
{ label: '仓栅', value: '仓栅' },
{ label: '牵引车', value: '牵引车' },
],
width: 110,
align: 'center',
}, },
{ {
label: '业务关系', label: '业务关系',
prop: 'businessRelation', prop: 'businessRelation',
search: true, search: true,
searchOrder: 5,
searchValue: '',
type: 'select', type: 'select',
dicData: [ dicData: [
{ label: '全部', value: '' },
{ label: '自有', value: '自有' }, { label: '自有', value: '自有' },
{ label: '业务合作', value: '业务合作' },
{ label: '管理挂靠', value: '管理挂靠' }, { label: '管理挂靠', value: '管理挂靠' },
{ label: '业务合作', value: '业务合作' },
], ],
width: 120, minWidth: 120,
align: 'center', align: 'center',
}, },
{ {
label: '能源类型', label: '所属组织',
prop: 'energyType', prop: 'organizationName',
search: true, search: true,
searchOrder: 1,
type: 'select',
filterable: true,
dicData: [],
minWidth: 150,
},
{
label: '车辆类型',
prop: 'vehicleType',
search: true,
searchOrder: 4,
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, minWidth: 110,
align: 'center', align: 'center',
}, },
{ {
label: '核定载质量(KG)', label: '核定载质量(KG)',
prop: 'approvedLoadKg', prop: 'approvedLoadKg',
width: 140, minWidth: 140,
align: 'right', align: 'right',
}, },
{ {
label: '状态', label: '绑定司机',
prop: 'boundDriver',
slot: true,
minWidth: 120,
align: 'center',
},
{
label: '车辆类型',
prop: 'vehicleType',
minWidth: 110,
align: 'center',
},
{
label: '认证状态',
prop: 'certificationStatus',
slot: true,
search: true,
searchOrder: 2,
searchValue: '',
type: 'select',
dicData: [
{ label: '全部', value: '' },
{ label: '认证中', value: 0 },
{ label: '已认证', value: 1 },
{ label: '已驳回', value: 2 },
],
minWidth: 110,
align: 'center',
},
{
label: '车辆状态',
prop: 'status', prop: 'status',
search: true, search: true,
searchOrder: 3,
type: 'select', type: 'select',
slot: true, slot: true,
dicData: [ dicData: [
{ label: '启用', value: 1 }, { label: '启用', value: 1 },
{ label: '停用', value: 2 }, { label: '停用', value: 2 },
], ],
width: 90, minWidth: 90,
align: 'center', align: 'center',
}, },
{ {
label: '行驶证有效期', label: '道路运输证号',
prop: 'roadTransportCertNo',
minWidth: 160,
},
{
label: '行驶证认证',
prop: 'drivingLicenseEndDate', prop: 'drivingLicenseEndDate',
slot: true, slot: true,
width: 140, minWidth: 140,
align: 'center', align: 'center',
}, },
{ {
label: '道路运输证有效期', label: '道路运输证认证',
prop: 'roadTransportCertEndDate', prop: 'roadTransportCertEndDate',
slot: true, slot: true,
width: 160, minWidth: 160,
align: 'center', align: 'center',
}, },
{ {
label: '年审有效期', label: '道路运输证年审',
prop: 'annualReviewEndDate', prop: 'annualReviewEndDate',
slot: true, slot: true,
width: 130, minWidth: 130,
align: 'center', align: 'center',
}, },
{
label: '',
prop: 'expireStatus',
search: true,
searchOrder: 0,
searchSpan: 6,
hide: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
], ],
}; };

View File

@@ -45,14 +45,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
column: [ column: [
{ {
label: '车船类型', label: '车船类型',
@@ -124,9 +125,8 @@ export const option = {
{ {
label: '直接经济损失', label: '直接经济损失',
prop: 'directEconomicLoss', prop: 'directEconomicLoss',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元',
minWidth: 140, minWidth: 140,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',
@@ -135,9 +135,8 @@ export const option = {
{ {
label: '保险理赔金额', label: '保险理赔金额',
prop: 'insuranceClaimAmount', prop: 'insuranceClaimAmount',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元',
minWidth: 140, minWidth: 140,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',
@@ -211,22 +210,13 @@ 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',
hide: true, searchRange: true,
addDisplay: false, search: true,
editDisplay: false,
viewDisplay: false,
},
{
label: '创建结束时间',
prop: 'createTimeEnd',
type: 'date',
format: 'YYYY-MM-DD 23:59:59',
valueFormat: 'YYYY-MM-DD 23:59:59',
hide: true, hide: true,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,

View File

@@ -44,14 +44,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
column: [ column: [
{ {
label: '车船类型', label: '车船类型',
@@ -140,9 +141,8 @@ export const option = {
{ {
label: '费用', label: '费用',
prop: 'fee', prop: 'fee',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元',
minWidth: 100, minWidth: 100,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',
@@ -155,6 +155,7 @@ export const option = {
label: '评定(复核)单位', label: '评定(复核)单位',
prop: 'assessmentUnit', prop: 'assessmentUnit',
minWidth: 160, minWidth: 160,
overHidden: true,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }], rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
@@ -215,22 +216,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',
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',
hide: true, hide: true,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,

View File

@@ -0,0 +1,226 @@
import { formatUpdateUserName } from '@/utils/audit';
export const vehicleTypeDic = [
{ label: '车辆', value: '车辆' },
{ label: '船舶', value: '船舶' },
];
export const onlineStatusDic = [
{ label: '否', value: 0 },
{ label: '是', value: 1 },
];
export const option = {
height: 'auto',
calcHeight: 32,
dialogWidth: 960,
labelPosition: 'right',
labelWidth: 'auto',
searchLabelWidth: 160,
tip: false,
searchBtnText: '查询',
emptyBtnText: '重置',
saveBtnText: '提交',
updateBtnText: '提交',
searchShow: true,
searchMenuSpan: 24,
searchIcon: true,
searchIndex: 4,
searchMenuPosition: 'right',
border: true,
index: true,
indexLabel: '序号',
viewBtn: true,
selection: true,
dialogClickModal: false,
menuWidth: 160,
menuFixed: 'right',
column: [
{
label: '车船类型',
prop: 'vehicleType',
type: 'radio',
dicData: vehicleTypeDic,
value: '车辆',
search: true,
searchOrder: 3,
span: 24,
order: 1,
minWidth: 110,
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
},
{
label: '车牌号/船号',
prop: 'vehicleNo',
slot: true,
formslot: true,
search: true,
searchOrder: 4,
span: 12,
order: 2,
minWidth: 140,
rules: [{ required: true, message: '请输入车牌号/船号', trigger: 'blur' }],
},
{
label: '设备号',
prop: 'equipmentCode',
formslot: true,
search: true,
searchOrder: 2,
span: 12,
order: 3,
minWidth: 150,
rules: [{ required: true, message: '设备编号由系统生成', trigger: 'blur' }],
},
{
label: '设备名称',
prop: 'equipmentName',
span: 12,
order: 4,
minWidth: 150,
rules: [
{ required: true, message: '请输入设备名称', trigger: 'blur' },
{ max: 100, message: '最多 100 个字符', trigger: 'blur' },
],
},
{
label: '出厂日期',
prop: 'factoryDate',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
span: 12,
order: 8,
minWidth: 130,
},
{
label: '设备品牌',
prop: 'equipmentBrand',
span: 12,
order: 5,
minWidth: 130,
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
},
{
label: '设备类型',
prop: 'equipmentType',
type: 'select',
dicData: [],
span: 12,
order: 6,
minWidth: 130,
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'change' }],
},
{
label: '规格型号',
prop: 'specificationModel',
span: 12,
order: 7,
minWidth: 150,
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minRows: 3,
span: 24,
order: 10,
minWidth: 180,
overHidden: true,
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
},
{
label: '更新时间',
prop: 'updateTime',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
addDisplay: false,
editDisplay: false,
viewDisplay: false,
minWidth: 170,
},
{
label: '创建时间',
prop: 'createTime',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
addDisplay: false,
editDisplay: false,
viewDisplay: false,
minWidth: 170,
},
{
label: '是否在线',
prop: 'onlineStatus',
type: 'select',
dicData: onlineStatusDic,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
minWidth: 100,
},
{
label: '原厂设备号',
prop: 'originalEquipmentNo',
span: 12,
order: 9,
hide: true,
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
},
{
label: '附件',
prop: 'attachments',
slot: true,
formslot: true,
span: 24,
order: 11,
hide: true,
},
{
label: '组织',
prop: 'createDept',
type: 'tree',
dicData: [],
props: { label: 'title', value: 'id' },
checkStrictly: true,
search: true,
searchOrder: 1,
hide: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '更新人',
prop: 'updateUserName',
formatter: formatUpdateUserName,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
],
};
export const excelOption = {
labelPosition: 'right',
submitBtn: false,
emptyBtn: false,
column: [
{
label: '模板上传',
prop: 'excelFile',
type: 'upload',
drag: true,
loadText: '模板上传中,请稍等',
span: 24,
propsHttp: { res: 'data' },
tip: '请上传 .xls,.xlsx 标准格式文件',
action: '/blade-transport/equipment-ledger/import-equipment-ledger',
},
{ label: '模板下载', prop: 'excelTemplate', formslot: true, span: 24 },
],
};

View File

@@ -34,14 +34,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
menuFixed: 'right', menuFixed: 'right',
column: [ column: [
{ {
@@ -103,9 +104,8 @@ export const option = {
{ {
label: '交易金额', label: '交易金额',
prop: 'transactionAmount', prop: 'transactionAmount',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元',
minWidth: 130, minWidth: 130,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',

View File

@@ -42,14 +42,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
column: [ column: [
{ {
label: '车船类型', label: '车船类型',
@@ -128,8 +129,8 @@ export const option = {
{ {
label: '保额', label: '保额',
prop: 'insuredAmount', prop: 'insuredAmount',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元', append: '元',
minWidth: 120, minWidth: 120,
rules: [{ validator: validateNonNegative, trigger: 'blur' }], rules: [{ validator: validateNonNegative, trigger: 'blur' }],
@@ -137,8 +138,8 @@ export const option = {
{ {
label: '保费', label: '保费',
prop: 'premium', prop: 'premium',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元', append: '元',
minWidth: 120, minWidth: 120,
rules: [ rules: [
@@ -181,30 +182,6 @@ export const option = {
display: false, display: false,
minWidth: 170, minWidth: 170,
}, },
{
label: '创建开始时间',
prop: 'createTimeStart',
type: 'date',
format: 'YYYY-MM-DD 00:00:00',
valueFormat: 'YYYY-MM-DD 00:00:00',
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,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{ {
label: '组织', label: '组织',
prop: 'createDept', prop: 'createDept',
@@ -221,6 +198,19 @@ export const option = {
editDisplay: false, editDisplay: false,
viewDisplay: false, viewDisplay: false,
}, },
{
label: '创建时间',
prop: 'createTimeRange',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
searchRange: true,
search: true,
hide: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{ {
label: '更新人', label: '更新人',
prop: 'updateUserName', prop: 'updateUserName',

View File

@@ -30,14 +30,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
menuFixed: 'right', menuFixed: 'right',
column: [ column: [
{ {
@@ -47,6 +48,7 @@ export const option = {
dicData: vehicleTypeDic, dicData: vehicleTypeDic,
value: '车辆', value: '车辆',
search: true, search: true,
searchSpan: 6,
minWidth: 110, minWidth: 110,
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }], rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
}, },
@@ -56,6 +58,7 @@ export const option = {
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' },
@@ -65,9 +68,8 @@ export const option = {
{ {
label: '上月统计里程数', label: '上月统计里程数',
prop: 'previousMonthMileage', prop: 'previousMonthMileage',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '公里',
minWidth: 210, minWidth: 210,
slot: true, slot: true,
rules: [{ validator: validateNonNegative, trigger: 'blur' }], rules: [{ validator: validateNonNegative, trigger: 'blur' }],
@@ -75,9 +77,8 @@ export const option = {
{ {
label: '本月统计里程数', label: '本月统计里程数',
prop: 'currentMonthMileage', prop: 'currentMonthMileage',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '公里',
minWidth: 210, minWidth: 210,
slot: true, slot: true,
rules: [{ validator: validateNonNegative, trigger: 'blur' }], rules: [{ validator: validateNonNegative, trigger: 'blur' }],
@@ -85,9 +86,8 @@ export const option = {
{ {
label: '本月行驶里程数', label: '本月行驶里程数',
prop: 'monthlyMileage', prop: 'monthlyMileage',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '公里',
minWidth: 170, minWidth: 170,
slot: true, slot: true,
rules: [{ validator: validateNonNegative, trigger: 'blur' }], rules: [{ validator: validateNonNegative, trigger: 'blur' }],
@@ -95,9 +95,8 @@ export const option = {
{ {
label: '累计行驶里程数', label: '累计行驶里程数',
prop: 'totalMileage', prop: 'totalMileage',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '公里',
minWidth: 170, minWidth: 170,
slot: true, slot: true,
rules: [{ validator: validateNonNegative, trigger: 'blur' }], rules: [{ validator: validateNonNegative, trigger: 'blur' }],
@@ -168,24 +167,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,
@@ -202,6 +191,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,

View File

@@ -31,14 +31,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
menuFixed: 'right', menuFixed: 'right',
column: [ column: [
{ {
@@ -111,25 +112,24 @@ export const option = {
{ {
label: '数量', label: '数量',
prop: 'quantity', prop: 'quantity',
type: 'number', type: 'input',
precision: 2, formslot: true,
minWidth: 110, minWidth: 110,
rules: [{ validator: validateNonNegative, trigger: 'blur' }], rules: [{ validator: validateNonNegative, trigger: 'blur' }],
}, },
{ {
label: '单价', label: '单价',
prop: 'unitPrice', prop: 'unitPrice',
type: 'number', type: 'input',
precision: 2, formslot: true,
minWidth: 120, minWidth: 120,
append: '元/升',
rules: [{ validator: validateNonNegative, trigger: 'blur' }], rules: [{ validator: validateNonNegative, trigger: 'blur' }],
}, },
{ {
label: '交易金额', label: '交易金额',
prop: 'transactionAmount', prop: 'transactionAmount',
type: 'number', type: 'input',
precision: 2, formslot: true,
minWidth: 130, minWidth: 130,
rules: [ rules: [
{ required: true, message: '请输入交易金额', trigger: 'blur' }, { required: true, message: '请输入交易金额', trigger: 'blur' },
@@ -139,8 +139,8 @@ export const option = {
{ {
label: '余额', label: '余额',
prop: 'balance', prop: 'balance',
type: 'number', type: 'input',
precision: 2, formslot: true,
minWidth: 110, minWidth: 110,
rules: [{ validator: validateNonNegative, trigger: 'blur' }], rules: [{ validator: validateNonNegative, trigger: 'blur' }],
}, },
@@ -227,22 +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',
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',
hide: true, hide: true,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,

View File

@@ -42,14 +42,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
menuFixed: 'right', menuFixed: 'right',
column: [ column: [
{ {
@@ -102,9 +103,8 @@ export const option = {
{ {
label: '金额', label: '金额',
prop: 'amount', prop: 'amount',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元',
minWidth: 120, minWidth: 120,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',

View File

@@ -35,14 +35,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
column: [ column: [
{ {
label: '车牌号', label: '车牌号',
@@ -88,8 +89,8 @@ export const option = {
{ {
label: '换胎数量', label: '换胎数量',
prop: 'tireQuantity', prop: 'tireQuantity',
type: 'number', type: 'input',
precision: 0, formslot: true,
minWidth: 110, minWidth: 110,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',
@@ -98,9 +99,8 @@ export const option = {
{ {
label: '换胎费用', label: '换胎费用',
prop: 'replacementCost', prop: 'replacementCost',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元',
minWidth: 120, minWidth: 120,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',
@@ -150,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,

View File

@@ -22,14 +22,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
menuFixed: 'right', menuFixed: 'right',
column: [ column: [
{ {
@@ -105,23 +106,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,

View File

@@ -25,14 +25,6 @@ export const vehicleTypeDic = [
{ label: '船舶', value: '船舶' }, { label: '船舶', value: '船舶' },
]; ];
export const violationTypeDic = [
{ label: '闯红灯', value: '闯红灯' },
{ label: '超速', value: '超速' },
{ label: '违停', value: '违停' },
{ label: '压线', value: '压线' },
{ label: '其他', value: '其他' },
];
export const processStatusDic = [ export const processStatusDic = [
{ label: '未处理', value: '未处理' }, { label: '未处理', value: '未处理' },
{ label: '已处理', value: '已处理' }, { label: '已处理', value: '已处理' },
@@ -53,14 +45,15 @@ export const option = {
searchShow: true, searchShow: true,
searchMenuSpan: 24, searchMenuSpan: 24,
searchIcon: true, searchIcon: true,
searchIndex: 8, searchIndex: 4,
searchMenuPosition: 'right', searchMenuPosition: 'right',
border: true, border: true,
index: true, index: true,
indexLabel: '序号',
viewBtn: true, viewBtn: true,
selection: true, selection: true,
dialogClickModal: false, dialogClickModal: false,
menuWidth: 220, menuWidth: 180,
column: [ column: [
{ {
label: '车船类型', label: '车船类型',
@@ -104,11 +97,11 @@ export const option = {
label: '类型', label: '类型',
prop: 'violationType', prop: 'violationType',
type: 'select', type: 'select',
dicData: violationTypeDic, dicData: [],
minWidth: 120, minWidth: 120,
span: 12, span: 12,
placeholder: '请选择', placeholder: '请选择',
rules: [{ required: true, message: '请选择类型', trigger: 'change' }], rules: [],
}, },
{ {
label: '事项', label: '事项',
@@ -118,10 +111,7 @@ export const option = {
display: false, display: false,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',
rules: [ rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
{ required: true, message: '请输入事项', trigger: 'blur' },
{ max: 100, message: '最多 100 个字符', trigger: 'blur' },
],
}, },
{ {
label: '日期', label: '日期',
@@ -149,8 +139,8 @@ export const option = {
{ {
label: '罚款', label: '罚款',
prop: 'fineAmount', prop: 'fineAmount',
type: 'number', type: 'input',
precision: 2, formslot: true,
append: '元', append: '元',
minWidth: 100, minWidth: 100,
span: 12, span: 12,
@@ -160,8 +150,8 @@ export const option = {
{ {
label: '被扣分数', label: '被扣分数',
prop: 'deductPoints', prop: 'deductPoints',
type: 'number', type: 'input',
precision: 0, formslot: true,
minWidth: 110, minWidth: 110,
span: 12, span: 12,
placeholder: '请输入', placeholder: '请输入',
@@ -233,23 +223,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,

View File

@@ -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,20 +23,26 @@ 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: 20px; font-size: 17px;
color: #fff; color: #fff;
font-weight: 700; font-weight: 700;
padding-left: 4px; display: flex;
align-items: center;
justify-content: center;
} }
.logo-img { .logo-img {
width: 40px; width: 30px;
margin-top: 5px; margin-top: 10px;
} }
</style> </style>

View File

@@ -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>
@@ -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>

View File

@@ -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>

View File

@@ -18,7 +18,7 @@ const common = {
!storedColorName || LEGACY_PRIMARY_COLORS.includes(String(storedColorName).toUpperCase()) !storedColorName || LEGACY_PRIMARY_COLORS.includes(String(storedColorName).toUpperCase())
? DEFAULT_PRIMARY_COLOR ? DEFAULT_PRIMARY_COLOR
: storedColorName, : storedColorName,
themeName: getStore({ name: 'themeName' }) || 'theme-go', themeName: getStore({ name: 'themeName' }) || 'theme-d2',
lockPasswd: getStore({ name: 'lockPasswd' }) || '', lockPasswd: getStore({ name: 'lockPasswd' }) || '',
website: website, website: website,
setting: website.setting, setting: website.setting,

View File

@@ -308,7 +308,7 @@ const user = {
state.userInfo = { user_name: 'unauth', role_name: 'unauth', authority: 'unauth' }; state.userInfo = { user_name: 'unauth', role_name: 'unauth', authority: 'unauth' };
} else { } else {
if (validatenull(userInfo.avatar)) { if (validatenull(userInfo.avatar)) {
userInfo.avatar = '/img/bg/img-logo.png'; userInfo.avatar = '/img/bg/img-logo.jpg';
} }
if (!validatenull(userInfo.role_name)) { if (!validatenull(userInfo.role_name)) {
userInfo.roleName = userInfo.role_name; userInfo.roleName = userInfo.role_name;

View File

@@ -119,7 +119,8 @@ a {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
margin-bottom: 10px; //margin-bottom: 6px;
padding: 12px;
} }
.avue-view { .avue-view {

View File

@@ -109,7 +109,7 @@
} }
.basic-container__card .avue-crud__search.el-card > .el-card__body { .basic-container__card .avue-crud__search.el-card > .el-card__body {
padding: 12px 12px 4px; padding: 18px 18px 8px;
} }
.basic-container__card .avue-crud__header { .basic-container__card .avue-crud__header {
@@ -127,7 +127,7 @@
.avue-crud__search .el-form-item--small.el-form-item, .avue-crud__search .el-form-item--small.el-form-item,
.avue-crud__search .el-form-item--large.el-form-item, .avue-crud__search .el-form-item--large.el-form-item,
.avue-crud__search .el-form-item--medium.el-form-item { .avue-crud__search .el-form-item--medium.el-form-item {
margin-bottom: 8px; margin-bottom: 1px;
} }
.avue-crud__search .el-form-item__label { .avue-crud__search .el-form-item__label {
@@ -145,12 +145,16 @@
} }
.avue-crud__search { .avue-crud__search {
margin-top: 4px;
margin-bottom: 8px; margin-bottom: 8px;
} }
.avue-crud__search .avue-form__menu,
.avue-crud__search .avue-form__menu--right { .avue-crud__search .avue-form__menu--right {
display: flex; display: flex;
flex: 0 0 100%;
justify-content: flex-end; justify-content: flex-end;
//max-width: 100%;
width: 100%; width: 100%;
} }
@@ -203,6 +207,102 @@
justify-content: center; justify-content: center;
} }
// =====================================================================
// 弹窗标准(与 business/project-apply 弹窗视觉一致)
// 灰底弹窗体 + 分组白卡标题融入卡头4px 主色竖条 + 8px 间距)
// =====================================================================
// 1) 所有弹窗内容区统一灰底 + 16px 内边距(与 project-apply 一致,避免内容贴边)
.el-dialog__body {
background-color: #f5f6fa;
padding: 16px;
}
// 2) Avue 默认弹窗表单自动包成白卡,无需逐页改 option 即统一标准
.el-dialog .avue-form {
background: #fff;
border-radius: 6px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
padding: 16px;
}
// 3) Avue 弹窗内分组option.group渲染为白卡标题在卡内
.el-dialog .avue-form__group {
background: #fff;
border-radius: 6px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
margin-bottom: 16px;
overflow: hidden;
.avue-group__header {
border-bottom: none;
padding: 14px 16px 4px;
font-weight: 500;
color: #303133;
}
.avue-group__item {
padding: 14px 16px 4px;
}
}
// 4) 弹窗内表单项默认上下间距 16px覆盖默认 18px / 22px
.el-dialog .el-form-item {
margin-bottom: 16px;
}
// 5) 通用分组白卡组件(<section-card>):标题融入卡头
.section-card {
background: #fff;
border-radius: 6px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
margin-bottom: 16px;
overflow: hidden;
&:last-child {
margin-bottom: 0;
}
&__header {
display: flex;
align-items: center;
gap: 8px;
padding: 14px 16px 4px;
font-weight: 500;
color: #303133;
}
&__bar {
flex: none;
width: 4px;
height: 16px;
border-radius: 2px;
background-color: var(--el-color-primary);
}
&__title {
flex: 1;
min-width: 0;
}
&__extra {
margin-left: auto;
flex: none;
}
&__body {
padding: 14px 16px 4px;
}
}
// 6) 弹窗内两列表单栅格工具类(与 project-apply 一致)
.form-grid-2 {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
column-gap: 72px;
row-gap: 0;
}
.avue-crud__dialog .avue-dialog__footer > .el-button { .avue-crud__dialog .avue-dialog__footer > .el-button {
margin-left: 12px; margin-left: 12px;
} }
@@ -216,6 +316,14 @@
order: 2; order: 2;
} }
// 统一 avue-crud 弹窗内部可滚动高度:内容超出时在窗内滚动,避免弹窗被整体撑爆
// @smallwei/avue 3.9.2 无 dialogHeight 属性,故用全局样式统一所有 CRUD 弹窗)
.avue-crud__dialog .el-dialog__body {
max-height: calc(100vh - 200px);
overflow-y: auto;
//background: #f5f6fa;
}
// 统一表格线条颜色 // 统一表格线条颜色
.el-table { .el-table {
--el-table-border-color: #eff1f7; --el-table-border-color: #eff1f7;
@@ -256,6 +364,19 @@
margin-top: 12px; margin-top: 12px;
} }
// 统一 CRUD 顶部新增按钮为蓝底白字,保留其他工具按钮的描边样式
.avue-crud__header .el-button--primary.is-plain:has(.el-icon-plus) {
--el-button-bg-color: #409eff;
--el-button-border-color: #409eff;
--el-button-hover-bg-color: #66b1ff;
--el-button-hover-border-color: #66b1ff;
--el-button-active-bg-color: #337ecc;
--el-button-active-border-color: #337ecc;
--el-button-text-color: #fff;
--el-button-hover-text-color: #fff;
--el-button-active-text-color: #fff;
}
// 统一分页为按钮样式并靠右展示 // 统一分页为按钮样式并靠右展示
.avue-crud__pagination, .avue-crud__pagination,
.empty-pagination { .empty-pagination {
@@ -263,6 +384,7 @@
justify-content: flex-end; justify-content: flex-end;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
padding: 16px 0 !important;
} }
.avue-crud__pagination .el-pagination, .avue-crud__pagination .el-pagination,
@@ -277,7 +399,6 @@
justify-content: flex-end; justify-content: flex-end;
width: 100%; width: 100%;
gap: 6px; gap: 6px;
padding: 18px 0 0;
color: #303133; color: #303133;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
@@ -326,12 +447,7 @@
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
} }
.el-pagination .btn-prev, // 上一页 / 下一页 箭头按钮与页码按钮等宽,不再单独加宽
.el-pagination .btn-next,
.erp-pagination-first,
.erp-pagination-last {
min-width: 54px;
}
.el-pagination .el-pager { .el-pagination .el-pager {
gap: 6px; gap: 6px;
@@ -339,18 +455,7 @@
padding: 0; padding: 0;
} }
.el-pagination .btn-prev .el-icon, // 上一页 / 下一页 改为原生箭头图标:不再隐藏原生图标,也不再注入「上一页 / 下一页」文字
.el-pagination .btn-next .el-icon {
display: none;
}
.el-pagination .btn-prev::before {
content: '上一页';
}
.el-pagination .btn-next::before {
content: '下一页';
}
.el-pagination.is-background .el-pager li.is-active, .el-pagination.is-background .el-pager li.is-active,
.el-pagination .el-pager li.is-active { .el-pagination .el-pager li.is-active {
@@ -436,6 +541,106 @@
color: #fff; color: #fff;
} }
// 全站统一:分页展示「上一页 / 下一页」原生箭头图标(不再隐藏;首页 / 尾页仍不注入)
// 全站统一:隐藏操作栏按钮前的图标
.avue-crud__menu .el-button--text i,
.avue-crud__menu .el-button i {
display: none !important;
}
// 全站统一Avue 操作列文字链接保持间距并支持自动换行
// 注意Avue 自带 .avue-crud .avue-crud__menu{display:block}(特异性同为 0,2,0
// 此处重复类名升至 0,3,0 并强制 display:inline-flex !important彻底压过 Avue 内置样式,
// 避免 dev 模式下 CSS 注入顺序导致 .avue-crud__menu 退化成 block 而让操作项竖排错位。
.avue-crud .avue-crud__menu.avue-crud__menu {
display: inline-flex !important;
flex-wrap: wrap;
gap: 8px;
align-items: center;
justify-content: start;
width: 100% !important;
text-align: left;
}
// 全站统一:手写表格操作列中的文字链接保持间距并支持自动换行
.el-table .el-table__body .cell:not(.avue-crud__menu):has(> .el-link) {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px;
}
// 全站统一:表格操作列文字链接统一为主色(蓝色)
// 覆盖 Avue #menu 槽位与手写表格操作列中 el-link 的 warning / success / danger 等类型,
// 同时统一 hover / active / disabled 态,保证全站操作列风格一致。
// 选择器同时覆盖 Avue 行菜单(.avue-crud__menu与任意含 el-link 的表格体单元格(手写操作列)。
.avue-crud__menu .el-link,
.el-table .el-table__body .cell:has(.el-link) .el-link {
// 覆盖 Element Plus el-link 默认的 font-weight: var(--el-font-weight-primary)500 中等粗),
// 操作列文字统一为常规字重,避免「查看/编辑/删除」等链接显得加粗。
font-weight: normal;
--el-link-text-color: var(--el-color-primary);
--el-link-hover-text-color: var(--el-color-primary-light-3);
--el-link-active-text-color: var(--el-color-primary-dark-2);
--el-link-disabled-text-color: var(--el-color-primary-light-5);
}
// 全站统一:去除操作列 el-link 默认 margin避免与 8px gap 叠加导致文字间距过宽
.avue-crud .avue-crud__menu .el-link,
.el-table .el-table__body .cell:not(.avue-crud__menu):has(> .el-link) .el-link {
margin: 0;
}
.avue-crud__menu > .el-button,
.avue-crud__menu > .el-dropdown {
margin: 0;
}
.avue-crud__menu .el-button {
padding-left: 4px;
padding-right: 4px;
font-weight: normal;
}
// 全站统一Element Plus 全局开启 show-overflow-tooltip 后,
// 操作列单元格会被加上 .el-tooltip 类并写死宽度,导致内部 el-link 换行后被裁切。
// 此处豁免操作列单元格:让 Avue 行菜单与手写表格操作列保持原有 flex 自动换行,不被固定宽度裁切。
.el-table .cell.avue-crud__menu,
.el-table .el-table__body .cell.el-tooltip:has(> .el-link) {
width: auto !important;
overflow: visible;
text-overflow: clip;
}
// 全站统一Avue 内置行操作按钮(查看 / 编辑 / 删除 / 复制等)视觉对齐为 el-link 链接样式。
// 选择器仅命中表格行操作列 .avue-crud__menu 内的 is-text 按钮,不误伤顶部工具栏(.avue-crud__header
// 与弹窗按钮(.avue-crud__dialog__menu。事件rowView/rowEdit/rowDel与权限permission 指令)
// 由 Avue 自带,此处只改外观,零功能影响。
.avue-crud__menu > .el-button.is-text {
height: auto;
padding: 0;
border: none;
background: transparent;
color: var(--el-color-primary);
font-weight: normal;
&:hover,
&:focus,
&:active {
background: transparent;
color: var(--el-color-primary-light-3);
text-decoration: underline;
}
&.is-disabled,
&.is-disabled:hover {
background: transparent;
color: var(--el-color-primary-light-5);
text-decoration: none;
}
}
@media (max-width: 768px) { @media (max-width: 768px) {
.avue-crud__pagination .el-pagination, .avue-crud__pagination .el-pagination,
.empty-pagination .el-pagination, .empty-pagination .el-pagination,

View File

@@ -3,7 +3,7 @@
user-select: none; user-select: none;
position: relative; position: relative;
padding: 0 10px; padding: 0 10px;
margin-bottom: 10px; margin-bottom: 5px;
box-sizing: border-box; box-sizing: border-box;
border-top: 1px solid #f6f6f6; border-top: 1px solid #f6f6f6;
background-color: #fff; background-color: #fff;

View File

@@ -26,7 +26,7 @@
} }
.avue-logo { .avue-logo {
background: linear-gradient(90deg, #006cff, #399efd) !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
} }
.avue-tags { .avue-tags {

View File

@@ -1,7 +1,23 @@
.theme-bule { .theme-bule {
.avue-top, .avue-logo { .avue-top, .avue-logo {
background: #004ca7; background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
color: rgba(0, 0, 0, 0.85);
}
.avue-top {
.top-bar__right,
.avue-breadcrumb,
.top-bar__item,
.el-dropdown,
.el-dropdown-link {
color: rgba(0, 0, 0, 0.85);
i {
color: rgba(0, 0, 0, 0.65);
}
}
} }
.avue-sidebar { .avue-sidebar {
@@ -12,25 +28,21 @@
} }
} }
.el-dropdown {
color: #fff;
}
.avue-logo { .avue-logo {
.avue-logo_title { .avue-logo_title {
color: #fff; color: rgba(0, 0, 0, 0.85);
} }
} }
.avue-breadcrumb { .avue-breadcrumb {
i { i {
color: #fff; color: rgba(0, 0, 0, 0.65);
} }
} }
.top-bar__item { .top-bar__item {
i { i {
color: #fff; color: rgba(0, 0, 0, 0.65);
} }
} }
@@ -39,13 +51,13 @@
.el-menu-item { .el-menu-item {
i, i,
span { span {
color: #fff; color: rgba(0, 0, 0, 0.85);
} }
&:hover { &:hover {
i, i,
span { span {
color: #fff; color: var(--el-color-primary);
} }
} }
} }

View File

@@ -34,7 +34,8 @@
} }
.avue-top { .avue-top {
background: linear-gradient(120deg, #25aff3, #008ad3); background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
} }
.avue-tags { .avue-tags {
@@ -62,7 +63,7 @@
.avue-logo { .avue-logo {
background: #fff; background: #fff;
box-shadow: none; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
} }
.avue-sidebar--tip { .avue-sidebar--tip {
@@ -71,20 +72,20 @@
} }
.el-dropdown { .el-dropdown {
color: #fff; color: rgba(0, 0, 0, 0.85);
} }
.avue-logo_title { .avue-logo_title {
font-weight: 400; font-weight: 400;
color: #008ad3; color: rgba(0, 0, 0, 0.85);
} }
.logo_title, .logo_title,
.avue-breadcrumb { .avue-breadcrumb {
color: #fff; color: rgba(0, 0, 0, 0.85);
i { i {
color: #fff; color: rgba(0, 0, 0, 0.65);
} }
} }
@@ -92,13 +93,13 @@
.el-menu-item { .el-menu-item {
i, i,
span { span {
color: #fff; color: rgba(0, 0, 0, 0.85);
} }
&:hover { &:hover {
i, i,
span { span {
color: #fff; color: var(--el-color-primary);
} }
} }
} }
@@ -169,7 +170,7 @@
.top-bar__item { .top-bar__item {
i { i {
color: #fff; color: rgba(0, 0, 0, 0.65);
} }
} }
} }

View File

@@ -1,8 +1,7 @@
.theme-d2 { .theme-d2 {
.avue-logo { .avue-logo {
color: var(--el-color-primary); color: rgba(0, 0, 0, 0.85);
background-color: #ebf1f6; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
box-shadow: none;
.avue-logo_title { .avue-logo_title {
font-size: 20px; font-size: 20px;
@@ -11,12 +10,11 @@
} }
.avue-top { .avue-top {
background-color: #ebf1f6; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
box-shadow: none;
} }
.avue-main { .avue-main {
padding: 0 5px; padding: 0 1px;
} }
.avue-tags { .avue-tags {
@@ -48,7 +46,8 @@
} }
.avue-sidebar { .avue-sidebar {
background-color: #ebf1f6; //background-color: #ebf1f6;
background-color: #ffffff;
box-shadow: none; box-shadow: none;
.el-menu-item, .el-sub-menu__title { .el-menu-item, .el-sub-menu__title {

View File

@@ -77,8 +77,8 @@
background-color: #f4f6fa; background-color: #f4f6fa;
} }
.avue-tags { .avue-tags {
margin: 5px 6px 8px 6px;
padding-bottom: 2px; padding-bottom: 2px;
margin-left: 1px;
.el-tabs__nav-prev, .el-tabs__nav-prev,
.el-tabs__nav-next { .el-tabs__nav-next {

View File

@@ -33,7 +33,7 @@
.avue-logo { .avue-logo {
background-color: #fff; background-color: #fff;
box-shadow: none; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
.avue-logo_title { .avue-logo_title {
color: var(--el-color-primary); color: var(--el-color-primary);

View File

@@ -47,9 +47,10 @@
.theme-cool, .theme-cool,
.theme-beautiful { .theme-beautiful {
.avue-logo { .avue-logo {
background: var(--el-color-primary) !important; background: #419eff !important;
background-color: var(--el-color-primary) !important; background-color: #419eff !important;
color: #fff; color: #fff;
box-shadow: none;
.avue-logo_title, .avue-logo_title,
.avue-logo_subtitle, .avue-logo_subtitle,

View File

@@ -1,7 +1,7 @@
.theme-iview { .theme-iview {
.avue-logo { .avue-logo {
background: #001529; background: #fff;
box-shadow: none; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
text-align: center; text-align: center;
.avue-logo_title { .avue-logo_title {

View File

@@ -1,11 +1,12 @@
.theme-lte { .theme-lte {
.avue-logo { .avue-logo {
background-color: var(--el-color-primary); background-color: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
.avue-logo_title { .avue-logo_title {
font-weight: 500; font-weight: 500;
font-size: 20px; font-size: 20px;
color: #fff; color: rgba(0, 0, 0, 0.85);
} }
} }

View File

@@ -36,7 +36,8 @@
.avue-top, .avue-top,
.avue-logo, .avue-logo,
.tags-container { .tags-container {
background-color: var(--el-color-primary); background-color: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
} }
.avue-sidebar--tip { .avue-sidebar--tip {
@@ -45,20 +46,20 @@
} }
.el-dropdown { .el-dropdown {
color: #fff; color: rgba(0, 0, 0, 0.85);
} }
.avue-logo_title { .avue-logo_title {
font-weight: 400; font-weight: 400;
color: #fff; color: rgba(0, 0, 0, 0.85);
} }
.logo_title, .logo_title,
.avue-breadcrumb { .avue-breadcrumb {
color: #fff; color: rgba(0, 0, 0, 0.85);
i { i {
color: #fff; color: rgba(0, 0, 0, 0.65);
} }
} }
@@ -66,13 +67,13 @@
.el-menu-item { .el-menu-item {
i, i,
span { span {
color: #fff; color: rgba(0, 0, 0, 0.85);
} }
&:hover { &:hover {
i, i,
span { span {
color: #fff; color: var(--el-color-primary);
} }
} }
} }
@@ -137,7 +138,7 @@
.top-bar__item { .top-bar__item {
i { i {
color: #fff; color: rgba(0, 0, 0, 0.65);
} }
} }
} }

View File

@@ -3,8 +3,8 @@
.avue-top { .avue-top {
position: relative; position: relative;
background-color: #fff; background-color: #fff;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
color: rgba(0, 0, 0, .65); color: rgba(0, 0, 0, 0.85);
font-size: 28px; font-size: 28px;
height: variables.$top_height; height: variables.$top_height;
line-height: variables.$top_height; line-height: variables.$top_height;
@@ -56,7 +56,7 @@
.el-input__wrapper { .el-input__wrapper {
font-size: 13px; font-size: 13px;
border: none; border: none;
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.45); box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
background-color: #fff; background-color: #fff;
border-radius: 4px; border-radius: 4px;
} }
@@ -73,7 +73,7 @@
height: 30px; height: 30px;
border-radius: 100%; border-radius: 100%;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid #eee; border: 1px solid rgba(255, 255, 255, 0.5);
vertical-align: middle; vertical-align: middle;
} }
@@ -81,7 +81,6 @@
.top-bar__right { .top-bar__right {
height: variables.$top_height; height: variables.$top_height;
position: absolute; position: absolute;
margin-top: 2px;
top: 0; top: 0;
i { i {
@@ -107,7 +106,7 @@
} }
.el-color-picker__trigger { .el-color-picker__trigger {
border-color: rgba(255, 255, 255, 0.85); border-color: rgba(255, 255, 255, 0.4);
} }
.el-color-picker__icon { .el-color-picker__icon {
@@ -121,6 +120,7 @@
height: variables.$top_height; height: variables.$top_height;
margin: 0 7px; margin: 0 7px;
font-size: 16px; font-size: 16px;
top: -4px;
.el-badge__content.is-fixed { .el-badge__content.is-fixed {
top: 12px; top: 12px;
@@ -132,22 +132,25 @@
height: 100%; height: 100%;
padding-left: 50px; padding-left: 50px;
box-sizing: border-box; box-sizing: border-box;
background: var(--el-color-primary); // 顶部状态栏背景条:品牌色淡底 + 左侧主色竖条,与白色头部区分
background: #419eff;
//border-left: 4px solid #409eff;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-size: inherit; font-size: inherit;
font-weight: 400; font-weight: 500;
color: #fff;
} }
.avue-logo { .avue-logo {
height: variables.$top_height; height: variables.$top_height;
line-height: variables.$top_height; line-height: variables.$top_height;
background-color: var(--el-color-primary); background-color: #419eff;
font-size: 20px; font-size: 20px;
overflow: hidden; overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15); box-shadow: none;
color: #fff; color: #fff;
&_title { &_title {
@@ -155,7 +158,7 @@
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
font-size: 20px; font-size: 20px;
color: #fff; color: inherit;
} }
&_subtitle { &_subtitle {
@@ -163,6 +166,6 @@
text-align: center; text-align: center;
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;
color: #fff; color: inherit;
} }
} }

Some files were not shown because too many files have changed in this diff Show More