diff --git a/dist.zip b/dist.zip index b503eef..3802846 100644 Binary files a/dist.zip and b/dist.zip differ diff --git a/doc/~$未完成计划.xlsx b/doc/~$未完成计划.xlsx new file mode 100644 index 0000000..840cc82 Binary files /dev/null and b/doc/~$未完成计划.xlsx differ diff --git a/doc/未完成计划.xlsx b/doc/未完成计划.xlsx new file mode 100644 index 0000000..22d92e4 Binary files /dev/null and b/doc/未完成计划.xlsx differ diff --git a/gptlog-process/gpdlog.md b/gptlog-process/gpdlog.md index 7d903c7..4ab77db 100644 --- a/gptlog-process/gpdlog.md +++ b/gptlog-process/gpdlog.md @@ -391,3 +391,237 @@ ### 结论 所有当前修改已提交并推送到远程 `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`,包括本次追加的中文执行日志。 diff --git a/src/utils/request.js b/src/utils/request.js index b58efb7..e832d30 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -8,7 +8,7 @@ const request_config = window.g.API_WEB_URL + `/submit/MESCommonBase.ashx` export const name = name_config const service = axios.create({ baseURL: request_config, - timeout: 1000 * 5 // 请求超时时间 + timeout: 1000 * 15 // 请求超时时间 }) // && config.data.name !== '菜单系统模块_通知信息_查询数据' && config.data.name !== '菜单系统模块_首页信息_查询数据1' && config.data.name !== '菜单系统模块_首页信息_查询数据2' diff --git a/src/views/TestTaskDashboard.vue b/src/views/TestTaskDashboard.vue index b54a6c0..4c7e004 100644 --- a/src/views/TestTaskDashboard.vue +++ b/src/views/TestTaskDashboard.vue @@ -145,7 +145,7 @@ const CreateData = inject('CreateData') const ExecDatabase = inject('ExecDatabase') defineOptions({ name: 'AssemblyCenterTaskDashboard' }) -const now = ref(new Date('2026-05-06 10:10:10')) +const now = ref(new Date()) let timer = null let resizeHandler = null let scrollTimers = [] @@ -203,7 +203,7 @@ const VISIBLE_ROWS = { const testSummaryGroups = [ { key: 'valve', - label: '阀类', + label: '部件类', products: [ { key: 'valveMain', label: '阀', image: valveImage }, { key: 'valveOther', label: '其他', image: otherImage } @@ -329,7 +329,7 @@ const searchTestAssemblyTaskData = () => { ['物料名称', ''], ['物料编码', ''] ] - queryDashboardData('质量管理_测试装配任务_查询', applyTestAssemblyTaskData, param) + queryDashboardData('质检测试看板_测试装配任务_查询', applyTestAssemblyTaskData, param) } const searchTestAssemblyTaskListData = () => { queryDashboardData('质量管理_测试装配任务_查询2', applyTaskData) @@ -372,7 +372,7 @@ const searchStagnationData = () => { queryDashboardData('质量管理_及时检验报表_查询', applyStagnationData, param) } const searchDeliveryData = () => { - queryDashboardData('装配中心任务看板_质检发货状态查询', applyDeliveryData) + queryDashboardData('质检测试看板_质检发货状态查询', applyDeliveryData) } const applyTestAssemblyTaskData = rows => { const sortedRows = sortTestAssemblyTaskRows(rows) @@ -431,7 +431,7 @@ const applyDoneTaskData = 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() || '', salesOrder: item.销售订单 || item.合同号 || '', materialName: item.物料名称 || item.物料描述 || item.零件名称 || '', @@ -440,6 +440,8 @@ const applyTaskData = rows => { urgentQty: getNumber(item.加急总数 || item.加急数量), assignQty: getNumber(item.计划数量 || item.计划生产数 || item.分配数), completeQty: getNumber(item.完成数量), + inboundQty: getNumber(item.入库数量), + passQty: getNumber(item.合格数), operator: item.操作人 || '' })) } @@ -503,9 +505,9 @@ const normalizeText = value => { 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('系统') ? '系统类' : '阀类') @@ -573,7 +575,7 @@ const getPassRate = item => { 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 svgIcon = (from, to, body) => svgData( ` @@ -621,7 +623,9 @@ const taskColumns = [ { label: '加急数', key: 'urgentQty', width: '62px' }, { label: '计划数', key: 'assignQty', 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 = [ @@ -1115,8 +1119,8 @@ th { } .summary-product-image { - width: 82px; - height: 62px; + width: 130px; + height: 75px; object-fit: contain; } diff --git a/src/views/WarehouseDashboard.vue b/src/views/WarehouseDashboard.vue index 6353189..ca60806 100644 --- a/src/views/WarehouseDashboard.vue +++ b/src/views/WarehouseDashboard.vue @@ -11,37 +11,62 @@

