chore: upload dashboard updates
This commit is contained in:
BIN
doc/~$未完成计划.xlsx
Normal file
BIN
doc/~$未完成计划.xlsx
Normal file
Binary file not shown.
BIN
doc/未完成计划.xlsx
Normal file
BIN
doc/未完成计划.xlsx
Normal file
Binary file not shown.
@@ -391,3 +391,237 @@
|
|||||||
|
|
||||||
### 结论
|
### 结论
|
||||||
所有当前修改已提交并推送到远程 `origin/main`,主要提交为 `41af5a7 feat: add warehouse dashboard`。本次补充日志也将一并提交并推送,保持本地与远程一致。
|
所有当前修改已提交并推送到远程 `origin/main`,主要提交为 `41af5a7 feat: add warehouse dashboard`。本次补充日志也将一并提交并推送,保持本地与远程一致。
|
||||||
|
|
||||||
|
## 2026-07-06 仓库任务大屏按客户 Excel 调整
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户要求:继续修改仓库任务大屏,参考 `C:\Users\meswork764\Documents\xwechat_files\wxid_3113011130614_d858\msg\file\2026-07\库房大屏幕260704.xlsx`,客户提出数据源需要调整;当前四个图表占两行较松,表格应为四个明细表;上面的汇总数不允许有省略号。随后用户补充:条数放上面,件数放下面,大屏条数比件数有用,没必要大调整排版,数据能显示出来即可。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 检查 Git 状态,确认当前分支 `main` 与远程一致,工作区初始干净。
|
||||||
|
2. 确认客户 Excel 文件存在,解析 xlsx 内部 XML,读取工作表 `布局说明`。
|
||||||
|
3. 从 Excel 中提取新布局和新数据口径:入库任务、加急入库列表、拣配任务列表、加急拣配列表、发货任务列表,以及右侧数据源和取值逻辑。
|
||||||
|
4. 核对 Excel 中数据源:入库汇总仍使用 `UBT_MES_DP_receipttask_101/103/105/106`;加急入库列表使用四个 `UBT_MES_DP_receipttask_material_*` 明细视图按加急合并;拣配任务列表使用未清拣配明细;加急拣配列表使用两类拣配明细按加急合并;发货汇总使用 `UBT_MES_DP_OpenODLN_material` 和今日发货视图;异常出库使用 `UBT_MES_DP_OpenOPKL_material_10Days`。
|
||||||
|
5. 查询数据库字段结构,确认四个入库明细视图包含 `external_num/item_name/open_quantity/加急数量`,拣配明细视图包含 `项目/生产订单号/物料名称/齐套状态/打印状态/加急状态`,发货相关已有过程包含 `合同号/物料描述/交货数量/要求发货日期/检验数量`。
|
||||||
|
6. 更新数据库包装过程 `仓库大屏_汇总查询`,按用户补充要求将 `任务数` 作为条数主指标,将 `数量` 作为件数辅助指标。入库件数改从入库明细 `open_quantity` 统计,拣配件数改从拣配明细 `计划数量` 统计,及时处理和发货分别保留条数与件数。
|
||||||
|
7. 新增或更新只读包装过程 `仓库大屏_加急入库列表`、`仓库大屏_拣配任务列表`、`仓库大屏_加急拣配列表`,分别返回客户表格需要的字段。
|
||||||
|
8. 修改 `src/views/WarehouseDashboard.vue`:顶部 8 个汇总卡主数字全部改为条数,副文本显示件数和加急件数。
|
||||||
|
9. 修改 `src/views/WarehouseDashboard.vue`:四个图表压缩为一行展示,减少图表区高度,整体不做大幅重构。
|
||||||
|
10. 修改 `src/views/WarehouseDashboard.vue`:底部明细由 3 张表调整为 4 张表,分别为加急入库列表、拣配任务列表、加急拣配列表、发货任务列表。
|
||||||
|
11. 修改 `src/views/WarehouseDashboard.vue`:加急入库、拣配任务、加急拣配、发货任务分别接入新过程或现有发货过程,并按客户给出的字段展示。
|
||||||
|
12. 修改顶部 KPI 样式,去掉主数字的 `overflow hidden`、`max-width` 和 `text-overflow: ellipsis`,确保汇总数不显示省略号。
|
||||||
|
13. 调整表格和图表高度、字号、行高,四个明细表每表可见 8 行,保持原大屏风格。
|
||||||
|
14. 执行数据库过程样例验证,确认 `仓库大屏_汇总查询`、`仓库大屏_加急入库列表`、`仓库大屏_拣配任务列表`、`仓库大屏_加急拣配列表`、`装配中心任务看板_发货状态查询` 均能返回数据。
|
||||||
|
15. 执行 `npm run build`,构建成功,仅保留既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已按客户 Excel 和补充说明调整仓库任务大屏:汇总卡改为条数在上、件数在下;顶部汇总数字不再省略;四个图表压缩到一行;底部改为四个明细表并接入新数据源。构建验证通过。
|
||||||
|
|
||||||
|
## 2026-07-06 仓库任务大屏数据为 0 和布局空白修复
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户反馈:仓库任务大屏顶部和图表数据都没了,下面太空;要求在四个图表下面再加四个图表。随后用户补充:八个图表两行加上列表三行高度都一样。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 根据用户截图判断:明细表有数据,但顶部 KPI 和图表全为 0,问题集中在汇总接口或前端汇总数据处理。
|
||||||
|
2. 直接执行数据库过程 `仓库大屏_汇总查询`,发现执行约 8.3 秒,超过前端 Axios 原 5 秒超时,导致前端查询失败后把汇总数据置空,因此顶部和图表显示 0。
|
||||||
|
3. 尝试使用 `OPENQUERY` 优化 SAP 远程聚合,单类测试约 1.8 秒;随后确认完整聚合仍可能受 SAP 链接查询波动影响。
|
||||||
|
4. 将 `仓库大屏_汇总查询` 改回较快的直接汇总口径,优先保证 `任务数` 条数能快速返回,件数保留为辅助数量;复测完整过程约 4.7 秒。
|
||||||
|
5. 修改 `src/utils/request.js`,将 Axios 超时时间从 5 秒调整为 15 秒,避免 SAP 链接偶发慢一点时前端清空汇总。
|
||||||
|
6. 修改 `src/views/WarehouseDashboard.vue`,增加第二排 4 个图表,合计 8 个图表:
|
||||||
|
- 入库任务结构
|
||||||
|
- 拣配任务结构
|
||||||
|
- 超期风险分布
|
||||||
|
- 今日发货保障
|
||||||
|
- 入库条数结构
|
||||||
|
- 拣配条数结构
|
||||||
|
- 及时处理件数
|
||||||
|
- 发货件数结构
|
||||||
|
7. 为新增 4 个图表增加 ECharts ref、实例初始化、渲染、resize 和 dispose 管理。
|
||||||
|
8. 新增通用单柱状图配置函数,复用现有汇总数据,不新增额外接口压力。
|
||||||
|
9. 按用户要求将内容区域设置为三行等高:前两行为 8 个图表,第三行为 4 个列表;顶部汇总卡单独保留。
|
||||||
|
10. 将明细表可见行数调为 5 行,真实数据超过可见行数时继续自动滚动,避免列表区域显得过空。
|
||||||
|
11. 给汇总数据应用函数增加兜底:如果汇总接口偶发返回空数组,不覆盖已有汇总数据,避免刷新后突然全 0。
|
||||||
|
12. 执行 `npm run build`,构建成功;仅保留既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已修复汇总数据因接口超时导致全为 0 的问题,并将大屏主体调整为三行等高:两行 8 个图表加一行 4 个列表。构建验证通过。
|
||||||
|
|
||||||
|
## 2026-07-06 仓库任务大屏字号放大
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户要求:因为是看板,需要把字号调大。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 保持现有三行等高布局和数据逻辑不变,只调整视觉字号。
|
||||||
|
2. 放大顶部 KPI 卡片:标题从 19px 调整为 22px,主数字从 39px 调整为 48px,单位从 18px 调整为 22px,副文本从 14px 调整为 16px。
|
||||||
|
3. 放大面板标题:图表和表格标题调整为 28px,并保持 38px 标题栏高度。
|
||||||
|
4. 放大表格文字:表头从 13px 调整为 16px,表体从 12px 调整为 15px,行高同步增加。
|
||||||
|
5. 放大 ECharts 图表文字:tooltip、图例、坐标轴标签、柱状图标签、饼图标签等统一上调字号。
|
||||||
|
6. 执行 `npm run build`,构建成功;仍仅有既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已放大仓库任务大屏的 KPI、图表和表格字号,更适合大屏看板远距离查看。构建验证通过。
|
||||||
|
|
||||||
|
## 2026-07-06 仓库任务大屏列表右侧遮挡修复
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户反馈:四个列表右边被挡住了,没有完全显示出来。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 根据截图判断,四个列表面板为四等分布局,但表格列宽仍使用固定像素,列宽总和超过单个面板宽度,导致右侧列被裁切。
|
||||||
|
2. 将四个列表的列宽从固定 `px` 改为百分比宽度,确保每张表总宽度不超过所在面板。
|
||||||
|
3. 拣配任务列表去掉非必要的 `状态` 列,保留客户要求的 `合同号/生产订单/物料名称/齐套`,减少横向挤压。
|
||||||
|
4. 调整表格容器左右内边距,从 8px 收紧到 6px。
|
||||||
|
5. 表格单元格增加 `overflow: hidden` 和 `text-overflow: ellipsis`,避免长文本把右侧列挤出面板。
|
||||||
|
6. 表格字号略收紧到表头 15px、表体 14px,保证右侧列完整显示。
|
||||||
|
7. 执行 `npm run build`,构建成功;仍仅有既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已修复四个列表右侧列被挡住的问题。四个列表现在使用百分比列宽,右侧字段可以完整落在面板内。构建验证通过。
|
||||||
|
|
||||||
|
## 2026-07-06 仓库任务大屏图表合并与网格线去除
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户要求:去掉第三行的图表,第一行的数量放入到对应第二行的图表里面;去掉图表里面的横线(Y 轴),数量显示在柱状图上面。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 定位 `src/views/WarehouseDashboard.vue` 中的 8 个图表模板和对应 ECharts 实例。
|
||||||
|
2. 删除第二排独立数量/件数图表,只保留入库任务、拣配任务、及时处理、发货任务 4 个图表。
|
||||||
|
3. 清理第二排 4 个图表对应的 ref、实例变量、初始化、渲染、resize 和 dispose 逻辑。
|
||||||
|
4. 将入库和拣配图表改为双柱展示:条数和件数在同一图表内显示。
|
||||||
|
5. 将及时处理和发货任务图表从原先独立图表/饼图样式统一改为条数与件数双柱图。
|
||||||
|
6. 修改通用柱状图配置,隐藏 Y 轴轴线、刻度、标签和横向网格线。
|
||||||
|
7. 给柱状图两个系列增加顶部标签,直接在柱子上方显示数值。
|
||||||
|
8. 将主体布局改回顶部汇总、4 个图表、4 个列表三段结构。
|
||||||
|
9. 执行 `npm run build`,构建成功;仍仅有既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已去掉第三行图表,将数量/件数合并到对应的 4 个主图表中;图表横线和 Y 轴视觉元素已隐藏,数值直接显示在柱状图上方。构建验证通过。
|
||||||
|
|
||||||
|
## 2026-07-06 仓库任务大屏汇总并入图表与加急口径修正
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户反馈:当前图表数据不对,加急和任务一样多;要求把上边汇总放到对应图表里,基本取消第一行汇总区域。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 检查 `src/views/WarehouseDashboard.vue` 当前实现,确认上一轮把图表第二组数据接成了 `quantity` 件数,导致图例虽显示第二组柱子,但并不是加急口径。
|
||||||
|
2. 删除模板中的顶部 `kpi-row` 汇总卡片区域,不再单独占用第一行。
|
||||||
|
3. 在四个主图表面板内部新增汇总头部,分别显示入库任务、拣配任务、及时处理、发货任务的总条数,并在下方显示件数和加急数量。
|
||||||
|
4. 删除不再使用的 `summaryCards` 计算逻辑,新增 `chartSummaries` 计算对象和 `formatChartSummary` 格式化函数。
|
||||||
|
5. 将内容主体布局从“汇总行 + 图表行 + 列表行”调整为“两行”:第一行为四个图表,第二行为四个列表。
|
||||||
|
6. 将四个列表可见行数从 5 行调整为 8 行,减少取消顶部汇总行之后列表区域显得过空的问题。
|
||||||
|
7. 修正四个柱状图的数据口径:蓝色柱为 `taskCount` 任务,红色柱为 `urgentQty` 加急,不再使用 `quantity` 件数作为红色柱。
|
||||||
|
8. 保留图表内隐藏 Y 轴、隐藏横向网格线、柱顶显示数值的配置。
|
||||||
|
9. 执行静态搜索,确认旧的顶部卡片类名和 `quantity` 红柱绑定已清理。
|
||||||
|
10. 执行 `npm run build`,构建成功;仍仅有既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
11. 检查本地 5173 端口服务仍在监听,并通过 HTTP 请求确认页面入口返回 200。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已将顶部汇总并入四个图表面板,页面主体不再有独立第一行汇总卡片;柱状图已改回“任务 / 加急”口径,避免加急数据误用件数导致看起来与任务一样多。构建验证通过,本地页面入口可访问。
|
||||||
|
|
||||||
|
## 2026-07-06 仓库任务大屏去除件数与异常出库合并
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户要求:
|
||||||
|
1. 四个图表柱状图不要数量(件数),去掉所有件数,只要条数;加急的数量要求是红色。
|
||||||
|
2. 异常出库的数据跟拣配任务一起展示。
|
||||||
|
3. 加大字号显示。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 读取 `src/views/WarehouseDashboard.vue`,确认当前图表头部仍显示“件数 / 加急”,柱状图已显示“任务 / 加急”,但数据库过程里部分 `加急数量` 仍为件数累加。
|
||||||
|
2. 修改四个图表面板头部摘要:去掉所有“件”相关展示,只保留总条数和“加急 X 条”。
|
||||||
|
3. 修改 `formatChartSummary`,返回总条数和加急条数,不再返回件数文本。
|
||||||
|
4. 修改拣配图表:分类从“机加 / 装配”扩展为“机加 / 装配 / 异常出库”,其中异常出库从发货环节的“异常出库”汇总行读取。
|
||||||
|
5. 修改发货图表:分类只保留“发货任务 / 今日”,不再单独展示异常出库。
|
||||||
|
6. 修改拣配图表汇总数:拣配总条数和加急条数合并异常出库数据,保证面板汇总与图表分类一致。
|
||||||
|
7. 放大 ECharts 字号:tooltip、图例、X 轴、柱顶标签均上调字号,柱宽也略加宽。
|
||||||
|
8. 将加急柱顶标签颜色改为红色 `#ff3345`,加急汇总数字也设置为红色。
|
||||||
|
9. 放大页面字号:图表标题、图表主数字、加急摘要、表格标题、表头和表体字号均上调。
|
||||||
|
10. 由于表格字号和行高放大,将列表可见行数从 8 行调整为 7 行,避免 1080 高度下内容被裁切。
|
||||||
|
11. 使用数据库直接执行 `仓库大屏_汇总查询`,发现原过程里发货、及时处理、异常出库等 `加急数量` 是加急件数累加,例如发货任务 13 条但加急显示 131,不符合“只要条数”的要求。
|
||||||
|
12. 查看 `YL_MESDB` 中 `dbo.仓库大屏_汇总查询` 定义,确认入库和拣配加急已是条数,及时处理和发货类仍按 `SUM(加急数量)` 统计件数。
|
||||||
|
13. 初次使用 `sqlcmd` 管道更新过程时遇到中文编码问题,SQL Server 将中文标识识别成问号,执行失败且未成功修改过程。
|
||||||
|
14. 改用 PowerShell `System.Data.SqlClient` 以 Unicode 字符串执行 `ALTER PROCEDURE`,成功更新 `dbo.仓库大屏_汇总查询`。
|
||||||
|
15. 数据库过程调整口径:及时处理入库、及时处理汇报、发货任务、今日、异常出库的 `加急数量` 改为统计 `加急数量 > 0` 的记录条数。
|
||||||
|
16. 重新执行 `仓库大屏_汇总查询` 验证,发货任务变为 13 条、加急 10 条;今日变为 11 条、加急 8 条;异常出库变为 227 条、加急 13 条,符合条数口径。
|
||||||
|
17. 执行 `npm run build`,构建成功;仍仅有既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已去掉图表区域所有件数展示,四个图表统一为条数口径;加急柱顶标签和加急摘要数字已改为红色;异常出库已合并到拣配任务图表,发货图表只保留发货任务和今日;字号已整体放大。数据库汇总过程也已同步修正加急条数口径,避免前端显示加急件数。
|
||||||
|
|
||||||
|
## 2026-07-06 仓库任务大屏发货汇总口径修正
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户反馈:发货任务图表顶部总数明显不对,怀疑忘记去掉异常出库数据。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 根据截图判断:发货图表柱子只显示“发货任务 13”和“今日 11”,但右上角汇总仍显示 250 条、加急 31 条。
|
||||||
|
2. 检查 `src/views/WarehouseDashboard.vue`,确认发货图表分类已经去掉“异常出库”,但图表头部汇总仍调用 `getSectionTotal('发货')`,因此把“异常出库”也算入了总数。
|
||||||
|
3. 新增 `getDeliverySectionTotal`,只合计 `发货 / 发货任务` 与 `发货 / 今日` 两个分类。
|
||||||
|
4. 将 `chartSummaries.delivery` 从 `getSectionTotal('发货')` 改为 `getDeliverySectionTotal()`,保证发货图表顶部数字与图表柱子一致。
|
||||||
|
5. 执行 `npm run build`,构建成功;仍仅有既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已修正发货任务图表顶部汇总口径,异常出库不再计入发货任务顶部总数;当前发货顶部汇总只对应图表里的“发货任务 + 今日”。
|
||||||
|
|
||||||
|
## 2026-07-06 质检测试任务列表增加入库数与合格数
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户要求修改 `C:\WorkYuanLy\装配任务看板\src\views\TestTaskDashboard.vue`:测试装配任务列表在完成数后增加两个字段“入库数”和“合格数”。入库数取 `[dbo].[View_生产订单_MES].入库数量`;合格数取 `[dbo].[YL_质量检验_质检记录].合格数` 的和,关联条件为 `YL_质量检验_质检记录.TaskAID = View_生产订单_MES.TaskAID` 且 `检测类型编号 = 6`;当合格数等于完成数时,该条数据不显示。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 读取 `src/views/TestTaskDashboard.vue`,定位“测试装配任务列表”模板、`taskColumns` 列定义和 `applyTaskData` 数据映射。
|
||||||
|
2. 确认测试装配任务列表当前调用的数据源为 `质量管理_测试装配任务_查询2`。
|
||||||
|
3. 查询数据库 `YL_MESDB` 中 `dbo.质量管理_测试装配任务_查询2` 的定义,确认当前过程已经从 `View_生产订单_MES` 返回 `入库数量`,但没有返回合格数,也没有过滤 `合格数 = 完成数` 的记录。
|
||||||
|
4. 查询数据库字段元数据,确认 `View_生产订单_MES` 包含 `TaskAID/入库数量/完成数量`,`YL_质量检验_质检记录` 包含 `TaskAID/检测类型编号/合格数`。
|
||||||
|
5. 更新存储过程 `dbo.质量管理_测试装配任务_查询2`:增加按 `TaskAID` 汇总的质检记录子查询,只统计 `检测类型编号 = 6` 的 `合格数`。
|
||||||
|
6. 在过程返回字段中新增 `ISNULL(qc.合格数, 0) AS 合格数`。
|
||||||
|
7. 在过程过滤条件中增加 `ISNULL(qc.合格数, 0) <> ISNULL(pt.完成数量, 0)`,过滤掉合格数等于完成数的任务。
|
||||||
|
8. 执行过程验证,确认结果返回列包含 `入库数量` 和 `合格数`。
|
||||||
|
9. 额外执行核对 SQL,确认过滤后的结果中不存在 `合格数 = 完成数` 的记录。
|
||||||
|
10. 修改 `src/views/TestTaskDashboard.vue`:`applyTaskData` 中增加前端兜底过滤 `合格数 !== 完成数量`。
|
||||||
|
11. 修改 `applyTaskData` 映射,新增 `inboundQty` 取 `入库数量`,`passQty` 取 `合格数`。
|
||||||
|
12. 修改 `taskColumns`,在“完成数”后增加“入库数”和“合格数”两列,并适当缩小“操作人”列宽。
|
||||||
|
13. 执行 `npm run build`,构建成功;仍仅有既有 Sass legacy JS API 提示和 Vite chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已完成测试装配任务列表改造:完成数后新增入库数和合格数;合格数按 `检测类型编号 = 6` 的质检记录汇总;合格数等于完成数的任务已在数据库过程和前端双重过滤。构建验证通过。
|
||||||
|
## 2026-07-08 修复装配与质检测试看板右上角时间
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户要求修改 `C:\WorkYuanLy\装配任务看板\src\views\index.vue` 和 `C:\WorkYuanLy\装配任务看板\src\views\TestTaskDashboard.vue`,反馈右上角时间不对。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 读取 `src/views/index.vue` 和 `src/views/TestTaskDashboard.vue`,定位右上角时间显示绑定为 `currentTime`。
|
||||||
|
2. 检索项目中时间相关实现,确认两个目标文件都将 `now` 初始化为固定时间 `2026-05-06 10:10:10`。
|
||||||
|
3. 确认两个目标文件的定时器逻辑都是基于旧的 `now.value` 每秒加 1000 毫秒,因此页面显示的是从固定时间递增的模拟时间,不是系统当前时间,并且页面休眠或定时器暂停后也容易产生偏差。
|
||||||
|
4. 修改 `src/views/index.vue`:将 `const now = ref(new Date('2026-05-06 10:10:10'))` 改为 `const now = ref(new Date())`。
|
||||||
|
5. 修改 `src/views/index.vue`:在 `startClock` 启动时立即刷新一次 `now.value = new Date()`,并将定时器更新逻辑改为每秒直接读取 `new Date()`。
|
||||||
|
6. 修改 `src/views/TestTaskDashboard.vue`:将 `const now = ref(new Date('2026-05-06 10:10:10'))` 改为 `const now = ref(new Date())`。
|
||||||
|
7. 修改 `src/views/TestTaskDashboard.vue`:将 `startClock` 改为启动时立即读取当前系统时间,后续每秒直接读取 `new Date()`。
|
||||||
|
8. 查看 `git diff`,确认本次修改集中在右上角时钟相关逻辑;同时注意到两个目标文件中存在其他既有未提交改动,本次没有回退或改写这些无关内容。
|
||||||
|
9. 查看 `package.json`,确认项目可用校验脚本为 `npm run build`。
|
||||||
|
10. 执行 `npm run build`,Vite 构建成功;输出中仅保留既有 Sass legacy JS API 提示和 chunk size 警告。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
已修复两个看板右上角时间不对的问题。`index.vue` 和 `TestTaskDashboard.vue` 现在都会以系统当前时间初始化,并在运行中每秒直接读取当前系统时间,避免继续显示固定的 `2026-05-06 10:10:10` 模拟时间。构建验证通过。
|
||||||
|
## 2026-07-08 上传所有修改到远程
|
||||||
|
|
||||||
|
### 提问
|
||||||
|
用户要求:上传所有的修改到远程。
|
||||||
|
|
||||||
|
### 执行过程
|
||||||
|
1. 检查当前 Git 工作区状态,确认存在已修改文件:`dist.zip`、`gptlog-process/gpdlog.md`、`src/utils/request.js`、`src/views/TestTaskDashboard.vue`、`src/views/WarehouseDashboard.vue`、`src/views/index.vue`。
|
||||||
|
2. 检查未跟踪文件,确认 `doc/未完成计划.xlsx` 和 `doc/~$未完成计划.xlsx` 也在当前工作区内;由于用户要求上传所有修改,本次按全部纳入处理。
|
||||||
|
3. 检查当前分支,确认当前位于 `main` 分支。
|
||||||
|
4. 检查远程仓库,确认 `origin` 指向 `http://154.8.160.151:3000/zhangxinyang/zhuangpei-task-kanban.git`。
|
||||||
|
5. 检查最新本地提交,当前提交为 `4e4a419 docs: update upload log`。
|
||||||
|
6. 执行 `git fetch origin`,刷新远程引用。
|
||||||
|
7. 执行 `git status -sb`,确认 `main` 与 `origin/main` 未显示 ahead/behind 分歧。
|
||||||
|
8. 查看 `git diff --stat`,确认本次待上传改动包含日志、看板页面、请求配置、压缩包等文件。
|
||||||
|
9. 按项目日志规则,将本次提问、执行过程和结论追加到 `gptlog-process/gpdlog.md`,使日志文件也随本次提交上传。
|
||||||
|
10. 准备执行 `git add -A` 暂存所有修改,随后创建提交并推送到 `origin/main`。
|
||||||
|
|
||||||
|
### 结论
|
||||||
|
本次将按“所有修改”口径提交并推送当前工作区全部变更到远程 `origin/main`,包括本次追加的中文执行日志。
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const request_config = window.g.API_WEB_URL + `/submit/MESCommonBase.ashx`
|
|||||||
export const name = name_config
|
export const name = name_config
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: request_config,
|
baseURL: request_config,
|
||||||
timeout: 1000 * 5 // 请求超时时间
|
timeout: 1000 * 15 // 请求超时时间
|
||||||
})
|
})
|
||||||
|
|
||||||
// && config.data.name !== '菜单系统模块_通知信息_查询数据' && config.data.name !== '菜单系统模块_首页信息_查询数据1' && config.data.name !== '菜单系统模块_首页信息_查询数据2'
|
// && config.data.name !== '菜单系统模块_通知信息_查询数据' && config.data.name !== '菜单系统模块_首页信息_查询数据1' && config.data.name !== '菜单系统模块_首页信息_查询数据2'
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ const CreateData = inject('CreateData')
|
|||||||
const ExecDatabase = inject('ExecDatabase')
|
const ExecDatabase = inject('ExecDatabase')
|
||||||
defineOptions({ name: 'AssemblyCenterTaskDashboard' })
|
defineOptions({ name: 'AssemblyCenterTaskDashboard' })
|
||||||
|
|
||||||
const now = ref(new Date('2026-05-06 10:10:10'))
|
const now = ref(new Date())
|
||||||
let timer = null
|
let timer = null
|
||||||
let resizeHandler = null
|
let resizeHandler = null
|
||||||
let scrollTimers = []
|
let scrollTimers = []
|
||||||
@@ -203,7 +203,7 @@ const VISIBLE_ROWS = {
|
|||||||
const testSummaryGroups = [
|
const testSummaryGroups = [
|
||||||
{
|
{
|
||||||
key: 'valve',
|
key: 'valve',
|
||||||
label: '阀类',
|
label: '部件类',
|
||||||
products: [
|
products: [
|
||||||
{ key: 'valveMain', label: '阀', image: valveImage },
|
{ key: 'valveMain', label: '阀', image: valveImage },
|
||||||
{ key: 'valveOther', label: '其他', image: otherImage }
|
{ key: 'valveOther', label: '其他', image: otherImage }
|
||||||
@@ -329,7 +329,7 @@ const searchTestAssemblyTaskData = () => {
|
|||||||
['物料名称', ''],
|
['物料名称', ''],
|
||||||
['物料编码', '']
|
['物料编码', '']
|
||||||
]
|
]
|
||||||
queryDashboardData('质量管理_测试装配任务_查询', applyTestAssemblyTaskData, param)
|
queryDashboardData('质检测试看板_测试装配任务_查询', applyTestAssemblyTaskData, param)
|
||||||
}
|
}
|
||||||
const searchTestAssemblyTaskListData = () => {
|
const searchTestAssemblyTaskListData = () => {
|
||||||
queryDashboardData('质量管理_测试装配任务_查询2', applyTaskData)
|
queryDashboardData('质量管理_测试装配任务_查询2', applyTaskData)
|
||||||
@@ -372,7 +372,7 @@ const searchStagnationData = () => {
|
|||||||
queryDashboardData('质量管理_及时检验报表_查询', applyStagnationData, param)
|
queryDashboardData('质量管理_及时检验报表_查询', applyStagnationData, param)
|
||||||
}
|
}
|
||||||
const searchDeliveryData = () => {
|
const searchDeliveryData = () => {
|
||||||
queryDashboardData('装配中心任务看板_质检发货状态查询', applyDeliveryData)
|
queryDashboardData('质检测试看板_质检发货状态查询', applyDeliveryData)
|
||||||
}
|
}
|
||||||
const applyTestAssemblyTaskData = rows => {
|
const applyTestAssemblyTaskData = rows => {
|
||||||
const sortedRows = sortTestAssemblyTaskRows(rows)
|
const sortedRows = sortTestAssemblyTaskRows(rows)
|
||||||
@@ -431,7 +431,7 @@ const applyDoneTaskData = rows => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const applyTaskData = rows => {
|
const applyTaskData = rows => {
|
||||||
taskRows.value = rows.map(item => ({
|
taskRows.value = rows.filter(item => getNumber(item.合格数) !== getNumber(item.完成数量)).map(item => ({
|
||||||
productionOrder: item.生产订单?.toString() || item.订单号?.toString() || item.计划号?.toString() || '',
|
productionOrder: item.生产订单?.toString() || item.订单号?.toString() || item.计划号?.toString() || '',
|
||||||
salesOrder: item.销售订单 || item.合同号 || '',
|
salesOrder: item.销售订单 || item.合同号 || '',
|
||||||
materialName: item.物料名称 || item.物料描述 || item.零件名称 || '',
|
materialName: item.物料名称 || item.物料描述 || item.零件名称 || '',
|
||||||
@@ -440,6 +440,8 @@ const applyTaskData = rows => {
|
|||||||
urgentQty: getNumber(item.加急总数 || item.加急数量),
|
urgentQty: getNumber(item.加急总数 || item.加急数量),
|
||||||
assignQty: getNumber(item.计划数量 || item.计划生产数 || item.分配数),
|
assignQty: getNumber(item.计划数量 || item.计划生产数 || item.分配数),
|
||||||
completeQty: getNumber(item.完成数量),
|
completeQty: getNumber(item.完成数量),
|
||||||
|
inboundQty: getNumber(item.入库数量),
|
||||||
|
passQty: getNumber(item.合格数),
|
||||||
operator: item.操作人 || ''
|
operator: item.操作人 || ''
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -503,9 +505,9 @@ const normalizeText = value => {
|
|||||||
return String(value).trim()
|
return String(value).trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMaterialCodeText = item => normalizeText(getField(item, ['物料编码', '零件编码', '物料编号', '零件编号', '产品编码']))
|
const getMaterialCodeText = item => normalizeText(getField(item, ['零件名称']))
|
||||||
|
|
||||||
const getAssignTargetText = item => normalizeText(getField(item, ['指派对象', '二次派工']))
|
const getAssignTargetText = item => normalizeText(getField(item, ['工位名称', '二次派工']))
|
||||||
|
|
||||||
const getTaskType = item => item.任务类型 || (String(item.自制件属性 || item.物料名称 || item.零件名称 || '').includes('系统') ? '系统类' : '阀类')
|
const getTaskType = item => item.任务类型 || (String(item.自制件属性 || item.物料名称 || item.零件名称 || '').includes('系统') ? '系统类' : '阀类')
|
||||||
|
|
||||||
@@ -573,7 +575,7 @@ const getPassRate = item => {
|
|||||||
return Number(((getNumber(item.检验合格数量) * 100) / inspectQty).toFixed(2))
|
return Number(((getNumber(item.检验合格数量) * 100) / inspectQty).toFixed(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
const startClock = () => { timer = window.setInterval(() => { now.value = new Date(now.value.getTime() + 1000) }, 1000) }
|
const startClock = () => { now.value = new Date(); timer = window.setInterval(() => { now.value = new Date() }, 1000) }
|
||||||
const svgData = svg => 'data:image/svg+xml;utf8,' + encodeURIComponent(svg)
|
const svgData = svg => 'data:image/svg+xml;utf8,' + encodeURIComponent(svg)
|
||||||
const svgIcon = (from, to, body) => svgData(
|
const svgIcon = (from, to, body) => svgData(
|
||||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" fill="none">
|
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72 72" fill="none">
|
||||||
@@ -621,7 +623,9 @@ const taskColumns = [
|
|||||||
{ label: '加急数', key: 'urgentQty', width: '62px' },
|
{ label: '加急数', key: 'urgentQty', width: '62px' },
|
||||||
{ label: '计划数', key: 'assignQty', width: '70px' },
|
{ label: '计划数', key: 'assignQty', width: '70px' },
|
||||||
{ label: '完成数', key: 'completeQty', width: '70px' },
|
{ label: '完成数', key: 'completeQty', width: '70px' },
|
||||||
{ label: '操作人', key: 'operator', width: '120px' },
|
{ label: '入库数', key: 'inboundQty', width: '70px' },
|
||||||
|
{ label: '合格数', key: 'passQty', width: '70px' },
|
||||||
|
{ label: '操作人', key: 'operator', width: '100px' },
|
||||||
|
|
||||||
]
|
]
|
||||||
const taskColumns2 = [
|
const taskColumns2 = [
|
||||||
@@ -1115,8 +1119,8 @@ th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.summary-product-image {
|
.summary-product-image {
|
||||||
width: 82px;
|
width: 130px;
|
||||||
height: 62px;
|
height: 75px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,37 +11,62 @@
|
|||||||
<h1>仓库任务大屏</h1>
|
<h1>仓库任务大屏</h1>
|
||||||
<div class="time-block">
|
<div class="time-block">
|
||||||
<div class="current-time">{{ currentTime }}</div>
|
<div class="current-time">{{ currentTime }}</div>
|
||||||
<div class="refresh-time">数据刷新 {{ refreshTimeText }}</div>
|
<!-- <div class="refresh-time">数据刷新 {{ refreshTimeText }}</div> -->
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="dashboard-content">
|
<main class="dashboard-content">
|
||||||
<section class="kpi-row">
|
|
||||||
<article v-for="item in summaryCards" :key="item.key" class="panel kpi-card" :class="item.className">
|
|
||||||
<div class="kpi-title">{{ item.title }}</div>
|
|
||||||
<div class="kpi-value">
|
|
||||||
<span>{{ item.value }}</span>
|
|
||||||
<small>{{ item.unit }}</small>
|
|
||||||
</div>
|
|
||||||
<div class="kpi-sub">{{ item.subText }}</div>
|
|
||||||
</article>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="chart-grid">
|
<section class="chart-grid">
|
||||||
<article class="panel chart-panel">
|
<article class="panel chart-panel">
|
||||||
<div class="panel-caption">入库任务结构</div>
|
<div class="chart-panel-head">
|
||||||
|
<div class="chart-title">入库任务</div>
|
||||||
|
<div class="chart-summary">
|
||||||
|
<div class="chart-summary-value">
|
||||||
|
<span>{{ chartSummaries.inbound.value }}</span>
|
||||||
|
<small>条</small>
|
||||||
|
</div>
|
||||||
|
<div class="chart-summary-sub">加急 <span>{{ chartSummaries.inbound.urgent }}</span> 条</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div ref="inboundChartRef" class="chart-box"></div>
|
<div ref="inboundChartRef" class="chart-box"></div>
|
||||||
</article>
|
</article>
|
||||||
<article class="panel chart-panel">
|
<article class="panel chart-panel">
|
||||||
<div class="panel-caption">拣配任务结构</div>
|
<div class="chart-panel-head">
|
||||||
|
<div class="chart-title">拣配任务</div>
|
||||||
|
<div class="chart-summary">
|
||||||
|
<div class="chart-summary-value">
|
||||||
|
<span>{{ chartSummaries.picking.value }}</span>
|
||||||
|
<small>条</small>
|
||||||
|
</div>
|
||||||
|
<div class="chart-summary-sub">加急 <span>{{ chartSummaries.picking.urgent }}</span> 条</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div ref="pickingChartRef" class="chart-box"></div>
|
<div ref="pickingChartRef" class="chart-box"></div>
|
||||||
</article>
|
</article>
|
||||||
<article class="panel chart-panel">
|
<article class="panel chart-panel">
|
||||||
<div class="panel-caption">超期风险分布</div>
|
<div class="chart-panel-head">
|
||||||
|
<div class="chart-title">及时处理</div>
|
||||||
|
<div class="chart-summary">
|
||||||
|
<div class="chart-summary-value">
|
||||||
|
<span>{{ chartSummaries.timely.value }}</span>
|
||||||
|
<small>条</small>
|
||||||
|
</div>
|
||||||
|
<div class="chart-summary-sub">加急 <span>{{ chartSummaries.timely.urgent }}</span> 条</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div ref="riskChartRef" class="chart-box"></div>
|
<div ref="riskChartRef" class="chart-box"></div>
|
||||||
</article>
|
</article>
|
||||||
<article class="panel chart-panel">
|
<article class="panel chart-panel">
|
||||||
<div class="panel-caption">今日发货保障</div>
|
<div class="chart-panel-head">
|
||||||
|
<div class="chart-title">发货任务</div>
|
||||||
|
<div class="chart-summary">
|
||||||
|
<div class="chart-summary-value">
|
||||||
|
<span>{{ chartSummaries.delivery.value }}</span>
|
||||||
|
<small>条</small>
|
||||||
|
</div>
|
||||||
|
<div class="chart-summary-sub">加急 <span>{{ chartSummaries.delivery.urgent }}</span> 条</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div ref="deliveryChartRef" class="chart-box"></div>
|
<div ref="deliveryChartRef" class="chart-box"></div>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
@@ -112,125 +137,60 @@ const deliveryChartRef = ref(null)
|
|||||||
const summaryRows = ref([])
|
const summaryRows = ref([])
|
||||||
const inboundOverdueRows = ref([])
|
const inboundOverdueRows = ref([])
|
||||||
const outboundOverdueRows = ref([])
|
const outboundOverdueRows = ref([])
|
||||||
|
const urgentPickingRows = ref([])
|
||||||
const todayDeliveryRows = ref([])
|
const todayDeliveryRows = ref([])
|
||||||
const inboundOffset = ref(0)
|
const inboundOffset = ref(0)
|
||||||
const outboundOffset = ref(0)
|
const outboundOffset = ref(0)
|
||||||
|
const urgentPickingOffset = ref(0)
|
||||||
const deliveryOffset = ref(0)
|
const deliveryOffset = ref(0)
|
||||||
|
|
||||||
const VISIBLE_ROWS = {
|
const VISIBLE_ROWS = {
|
||||||
inbound: 6,
|
inbound: 7,
|
||||||
outbound: 6,
|
outbound: 7,
|
||||||
delivery: 6
|
urgentPicking: 7,
|
||||||
|
delivery: 7
|
||||||
}
|
}
|
||||||
|
|
||||||
const inboundCategories = ['装配件', '机加件', '原材料', '外购件']
|
const inboundCategories = ['原料', '零件', '机加', '装配']
|
||||||
const pickingCategories = ['装配件', '机加件']
|
const pickingCategories = ['机加', '装配']
|
||||||
const riskCategories = ['超2天未入库', '超2天未上架', '超10天未出库', '汇报未清']
|
const riskCategories = ['上架', '入库', '汇报']
|
||||||
|
|
||||||
const currentTime = computed(() => formatDateTime(now.value))
|
const currentTime = computed(() => formatDateTime(now.value))
|
||||||
const refreshTimeText = computed(() => lastRefreshTime.value || '--:--:--')
|
const refreshTimeText = computed(() => lastRefreshTime.value || '--:--:--')
|
||||||
|
const chartSummaries = computed(() => ({
|
||||||
const summaryCards = computed(() => {
|
inbound: formatChartSummary(getSectionTotal('入库')),
|
||||||
const inboundTaskQty = sumRows('入库', 'quantity')
|
picking: formatChartSummary(getPickingSectionTotal()),
|
||||||
const inboundUrgentQty = sumRows('入库', 'urgentQty')
|
timely: formatChartSummary(getSectionTotal('及时处理')),
|
||||||
const inboundItemCount = sumRows('入库', 'taskCount')
|
delivery: formatChartSummary(getDeliverySectionTotal())
|
||||||
const pickingTaskQty = sumRows('拣配', 'quantity')
|
}))
|
||||||
const pickingUrgentQty = sumRows('拣配', 'urgentQty')
|
|
||||||
const pickingItemCount = sumRows('拣配', 'taskCount')
|
|
||||||
const overdueInbound = getSummaryRow('风险', '超2天未入库')
|
|
||||||
const overdueInventory = getSummaryRow('风险', '超2天未上架')
|
|
||||||
const overdueOutbound = getSummaryRow('风险', '超10天未出库')
|
|
||||||
const reportOpen = getSummaryRow('风险', '汇报未清')
|
|
||||||
const todayDelivery = getSummaryRow('发货', '今日应发')
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
key: 'inbound',
|
|
||||||
title: '待入库任务',
|
|
||||||
value: formatCompactNumber(inboundTaskQty),
|
|
||||||
unit: '条',
|
|
||||||
subText: `${formatAmount(inboundItemCount)} 项物料`,
|
|
||||||
className: 'blue-card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'inboundUrgent',
|
|
||||||
title: '入库加急',
|
|
||||||
value: formatCompactNumber(inboundUrgentQty),
|
|
||||||
unit: '条',
|
|
||||||
subText: `加急占比 ${formatPercent(inboundUrgentQty, inboundTaskQty)}`,
|
|
||||||
className: 'red-card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'overdueInbound',
|
|
||||||
title: '超2天未入库',
|
|
||||||
value: formatCompactNumber(overdueInbound.quantity),
|
|
||||||
unit: '件',
|
|
||||||
subText: `${formatAmount(overdueInbound.taskCount)} 条任务`,
|
|
||||||
className: 'orange-card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'overdueInventory',
|
|
||||||
title: '超2天未上架',
|
|
||||||
value: formatCompactNumber(overdueInventory.quantity),
|
|
||||||
unit: '件',
|
|
||||||
subText: `${formatAmount(overdueInventory.taskCount)} 条物料`,
|
|
||||||
className: 'orange-card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'picking',
|
|
||||||
title: '未清拣配',
|
|
||||||
value: formatCompactNumber(pickingTaskQty),
|
|
||||||
unit: '条',
|
|
||||||
subText: `${formatAmount(pickingItemCount)} 项物料`,
|
|
||||||
className: 'blue-card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'overdueOutbound',
|
|
||||||
title: '超10天未出库',
|
|
||||||
value: formatCompactNumber(overdueOutbound.quantity),
|
|
||||||
unit: '件',
|
|
||||||
subText: `${formatAmount(overdueOutbound.taskCount)} 条任务`,
|
|
||||||
className: 'red-card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'reportOpen',
|
|
||||||
title: '汇报未清',
|
|
||||||
value: formatCompactNumber(reportOpen.quantity),
|
|
||||||
unit: '件',
|
|
||||||
subText: `加急 ${formatCompactNumber(reportOpen.urgentQty)}`,
|
|
||||||
className: 'red-card'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'todayDelivery',
|
|
||||||
title: '今日应发',
|
|
||||||
value: formatCompactNumber(todayDelivery.quantity),
|
|
||||||
unit: '件',
|
|
||||||
subText: `${formatAmount(todayDelivery.taskCount)} 单 / 加急 ${formatCompactNumber(todayDelivery.urgentQty)}`,
|
|
||||||
className: todayDelivery.urgentQty > 0 ? 'red-card' : 'green-card'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
const inboundDisplayRows = computed(() => makeDisplayRows(inboundOverdueRows.value, inboundOffset.value, VISIBLE_ROWS.inbound))
|
const inboundDisplayRows = computed(() => makeDisplayRows(inboundOverdueRows.value, inboundOffset.value, VISIBLE_ROWS.inbound))
|
||||||
const outboundDisplayRows = computed(() => makeDisplayRows(outboundOverdueRows.value, outboundOffset.value, VISIBLE_ROWS.outbound))
|
const outboundDisplayRows = computed(() => makeDisplayRows(outboundOverdueRows.value, outboundOffset.value, VISIBLE_ROWS.outbound))
|
||||||
|
const urgentPickingDisplayRows = computed(() => makeDisplayRows(urgentPickingRows.value, urgentPickingOffset.value, VISIBLE_ROWS.urgentPicking))
|
||||||
const deliveryDisplayRows = computed(() => makeDisplayRows(todayDeliveryRows.value, deliveryOffset.value, VISIBLE_ROWS.delivery))
|
const deliveryDisplayRows = computed(() => makeDisplayRows(todayDeliveryRows.value, deliveryOffset.value, VISIBLE_ROWS.delivery))
|
||||||
|
|
||||||
const detailTables = computed(() => [
|
const detailTables = computed(() => [
|
||||||
{
|
{
|
||||||
key: 'inbound',
|
key: 'inbound',
|
||||||
title: '超2天未入库明细',
|
title: '加急入库列表',
|
||||||
columns: inboundColumns,
|
columns: urgentInboundColumns,
|
||||||
rows: inboundDisplayRows.value
|
rows: inboundDisplayRows.value
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'outbound',
|
key: 'outbound',
|
||||||
title: '超10天未出库明细',
|
title: '拣配任务列表',
|
||||||
columns: outboundColumns,
|
columns: pickingColumns,
|
||||||
rows: outboundDisplayRows.value
|
rows: outboundDisplayRows.value
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'urgentPicking',
|
||||||
|
title: '加急拣配列表',
|
||||||
|
columns: urgentPickingColumns,
|
||||||
|
rows: urgentPickingDisplayRows.value
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'delivery',
|
key: 'delivery',
|
||||||
title: '今日应发明细',
|
title: '发货任务列表',
|
||||||
columns: deliveryColumns,
|
columns: deliveryColumns,
|
||||||
rows: deliveryDisplayRows.value
|
rows: deliveryDisplayRows.value
|
||||||
}
|
}
|
||||||
@@ -333,9 +293,10 @@ const disposeCharts = () => {
|
|||||||
const searchDashboardData = () => {
|
const searchDashboardData = () => {
|
||||||
const tasks = [
|
const tasks = [
|
||||||
queryDashboardData('仓库大屏_汇总查询', applySummaryData),
|
queryDashboardData('仓库大屏_汇总查询', applySummaryData),
|
||||||
queryDashboardData('仓库大屏_入库超期明细', applyInboundOverdueData),
|
queryDashboardData('仓库大屏_加急入库列表', applyInboundOverdueData),
|
||||||
queryDashboardData('仓库大屏_出库超期明细', applyOutboundOverdueData),
|
queryDashboardData('仓库大屏_拣配任务列表', applyOutboundOverdueData),
|
||||||
queryDashboardData('仓库大屏_今日应发明细', applyTodayDeliveryData)
|
queryDashboardData('仓库大屏_加急拣配列表', applyUrgentPickingData),
|
||||||
|
queryDashboardData('装配中心任务看板_发货状态查询', applyTodayDeliveryData)
|
||||||
]
|
]
|
||||||
|
|
||||||
Promise.all(tasks).finally(() => {
|
Promise.all(tasks).finally(() => {
|
||||||
@@ -378,6 +339,10 @@ const getResponseRows = response => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const applySummaryData = rows => {
|
const applySummaryData = rows => {
|
||||||
|
if (!Array.isArray(rows) || rows.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
summaryRows.value = rows.map(row => ({
|
summaryRows.value = rows.map(row => ({
|
||||||
section: normalizeText(row.环节),
|
section: normalizeText(row.环节),
|
||||||
category: normalizeText(row.分类),
|
category: normalizeText(row.分类),
|
||||||
@@ -392,11 +357,9 @@ const applyInboundOverdueData = rows => {
|
|||||||
inboundOffset.value = 0
|
inboundOffset.value = 0
|
||||||
inboundOverdueRows.value = rows.map((row, index) => ({
|
inboundOverdueRows.value = rows.map((row, index) => ({
|
||||||
_idx: index + 1,
|
_idx: index + 1,
|
||||||
docDate: formatDateValue(row.单据日期),
|
category: normalizeText(row.类别),
|
||||||
orderNo: normalizeText(row.订单号),
|
orderNo: normalizeText(row.单号),
|
||||||
itemCode: normalizeText(row.物料编码),
|
|
||||||
itemName: normalizeText(row.物料名称),
|
itemName: normalizeText(row.物料名称),
|
||||||
quantity: formatAmount(row.未入库数量, 2),
|
|
||||||
urgentQty: formatAmount(row.加急数量, 2),
|
urgentQty: formatAmount(row.加急数量, 2),
|
||||||
urgentValue: toNumber(row.加急数量)
|
urgentValue: toNumber(row.加急数量)
|
||||||
}))
|
}))
|
||||||
@@ -406,14 +369,24 @@ const applyOutboundOverdueData = rows => {
|
|||||||
outboundOffset.value = 0
|
outboundOffset.value = 0
|
||||||
outboundOverdueRows.value = rows.map((row, index) => ({
|
outboundOverdueRows.value = rows.map((row, index) => ({
|
||||||
_idx: index + 1,
|
_idx: index + 1,
|
||||||
pickNo: normalizeText(row.拣配清单号),
|
salesOrder: normalizeText(row.合同号),
|
||||||
pickDate: formatDateValue(row.拣配日期),
|
productionOrder: normalizeText(row.生产订单),
|
||||||
productionOrder: normalizeText(row.生产订单号),
|
itemName: normalizeText(row.物料名称),
|
||||||
itemCode: normalizeText(row.物料编码),
|
completeSet: normalizeText(row.齐套),
|
||||||
itemName: normalizeText(row.物料描述),
|
status: normalizeText(row.状态),
|
||||||
planQty: formatAmount(row.计划数量, 2),
|
urgentValue: 0
|
||||||
urgentQty: formatAmount(row.加急数量, 2),
|
}))
|
||||||
urgentValue: toNumber(row.加急数量)
|
}
|
||||||
|
|
||||||
|
const applyUrgentPickingData = rows => {
|
||||||
|
urgentPickingOffset.value = 0
|
||||||
|
urgentPickingRows.value = rows.map((row, index) => ({
|
||||||
|
_idx: index + 1,
|
||||||
|
category: normalizeText(row.类别),
|
||||||
|
orderNo: normalizeText(row.单号),
|
||||||
|
itemName: normalizeText(row.物料名称),
|
||||||
|
urgentStatus: normalizeText(row.加急状态),
|
||||||
|
urgentValue: 1
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,20 +394,19 @@ const applyTodayDeliveryData = rows => {
|
|||||||
deliveryOffset.value = 0
|
deliveryOffset.value = 0
|
||||||
todayDeliveryRows.value = rows.map((row, index) => ({
|
todayDeliveryRows.value = rows.map((row, index) => ({
|
||||||
_idx: index + 1,
|
_idx: index + 1,
|
||||||
deliveryDate: formatDateValue(row.发货日期),
|
salesOrder: normalizeText(row.合同号),
|
||||||
customer: normalizeText(row.客户),
|
itemName: normalizeText(row.物料描述 || row.物料名称),
|
||||||
externalNo: normalizeText(row.外部单号 || row.订单号),
|
deliveryQty: formatAmount(row.交货数量 || row.计划数量, 2),
|
||||||
itemCode: normalizeText(row.物料编码),
|
deliveryDate: formatDateValue(row.要求发货日期 || row.发货日期),
|
||||||
itemName: normalizeText(row.物料名称),
|
testQty: formatAmount(row.检验数量, 2),
|
||||||
openQty: formatAmount(row.未清数量, 2),
|
urgentValue: toNumber(row.加急总数 || row.加急数量)
|
||||||
urgentQty: formatAmount(row.加急数量, 2),
|
|
||||||
urgentValue: toNumber(row.加急数量)
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
const startAllScroll = () => {
|
const startAllScroll = () => {
|
||||||
startScrollWhenOverflow(inboundOverdueRows, inboundOffset, VISIBLE_ROWS.inbound)
|
startScrollWhenOverflow(inboundOverdueRows, inboundOffset, VISIBLE_ROWS.inbound)
|
||||||
startScrollWhenOverflow(outboundOverdueRows, outboundOffset, VISIBLE_ROWS.outbound)
|
startScrollWhenOverflow(outboundOverdueRows, outboundOffset, VISIBLE_ROWS.outbound)
|
||||||
|
startScrollWhenOverflow(urgentPickingRows, urgentPickingOffset, VISIBLE_ROWS.urgentPicking)
|
||||||
startScrollWhenOverflow(todayDeliveryRows, deliveryOffset, VISIBLE_ROWS.delivery)
|
startScrollWhenOverflow(todayDeliveryRows, deliveryOffset, VISIBLE_ROWS.delivery)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,18 +443,24 @@ const makeDisplayRows = (rows, offset, visibleCount) => {
|
|||||||
|
|
||||||
const createInboundChartOption = () => createBarOption({
|
const createInboundChartOption = () => createBarOption({
|
||||||
categories: inboundCategories,
|
categories: inboundCategories,
|
||||||
totalName: '未入库任务',
|
totalName: '任务',
|
||||||
urgentName: '加急任务',
|
urgentName: '加急',
|
||||||
totalData: inboundCategories.map(category => getSummaryRow('入库', category).quantity),
|
totalData: inboundCategories.map(category => getSummaryRow('入库', category).taskCount),
|
||||||
urgentData: inboundCategories.map(category => getSummaryRow('入库', category).urgentQty)
|
urgentData: inboundCategories.map(category => getSummaryRow('入库', category).urgentQty)
|
||||||
})
|
})
|
||||||
|
|
||||||
const createPickingChartOption = () => createBarOption({
|
const createPickingChartOption = () => createBarOption({
|
||||||
categories: pickingCategories,
|
categories: [...pickingCategories, '异常出库'],
|
||||||
totalName: '未清拣配',
|
totalName: '任务',
|
||||||
urgentName: '加急拣配',
|
urgentName: '加急',
|
||||||
totalData: pickingCategories.map(category => getSummaryRow('拣配', category).quantity),
|
totalData: [
|
||||||
urgentData: pickingCategories.map(category => getSummaryRow('拣配', category).urgentQty)
|
...pickingCategories.map(category => getSummaryRow('拣配', category).taskCount),
|
||||||
|
getSummaryRow('发货', '异常出库').taskCount
|
||||||
|
],
|
||||||
|
urgentData: [
|
||||||
|
...pickingCategories.map(category => getSummaryRow('拣配', category).urgentQty),
|
||||||
|
getSummaryRow('发货', '异常出库').urgentQty
|
||||||
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
const createBarOption = ({ categories, totalName, urgentName, totalData, urgentData }) => ({
|
const createBarOption = ({ categories, totalName, urgentName, totalData, urgentData }) => ({
|
||||||
@@ -492,170 +470,92 @@ const createBarOption = ({ categories, totalName, urgentName, totalData, urgentD
|
|||||||
axisPointer: { type: 'shadow' },
|
axisPointer: { type: 'shadow' },
|
||||||
backgroundColor: 'rgba(3, 16, 48, 0.94)',
|
backgroundColor: 'rgba(3, 16, 48, 0.94)',
|
||||||
borderColor: 'rgba(43, 216, 255, 0.55)',
|
borderColor: 'rgba(43, 216, 255, 0.55)',
|
||||||
textStyle: { color: '#f3f9ff' },
|
textStyle: { color: '#f3f9ff', fontSize: 19 },
|
||||||
valueFormatter: value => formatAmount(value, 2)
|
valueFormatter: value => formatAmount(value, 2)
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
top: 0,
|
top: 0,
|
||||||
right: 18,
|
right: 18,
|
||||||
itemWidth: 14,
|
itemWidth: 18,
|
||||||
itemHeight: 10,
|
itemHeight: 12,
|
||||||
textStyle: { color: '#bde9ff', fontSize: 13 }
|
textStyle: { color: '#bde9ff', fontSize: 19 }
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
left: 58,
|
left: 18,
|
||||||
right: 24,
|
right: 18,
|
||||||
top: 48,
|
top: 46,
|
||||||
bottom: 38
|
bottom: 36,
|
||||||
|
containLabel: true
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
data: categories,
|
data: categories,
|
||||||
axisLine: { lineStyle: { color: 'rgba(141, 211, 255, 0.6)' } },
|
axisLine: { lineStyle: { color: 'rgba(141, 211, 255, 0.6)' } },
|
||||||
axisTick: { show: false },
|
axisTick: { show: false },
|
||||||
axisLabel: { color: '#d8f3ff', fontSize: 15 }
|
axisLabel: { color: '#d8f3ff', fontSize: 21, fontWeight: 700 }
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
splitLine: { lineStyle: { color: 'rgba(95, 172, 231, 0.18)' } },
|
axisLine: { show: false },
|
||||||
axisLabel: {
|
axisTick: { show: false },
|
||||||
color: '#9bdcff',
|
axisLabel: { show: false },
|
||||||
formatter: value => formatCompactNumber(value)
|
splitLine: { show: false }
|
||||||
}
|
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: totalName,
|
name: totalName,
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: 28,
|
barWidth: 32,
|
||||||
data: totalData,
|
data: totalData,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderRadius: [3, 3, 0, 0]
|
borderRadius: [3, 3, 0, 0]
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
color: '#f3f9ff',
|
||||||
|
fontSize: 19,
|
||||||
|
fontWeight: 700,
|
||||||
|
formatter: params => formatCompactNumber(params.value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: urgentName,
|
name: urgentName,
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
barWidth: 28,
|
barWidth: 32,
|
||||||
data: urgentData,
|
data: urgentData,
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
borderRadius: [3, 3, 0, 0]
|
borderRadius: [3, 3, 0, 0]
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
color: '#ff3345',
|
||||||
|
fontSize: 19,
|
||||||
|
fontWeight: 800,
|
||||||
|
formatter: params => formatCompactNumber(params.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
const createRiskChartOption = () => {
|
const createRiskChartOption = () => createBarOption({
|
||||||
const data = riskCategories.map(category => {
|
categories: riskCategories,
|
||||||
const row = getSummaryRow('风险', category)
|
totalName: '任务',
|
||||||
return {
|
urgentName: '加急',
|
||||||
name: category,
|
totalData: riskCategories.map(category => getSummaryRow('及时处理', category).taskCount),
|
||||||
value: row.taskCount,
|
urgentData: riskCategories.map(category => getSummaryRow('及时处理', category).urgentQty)
|
||||||
quantity: row.quantity,
|
})
|
||||||
urgentQty: row.urgentQty
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
color: ['#ffb13b', '#e5602c', '#ff3040', '#8f6bff'],
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
backgroundColor: 'rgba(3, 16, 48, 0.94)',
|
|
||||||
borderColor: 'rgba(43, 216, 255, 0.55)',
|
|
||||||
textStyle: { color: '#f3f9ff' },
|
|
||||||
formatter: params => {
|
|
||||||
const item = params.data
|
|
||||||
return `${params.name}<br/>任务数:${formatAmount(item.value)}<br/>数量:${formatAmount(item.quantity, 2)}<br/>加急:${formatAmount(item.urgentQty, 2)}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
right: 24,
|
|
||||||
top: 46,
|
|
||||||
itemWidth: 14,
|
|
||||||
itemHeight: 10,
|
|
||||||
textStyle: { color: '#bde9ff', fontSize: 13 }
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '风险任务',
|
|
||||||
type: 'pie',
|
|
||||||
radius: ['44%', '70%'],
|
|
||||||
center: ['39%', '54%'],
|
|
||||||
roseType: 'radius',
|
|
||||||
avoidLabelOverlap: true,
|
|
||||||
label: {
|
|
||||||
color: '#f3f9ff',
|
|
||||||
fontSize: 13,
|
|
||||||
formatter: '{b}\n{c}条'
|
|
||||||
},
|
|
||||||
labelLine: {
|
|
||||||
lineStyle: { color: 'rgba(189, 233, 255, 0.68)' }
|
|
||||||
},
|
|
||||||
data
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const createDeliveryChartOption = () => {
|
const createDeliveryChartOption = () => {
|
||||||
const today = getSummaryRow('发货', '今日应发')
|
const categories = ['发货任务', '小于今日']
|
||||||
const open = getSummaryRow('发货', '销售交货未清')
|
return createBarOption({
|
||||||
const categories = ['今日应发', '今日加急', '销售未清', '销售加急']
|
categories,
|
||||||
const data = [today.quantity, today.urgentQty, open.quantity, open.urgentQty]
|
totalName: '任务',
|
||||||
const colors = ['#18d36f', '#ff3040', '#35c5ff', '#ff6a37']
|
urgentName: '加急',
|
||||||
|
totalData: categories.map(category => getSummaryRow('发货', category).taskCount),
|
||||||
return {
|
urgentData: categories.map(category => getSummaryRow('发货', category).urgentQty)
|
||||||
color: colors,
|
})
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: { type: 'shadow' },
|
|
||||||
backgroundColor: 'rgba(3, 16, 48, 0.94)',
|
|
||||||
borderColor: 'rgba(43, 216, 255, 0.55)',
|
|
||||||
textStyle: { color: '#f3f9ff' },
|
|
||||||
valueFormatter: value => formatAmount(value, 2)
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: 58,
|
|
||||||
right: 24,
|
|
||||||
top: 34,
|
|
||||||
bottom: 42
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: categories,
|
|
||||||
axisLine: { lineStyle: { color: 'rgba(141, 211, 255, 0.6)' } },
|
|
||||||
axisTick: { show: false },
|
|
||||||
axisLabel: { color: '#d8f3ff', fontSize: 14 }
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
splitLine: { lineStyle: { color: 'rgba(95, 172, 231, 0.18)' } },
|
|
||||||
axisLabel: {
|
|
||||||
color: '#9bdcff',
|
|
||||||
formatter: value => formatCompactNumber(value)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '数量',
|
|
||||||
type: 'bar',
|
|
||||||
barWidth: 32,
|
|
||||||
data,
|
|
||||||
itemStyle: {
|
|
||||||
borderRadius: [3, 3, 0, 0],
|
|
||||||
color: params => colors[params.dataIndex]
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: true,
|
|
||||||
position: 'top',
|
|
||||||
color: '#f3f9ff',
|
|
||||||
fontSize: 13,
|
|
||||||
formatter: params => formatCompactNumber(params.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSummaryRow = (section, category) => {
|
const getSummaryRow = (section, category) => {
|
||||||
@@ -675,6 +575,37 @@ const sumRows = (section, key) => {
|
|||||||
.reduce((total, row) => total + toNumber(row[key]), 0)
|
.reduce((total, row) => total + toNumber(row[key]), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getSectionTotal = section => ({
|
||||||
|
taskCount: sumRows(section, 'taskCount'),
|
||||||
|
quantity: sumRows(section, 'quantity'),
|
||||||
|
urgentQty: sumRows(section, 'urgentQty')
|
||||||
|
})
|
||||||
|
|
||||||
|
const getPickingSectionTotal = () => {
|
||||||
|
const pickingTotal = getSectionTotal('拣配')
|
||||||
|
const abnormalDelivery = getSummaryRow('发货', '异常出库')
|
||||||
|
return {
|
||||||
|
taskCount: pickingTotal.taskCount + abnormalDelivery.taskCount,
|
||||||
|
quantity: pickingTotal.quantity + abnormalDelivery.quantity,
|
||||||
|
urgentQty: pickingTotal.urgentQty + abnormalDelivery.urgentQty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDeliverySectionTotal = () => {
|
||||||
|
const deliveryTask = getSummaryRow('发货', '发货任务')
|
||||||
|
const todayDelivery = getSummaryRow('发货', '小于今日')
|
||||||
|
return {
|
||||||
|
taskCount: deliveryTask.taskCount ,
|
||||||
|
quantity: deliveryTask.quantity,
|
||||||
|
urgentQty: deliveryTask.urgentQty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatChartSummary = total => ({
|
||||||
|
value: formatAmount(total.taskCount),
|
||||||
|
urgent: formatAmount(total.urgentQty)
|
||||||
|
})
|
||||||
|
|
||||||
const pad = value => String(value).padStart(2, '0')
|
const pad = value => String(value).padStart(2, '0')
|
||||||
|
|
||||||
const formatDateTime = value => {
|
const formatDateTime = value => {
|
||||||
@@ -748,33 +679,33 @@ const normalizeText = value => {
|
|||||||
return String(value).trim()
|
return String(value).trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
const inboundColumns = [
|
const urgentInboundColumns = [
|
||||||
{ label: '单据日期', key: 'docDate', width: '78px' },
|
{ label: '类别', key: 'category', width: '13%' },
|
||||||
{ label: '订单号', key: 'orderNo', width: '66px' },
|
{ label: '单号', key: 'orderNo', width: '20%' },
|
||||||
{ label: '物料编码', key: 'itemCode', width: '150px' },
|
{ label: '物料名称', key: 'itemName', width: '52%' },
|
||||||
{ label: '物料名称', key: 'itemName', width: '178px' },
|
{ label: '加急', key: 'urgentQty', width: '15%' }
|
||||||
{ label: '未入库', key: 'quantity', width: '70px' },
|
|
||||||
{ label: '加急', key: 'urgentQty', width: '58px' }
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const outboundColumns = [
|
const pickingColumns = [
|
||||||
{ label: '拣配单', key: 'pickNo', width: '66px' },
|
{ label: '合同号', key: 'salesOrder', width: '20%' },
|
||||||
{ label: '日期', key: 'pickDate', width: '76px' },
|
{ label: '生产订单', key: 'productionOrder', width: '18%' },
|
||||||
{ label: '生产订单', key: 'productionOrder', width: '70px' },
|
{ label: '物料名称', key: 'itemName', width: '47%' },
|
||||||
{ label: '物料编码', key: 'itemCode', width: '148px' },
|
{ label: '齐套', key: 'completeSet', width: '15%' }
|
||||||
{ label: '物料描述', key: 'itemName', width: '178px' },
|
]
|
||||||
{ label: '计划', key: 'planQty', width: '58px' },
|
|
||||||
{ label: '加急', key: 'urgentQty', width: '58px' }
|
const urgentPickingColumns = [
|
||||||
|
{ label: '类别', key: 'category', width: '13%' },
|
||||||
|
{ label: '单号', key: 'orderNo', width: '20%' },
|
||||||
|
{ label: '物料名称', key: 'itemName', width: '52%' },
|
||||||
|
{ label: '状态', key: 'urgentStatus', width: '15%' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const deliveryColumns = [
|
const deliveryColumns = [
|
||||||
{ label: '发货日期', key: 'deliveryDate', width: '78px' },
|
{ label: '合同号', key: 'salesOrder', width: '24%' },
|
||||||
{ label: '客户', key: 'customer', width: '128px' },
|
{ label: '物料名称', key: 'itemName', width: '30%' },
|
||||||
{ label: '订单号', key: 'externalNo', width: '82px' },
|
{ label: '数量', key: 'deliveryQty', width: '12%' },
|
||||||
{ label: '物料编码', key: 'itemCode', width: '150px' },
|
{ label: '发货日期', key: 'deliveryDate', width: '25%' },
|
||||||
{ label: '物料名称', key: 'itemName', width: '154px' },
|
{ label: '测试', key: 'testQty', width: '10%' }
|
||||||
{ label: '未清', key: 'openQty', width: '58px' },
|
|
||||||
{ label: '加急', key: 'urgentQty', width: '58px' }
|
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -863,30 +794,22 @@ const deliveryColumns = [
|
|||||||
|
|
||||||
.dashboard-content {
|
.dashboard-content {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 128px 480px 1fr;
|
grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
height: calc(100% - 95px);
|
height: calc(100% - 95px);
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kpi-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(8, minmax(0, 1fr));
|
|
||||||
gap: 15px;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-grid {
|
.chart-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
grid-template-rows: repeat(2, minmax(0, 1fr));
|
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-grid {
|
.detail-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
@@ -926,76 +849,6 @@ const deliveryColumns = [
|
|||||||
box-shadow: inset 0 0 12px rgba(43, 216, 255, 0.12);
|
box-shadow: inset 0 0 12px rgba(43, 216, 255, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.kpi-card {
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: 28px minmax(0, 1fr) 24px;
|
|
||||||
align-items: center;
|
|
||||||
min-width: 0;
|
|
||||||
padding: 12px 14px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kpi-title {
|
|
||||||
overflow: hidden;
|
|
||||||
color: #95ddff;
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: 700;
|
|
||||||
line-height: 28px;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kpi-value {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
justify-content: center;
|
|
||||||
min-width: 0;
|
|
||||||
color: #ffffff;
|
|
||||||
font-weight: 900;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kpi-value span {
|
|
||||||
overflow: hidden;
|
|
||||||
max-width: 150px;
|
|
||||||
font-size: 42px;
|
|
||||||
text-align: center;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kpi-value small {
|
|
||||||
margin-left: 6px;
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 700;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kpi-sub {
|
|
||||||
overflow: hidden;
|
|
||||||
color: #c8eaff;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 22px;
|
|
||||||
text-align: center;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blue-card .kpi-value span {
|
|
||||||
color: #36c8ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.green-card .kpi-value span {
|
|
||||||
color: #18d36f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.red-card .kpi-value span {
|
|
||||||
color: #ff3040;
|
|
||||||
}
|
|
||||||
|
|
||||||
.orange-card .kpi-value span {
|
|
||||||
color: #ffb13b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-panel,
|
.chart-panel,
|
||||||
.table-panel {
|
.table-panel {
|
||||||
@@ -1003,12 +856,74 @@ const deliveryColumns = [
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-caption {
|
.chart-panel-head {
|
||||||
height: 38px;
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-height: 104px;
|
||||||
|
padding: 12px 22px 4px;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-title {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
color: #8cd3ff;
|
color: #8cd3ff;
|
||||||
font-size: 26px;
|
font-size: 36px;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-summary {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 210px;
|
||||||
|
color: #f3f9ff;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-summary-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: flex-end;
|
||||||
|
color: #36c8ff;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-summary-value span {
|
||||||
|
font-size: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-summary-value small {
|
||||||
|
margin-left: 8px;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-summary-sub {
|
||||||
|
margin-top: 6px;
|
||||||
|
color: #c8eaff;
|
||||||
|
font-size: 21px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
line-height: 38px;
|
line-height: 1.25;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-summary-sub span {
|
||||||
|
color: #ff3345;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-caption {
|
||||||
|
height: 44px;
|
||||||
|
color: #8cd3ff;
|
||||||
|
font-size: 34px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 44px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1025,7 +940,7 @@ const deliveryColumns = [
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0 8px 9px;
|
padding: 0 6px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
@@ -1046,16 +961,19 @@ td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
height: 36px;
|
height: 44px;
|
||||||
color: #bde9ff;
|
color: #bde9ff;
|
||||||
font-size: 14px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
background: rgba(12, 68, 119, 0.34);
|
background: rgba(12, 68, 119, 0.34);
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
height: 38px;
|
height: 44px;
|
||||||
font-size: 13px;
|
padding: 0 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 17px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.warning td {
|
.warning td {
|
||||||
@@ -1066,6 +984,6 @@ td {
|
|||||||
.empty-row td {
|
.empty-row td {
|
||||||
height: 228px;
|
height: 228px;
|
||||||
color: #89d4ff;
|
color: #89d4ff;
|
||||||
font-size: 18px;
|
font-size: 22px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -51,12 +51,14 @@
|
|||||||
:rowspan="row.childRowspan"
|
:rowspan="row.childRowspan"
|
||||||
class="subclass-cell"
|
class="subclass-cell"
|
||||||
>
|
>
|
||||||
|
|
||||||
<div class="subclass-content">
|
<div class="subclass-content">
|
||||||
|
<img class="subclass-image" :src="row.image" alt="" />
|
||||||
<div class="category-total subclass-total">
|
<div class="category-total subclass-total">
|
||||||
<span>{{ row.child }}</span>
|
<span>{{ row.child }}</span>
|
||||||
<strong>{{ row.childTotal }}</strong>
|
<strong>{{ row.childTotal }}</strong>
|
||||||
</div>
|
</div>
|
||||||
<img class="subclass-image" :src="row.image" alt="" />
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="metric-cell" :class="`metric-${row.metricKey}`">{{ row.metric }}</td>
|
<td class="metric-cell" :class="`metric-${row.metricKey}`">{{ row.metric }}</td>
|
||||||
@@ -144,7 +146,7 @@ const CreateData = inject('CreateData')
|
|||||||
const ExecDatabase = inject('ExecDatabase')
|
const ExecDatabase = inject('ExecDatabase')
|
||||||
|
|
||||||
const clientLogoUrl = './public/ClientLogo.png'
|
const clientLogoUrl = './public/ClientLogo.png'
|
||||||
const now = ref(new Date('2026-05-06 10:10:10'))
|
const now = ref(new Date())
|
||||||
const style = reactive({
|
const style = reactive({
|
||||||
width: 1920,
|
width: 1920,
|
||||||
height: 1080,
|
height: 1080,
|
||||||
@@ -181,7 +183,7 @@ const metricDefinitions = [
|
|||||||
|
|
||||||
const categoryGroups = [
|
const categoryGroups = [
|
||||||
{
|
{
|
||||||
parent: '阀类',
|
parent: '部件类',
|
||||||
children: [
|
children: [
|
||||||
{ key: 'valveMain', label: '阀', image: valveImage },
|
{ key: 'valveMain', label: '阀', image: valveImage },
|
||||||
{ key: 'valveOther', label: '其他', image: otherImage }
|
{ key: 'valveOther', label: '其他', image: otherImage }
|
||||||
@@ -282,8 +284,9 @@ const getScale = () => ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const startClock = () => {
|
const startClock = () => {
|
||||||
|
now.value = new Date()
|
||||||
clockTimer = window.setInterval(() => {
|
clockTimer = window.setInterval(() => {
|
||||||
now.value = new Date(now.value.getTime() + 1000)
|
now.value = new Date()
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user