仓库任务大屏

{{ currentTime }}
-
数据刷新 {{ refreshTimeText }}
+
-
-
-
{{ item.title }}
-
- {{ item.value }} - {{ item.unit }} -
-
{{ item.subText }}
-
-
-
-
入库任务结构
+
+
入库任务
+
+
+ {{ chartSummaries.inbound.value }} + +
+
加急 {{ chartSummaries.inbound.urgent }}
+
+
-
拣配任务结构
+
+
拣配任务
+
+
+ {{ chartSummaries.picking.value }} + +
+
加急 {{ chartSummaries.picking.urgent }}
+
+
-
超期风险分布
+
+
及时处理
+
+
+ {{ chartSummaries.timely.value }} + +
+
加急 {{ chartSummaries.timely.urgent }}
+
+
-
今日发货保障
+
+
发货任务
+
+
+ {{ chartSummaries.delivery.value }} + +
+
加急 {{ chartSummaries.delivery.urgent }}
+
+
@@ -112,125 +137,60 @@ const deliveryChartRef = ref(null) const summaryRows = ref([]) const inboundOverdueRows = ref([]) const outboundOverdueRows = ref([]) +const urgentPickingRows = ref([]) const todayDeliveryRows = ref([]) const inboundOffset = ref(0) const outboundOffset = ref(0) +const urgentPickingOffset = ref(0) const deliveryOffset = ref(0) const VISIBLE_ROWS = { - inbound: 6, - outbound: 6, - delivery: 6 + inbound: 7, + outbound: 7, + urgentPicking: 7, + delivery: 7 } -const inboundCategories = ['装配件', '机加件', '原材料', '外购件'] -const pickingCategories = ['装配件', '机加件'] -const riskCategories = ['超2天未入库', '超2天未上架', '超10天未出库', '汇报未清'] +const inboundCategories = ['原料', '零件', '机加', '装配'] +const pickingCategories = ['机加', '装配'] +const riskCategories = ['上架', '入库', '汇报'] const currentTime = computed(() => formatDateTime(now.value)) const refreshTimeText = computed(() => lastRefreshTime.value || '--:--:--') - -const summaryCards = computed(() => { - const inboundTaskQty = sumRows('入库', 'quantity') - const inboundUrgentQty = sumRows('入库', 'urgentQty') - const inboundItemCount = sumRows('入库', 'taskCount') - 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 chartSummaries = computed(() => ({ + inbound: formatChartSummary(getSectionTotal('入库')), + picking: formatChartSummary(getPickingSectionTotal()), + timely: formatChartSummary(getSectionTotal('及时处理')), + delivery: formatChartSummary(getDeliverySectionTotal()) +})) const inboundDisplayRows = computed(() => makeDisplayRows(inboundOverdueRows.value, inboundOffset.value, VISIBLE_ROWS.inbound)) 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 detailTables = computed(() => [ { key: 'inbound', - title: '超2天未入库明细', - columns: inboundColumns, + title: '加急入库列表', + columns: urgentInboundColumns, rows: inboundDisplayRows.value }, { key: 'outbound', - title: '超10天未出库明细', - columns: outboundColumns, + title: '拣配任务列表', + columns: pickingColumns, rows: outboundDisplayRows.value }, + { + key: 'urgentPicking', + title: '加急拣配列表', + columns: urgentPickingColumns, + rows: urgentPickingDisplayRows.value + }, { key: 'delivery', - title: '今日应发明细', + title: '发货任务列表', columns: deliveryColumns, rows: deliveryDisplayRows.value } @@ -333,9 +293,10 @@ const disposeCharts = () => { const searchDashboardData = () => { const tasks = [ queryDashboardData('仓库大屏_汇总查询', applySummaryData), - queryDashboardData('仓库大屏_入库超期明细', applyInboundOverdueData), - queryDashboardData('仓库大屏_出库超期明细', applyOutboundOverdueData), - queryDashboardData('仓库大屏_今日应发明细', applyTodayDeliveryData) + queryDashboardData('仓库大屏_加急入库列表', applyInboundOverdueData), + queryDashboardData('仓库大屏_拣配任务列表', applyOutboundOverdueData), + queryDashboardData('仓库大屏_加急拣配列表', applyUrgentPickingData), + queryDashboardData('装配中心任务看板_发货状态查询', applyTodayDeliveryData) ] Promise.all(tasks).finally(() => { @@ -378,6 +339,10 @@ const getResponseRows = response => { } const applySummaryData = rows => { + if (!Array.isArray(rows) || rows.length === 0) { + return + } + summaryRows.value = rows.map(row => ({ section: normalizeText(row.环节), category: normalizeText(row.分类), @@ -392,11 +357,9 @@ const applyInboundOverdueData = rows => { inboundOffset.value = 0 inboundOverdueRows.value = rows.map((row, index) => ({ _idx: index + 1, - docDate: formatDateValue(row.单据日期), - orderNo: normalizeText(row.订单号), - itemCode: normalizeText(row.物料编码), + category: normalizeText(row.类别), + orderNo: normalizeText(row.单号), itemName: normalizeText(row.物料名称), - quantity: formatAmount(row.未入库数量, 2), urgentQty: formatAmount(row.加急数量, 2), urgentValue: toNumber(row.加急数量) })) @@ -406,14 +369,24 @@ const applyOutboundOverdueData = rows => { outboundOffset.value = 0 outboundOverdueRows.value = rows.map((row, index) => ({ _idx: index + 1, - pickNo: normalizeText(row.拣配清单号), - pickDate: formatDateValue(row.拣配日期), - productionOrder: normalizeText(row.生产订单号), - itemCode: normalizeText(row.物料编码), - itemName: normalizeText(row.物料描述), - planQty: formatAmount(row.计划数量, 2), - urgentQty: formatAmount(row.加急数量, 2), - urgentValue: toNumber(row.加急数量) + salesOrder: normalizeText(row.合同号), + productionOrder: normalizeText(row.生产订单), + itemName: normalizeText(row.物料名称), + completeSet: normalizeText(row.齐套), + status: normalizeText(row.状态), + urgentValue: 0 + })) +} + +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 todayDeliveryRows.value = rows.map((row, index) => ({ _idx: index + 1, - deliveryDate: formatDateValue(row.发货日期), - customer: normalizeText(row.客户), - externalNo: normalizeText(row.外部单号 || row.订单号), - itemCode: normalizeText(row.物料编码), - itemName: normalizeText(row.物料名称), - openQty: formatAmount(row.未清数量, 2), - urgentQty: formatAmount(row.加急数量, 2), - urgentValue: toNumber(row.加急数量) + salesOrder: normalizeText(row.合同号), + itemName: normalizeText(row.物料描述 || row.物料名称), + deliveryQty: formatAmount(row.交货数量 || row.计划数量, 2), + deliveryDate: formatDateValue(row.要求发货日期 || row.发货日期), + testQty: formatAmount(row.检验数量, 2), + urgentValue: toNumber(row.加急总数 || row.加急数量) })) } const startAllScroll = () => { startScrollWhenOverflow(inboundOverdueRows, inboundOffset, VISIBLE_ROWS.inbound) startScrollWhenOverflow(outboundOverdueRows, outboundOffset, VISIBLE_ROWS.outbound) + startScrollWhenOverflow(urgentPickingRows, urgentPickingOffset, VISIBLE_ROWS.urgentPicking) startScrollWhenOverflow(todayDeliveryRows, deliveryOffset, VISIBLE_ROWS.delivery) } @@ -471,18 +443,24 @@ const makeDisplayRows = (rows, offset, visibleCount) => { const createInboundChartOption = () => createBarOption({ categories: inboundCategories, - totalName: '未入库任务', - urgentName: '加急任务', - totalData: inboundCategories.map(category => getSummaryRow('入库', category).quantity), + totalName: '任务', + urgentName: '加急', + totalData: inboundCategories.map(category => getSummaryRow('入库', category).taskCount), urgentData: inboundCategories.map(category => getSummaryRow('入库', category).urgentQty) }) const createPickingChartOption = () => createBarOption({ - categories: pickingCategories, - totalName: '未清拣配', - urgentName: '加急拣配', - totalData: pickingCategories.map(category => getSummaryRow('拣配', category).quantity), - urgentData: pickingCategories.map(category => getSummaryRow('拣配', category).urgentQty) + categories: [...pickingCategories, '异常出库'], + totalName: '任务', + urgentName: '加急', + totalData: [ + ...pickingCategories.map(category => getSummaryRow('拣配', category).taskCount), + getSummaryRow('发货', '异常出库').taskCount + ], + urgentData: [ + ...pickingCategories.map(category => getSummaryRow('拣配', category).urgentQty), + getSummaryRow('发货', '异常出库').urgentQty + ] }) const createBarOption = ({ categories, totalName, urgentName, totalData, urgentData }) => ({ @@ -492,170 +470,92 @@ const createBarOption = ({ categories, totalName, urgentName, totalData, urgentD axisPointer: { type: 'shadow' }, backgroundColor: 'rgba(3, 16, 48, 0.94)', borderColor: 'rgba(43, 216, 255, 0.55)', - textStyle: { color: '#f3f9ff' }, + textStyle: { color: '#f3f9ff', fontSize: 19 }, valueFormatter: value => formatAmount(value, 2) }, legend: { top: 0, right: 18, - itemWidth: 14, - itemHeight: 10, - textStyle: { color: '#bde9ff', fontSize: 13 } + itemWidth: 18, + itemHeight: 12, + textStyle: { color: '#bde9ff', fontSize: 19 } }, grid: { - left: 58, - right: 24, - top: 48, - bottom: 38 + left: 18, + right: 18, + top: 46, + bottom: 36, + containLabel: true }, xAxis: { type: 'category', data: categories, axisLine: { lineStyle: { color: 'rgba(141, 211, 255, 0.6)' } }, axisTick: { show: false }, - axisLabel: { color: '#d8f3ff', fontSize: 15 } + axisLabel: { color: '#d8f3ff', fontSize: 21, fontWeight: 700 } }, yAxis: { type: 'value', - splitLine: { lineStyle: { color: 'rgba(95, 172, 231, 0.18)' } }, - axisLabel: { - color: '#9bdcff', - formatter: value => formatCompactNumber(value) - } + axisLine: { show: false }, + axisTick: { show: false }, + axisLabel: { show: false }, + splitLine: { show: false } }, series: [ { name: totalName, type: 'bar', - barWidth: 28, + barWidth: 32, data: totalData, itemStyle: { borderRadius: [3, 3, 0, 0] + }, + label: { + show: true, + position: 'top', + color: '#f3f9ff', + fontSize: 19, + fontWeight: 700, + formatter: params => formatCompactNumber(params.value) } }, { name: urgentName, type: 'bar', - barWidth: 28, + barWidth: 32, data: urgentData, itemStyle: { borderRadius: [3, 3, 0, 0] + }, + label: { + show: true, + position: 'top', + color: '#ff3345', + fontSize: 19, + fontWeight: 800, + formatter: params => formatCompactNumber(params.value) } } ] }) -const createRiskChartOption = () => { - const data = riskCategories.map(category => { - const row = getSummaryRow('风险', category) - return { - name: category, - value: row.taskCount, - 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}
任务数:${formatAmount(item.value)}
数量:${formatAmount(item.quantity, 2)}
加急:${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 createRiskChartOption = () => createBarOption({ + categories: riskCategories, + totalName: '任务', + urgentName: '加急', + totalData: riskCategories.map(category => getSummaryRow('及时处理', category).taskCount), + urgentData: riskCategories.map(category => getSummaryRow('及时处理', category).urgentQty) +}) const createDeliveryChartOption = () => { - const today = getSummaryRow('发货', '今日应发') - const open = getSummaryRow('发货', '销售交货未清') - const categories = ['今日应发', '今日加急', '销售未清', '销售加急'] - const data = [today.quantity, today.urgentQty, open.quantity, open.urgentQty] - const colors = ['#18d36f', '#ff3040', '#35c5ff', '#ff6a37'] - - return { - 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 categories = ['发货任务', '小于今日'] + return createBarOption({ + categories, + totalName: '任务', + urgentName: '加急', + totalData: categories.map(category => getSummaryRow('发货', category).taskCount), + urgentData: categories.map(category => getSummaryRow('发货', category).urgentQty) + }) } const getSummaryRow = (section, category) => { @@ -675,6 +575,37 @@ const sumRows = (section, key) => { .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 formatDateTime = value => { @@ -748,33 +679,33 @@ const normalizeText = value => { return String(value).trim() } -const inboundColumns = [ - { label: '单据日期', key: 'docDate', width: '78px' }, - { label: '订单号', key: 'orderNo', width: '66px' }, - { label: '物料编码', key: 'itemCode', width: '150px' }, - { label: '物料名称', key: 'itemName', width: '178px' }, - { label: '未入库', key: 'quantity', width: '70px' }, - { label: '加急', key: 'urgentQty', width: '58px' } +const urgentInboundColumns = [ + { label: '类别', key: 'category', width: '13%' }, + { label: '单号', key: 'orderNo', width: '20%' }, + { label: '物料名称', key: 'itemName', width: '52%' }, + { label: '加急', key: 'urgentQty', width: '15%' } ] -const outboundColumns = [ - { label: '拣配单', key: 'pickNo', width: '66px' }, - { label: '日期', key: 'pickDate', width: '76px' }, - { label: '生产订单', key: 'productionOrder', width: '70px' }, - { label: '物料编码', key: 'itemCode', width: '148px' }, - { label: '物料描述', key: 'itemName', width: '178px' }, - { label: '计划', key: 'planQty', width: '58px' }, - { label: '加急', key: 'urgentQty', width: '58px' } +const pickingColumns = [ + { label: '合同号', key: 'salesOrder', width: '20%' }, + { label: '生产订单', key: 'productionOrder', width: '18%' }, + { label: '物料名称', key: 'itemName', width: '47%' }, + { label: '齐套', key: 'completeSet', width: '15%' } +] + +const urgentPickingColumns = [ + { label: '类别', key: 'category', width: '13%' }, + { label: '单号', key: 'orderNo', width: '20%' }, + { label: '物料名称', key: 'itemName', width: '52%' }, + { label: '状态', key: 'urgentStatus', width: '15%' } ] const deliveryColumns = [ - { label: '发货日期', key: 'deliveryDate', width: '78px' }, - { label: '客户', key: 'customer', width: '128px' }, - { label: '订单号', key: 'externalNo', width: '82px' }, - { label: '物料编码', key: 'itemCode', width: '150px' }, - { label: '物料名称', key: 'itemName', width: '154px' }, - { label: '未清', key: 'openQty', width: '58px' }, - { label: '加急', key: 'urgentQty', width: '58px' } + { label: '合同号', key: 'salesOrder', width: '24%' }, + { label: '物料名称', key: 'itemName', width: '30%' }, + { label: '数量', key: 'deliveryQty', width: '12%' }, + { label: '发货日期', key: 'deliveryDate', width: '25%' }, + { label: '测试', key: 'testQty', width: '10%' } ] @@ -863,30 +794,22 @@ const deliveryColumns = [ .dashboard-content { display: grid; - grid-template-rows: 128px 480px 1fr; + grid-template-rows: minmax(0, 1fr) minmax(0, 1fr); gap: 15px; height: calc(100% - 95px); padding-top: 10px; } -.kpi-row { - display: grid; - grid-template-columns: repeat(8, minmax(0, 1fr)); - gap: 15px; - min-height: 0; -} - .chart-grid { display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - grid-template-rows: repeat(2, minmax(0, 1fr)); + grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 15px; min-height: 0; } .detail-grid { display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 15px; min-height: 0; } @@ -926,76 +849,6 @@ const deliveryColumns = [ 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, .table-panel { @@ -1003,12 +856,74 @@ const deliveryColumns = [ flex-direction: column; } -.panel-caption { - height: 38px; +.chart-panel-head { + 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; - 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; - 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; } @@ -1025,7 +940,7 @@ const deliveryColumns = [ flex: 1; min-height: 0; overflow: hidden; - padding: 0 8px 9px; + padding: 0 6px 8px; } table { @@ -1046,16 +961,19 @@ td { } th { - height: 36px; + height: 44px; color: #bde9ff; - font-size: 14px; + font-size: 18px; font-weight: 600; background: rgba(12, 68, 119, 0.34); } td { - height: 38px; - font-size: 13px; + height: 44px; + padding: 0 4px; + overflow: hidden; + font-size: 17px; + text-overflow: ellipsis; } .warning td { @@ -1066,6 +984,6 @@ td { .empty-row td { height: 228px; color: #89d4ff; - font-size: 18px; + font-size: 22px; } diff --git a/src/views/index.vue b/src/views/index.vue index 0ac8562..9524a0b 100644 --- a/src/views/index.vue +++ b/src/views/index.vue @@ -51,12 +51,14 @@ :rowspan="row.childRowspan" class="subclass-cell" > +
+
{{ row.child }} {{ row.childTotal }}
- +
{{ row.metric }} @@ -144,7 +146,7 @@ const CreateData = inject('CreateData') const ExecDatabase = inject('ExecDatabase') const clientLogoUrl = './public/ClientLogo.png' -const now = ref(new Date('2026-05-06 10:10:10')) +const now = ref(new Date()) const style = reactive({ width: 1920, height: 1080, @@ -181,7 +183,7 @@ const metricDefinitions = [ const categoryGroups = [ { - parent: '阀类', + parent: '部件类', children: [ { key: 'valveMain', label: '阀', image: valveImage }, { key: 'valveOther', label: '其他', image: otherImage } @@ -282,8 +284,9 @@ const getScale = () => ({ }) const startClock = () => { + now.value = new Date() clockTimer = window.setInterval(() => { - now.value = new Date(now.value.getTime() + 1000) + now.value = new Date() }, 1000) }