diff --git a/db_backups/add_design_report_task_hours_report_20260715.sql b/db_backups/add_design_report_task_hours_report_20260715.sql
new file mode 100644
index 0000000..a546d3a
--- /dev/null
+++ b/db_backups/add_design_report_task_hours_report_20260715.sql
@@ -0,0 +1,135 @@
+USE [YL_MESDB];
+GO
+
+SET ANSI_NULLS ON;
+GO
+SET QUOTED_IDENTIFIER ON;
+GO
+
+CREATE OR ALTER PROCEDURE [dbo].[设计报工_工时报表_任务工时_查询]
+ @开始日期 nvarchar(30) = N'',
+ @结束日期 nvarchar(30) = N'',
+ @操作人 nvarchar(100) = N'',
+ @项目号 nvarchar(100) = N'',
+ @物料编码 nvarchar(100) = N'',
+ @类别 nvarchar(100) = N'',
+ @DID int = NULL
+AS
+BEGIN
+ SET NOCOUNT ON;
+
+ DECLARE @开始 datetime = TRY_CONVERT(datetime, NULLIF(@开始日期, N''));
+ DECLARE @结束 datetime = TRY_CONVERT(datetime, NULLIF(@结束日期, N''));
+
+ ;WITH base AS
+ (
+ SELECT
+ r.[RID],
+ r.[DID],
+ ISNULL(r.[操作人], N'') AS [操作人],
+ t.[项目号],
+ t.[物料编码],
+ t.[物料名称],
+ t.[图号],
+ t.[类别],
+ t.[任务描述],
+ r.[开始时间],
+ r.[结束时间],
+ ISNULL(r.[工时秒数], 0) AS [工时秒数],
+ r.[已校验],
+ r.[进度说明],
+ r.[备注]
+ FROM [dbo].[MES_设计报工_记录] AS r
+ INNER JOIN [dbo].[MES_设计报工_任务] AS t ON r.[DID] = t.[DID]
+ WHERE
+ r.[开始时间] IS NOT NULL
+ AND r.[结束时间] IS NOT NULL
+ AND (@开始 IS NULL OR r.[开始时间] >= @开始)
+ AND (@结束 IS NULL OR r.[开始时间] < DATEADD(day, 1, @结束))
+ AND (ISNULL(@操作人, N'') = N'' OR r.[操作人] LIKE N'%' + @操作人 + N'%')
+ AND (ISNULL(@项目号, N'') = N'' OR t.[项目号] LIKE N'%' + @项目号 + N'%')
+ AND (ISNULL(@物料编码, N'') = N'' OR t.[物料编码] LIKE N'%' + @物料编码 + N'%')
+ AND (ISNULL(@类别, N'') = N'' OR t.[类别] LIKE N'%' + @类别 + N'%')
+ AND (@DID IS NULL OR @DID = 0 OR r.[DID] = @DID)
+ ),
+ result AS
+ (
+ SELECT
+ 1 AS [Level],
+ N't-' + CAST([DID] AS nvarchar(20)) AS [id],
+ CAST(N'' AS nvarchar(120)) AS [parentId],
+ CAST(N'' AS nvarchar(100)) AS [操作人],
+ CAST(N'' AS nvarchar(20)) AS [工作日期],
+ CAST(NULL AS int) AS [RID],
+ [DID],
+ ISNULL(MAX([项目号]), N'') AS [项目号],
+ ISNULL(MAX([物料编码]), N'') AS [物料编码],
+ ISNULL(MAX([物料名称]), N'') AS [物料名称],
+ ISNULL(MAX([图号]), N'') AS [图号],
+ ISNULL(MAX([类别]), N'') AS [类别],
+ ISNULL(MAX([任务描述]), N'') AS [任务描述],
+ CONVERT(varchar(19), MIN([开始时间]), 120) AS [开始时间],
+ CONVERT(varchar(19), MAX([结束时间]), 120) AS [结束时间],
+ COUNT(1) AS [报工次数],
+ CAST(SUM([工时秒数]) / 3600.0 AS decimal(18, 2)) AS [工时小时],
+ CASE
+ WHEN SUM(CONVERT(int, [已校验])) = COUNT(1) THEN N'已校验'
+ WHEN SUM(CONVERT(int, [已校验])) = 0 THEN N'未校验'
+ ELSE N'部分校验'
+ END AS [校验状态],
+ ISNULL(STRING_AGG(
+ CASE WHEN NULLIF(LTRIM(RTRIM([进度说明])), N'') IS NOT NULL
+ THEN CONVERT(nvarchar(max), CONVERT(nvarchar(19), [结束时间], 120) + NCHAR(13) + NCHAR(10) + [进度说明]) END,
+ NCHAR(13) + NCHAR(10) + NCHAR(13) + NCHAR(10)
+ ) WITHIN GROUP (ORDER BY [开始时间], [RID]), N'') AS [进度说明],
+ ISNULL(STRING_AGG(
+ CASE WHEN NULLIF(LTRIM(RTRIM([备注])), N'') IS NOT NULL
+ THEN CONVERT(nvarchar(max), [备注]) END,
+ NCHAR(13) + NCHAR(10)
+ ) WITHIN GROUP (ORDER BY [开始时间], [RID]), N'') AS [备注]
+ FROM base
+ GROUP BY [DID]
+
+ UNION ALL
+
+ SELECT
+ 2 AS [Level],
+ N't-' + CAST([DID] AS nvarchar(20)) + N'-o-' + [操作人] AS [id],
+ N't-' + CAST([DID] AS nvarchar(20)) AS [parentId],
+ [操作人],
+ CAST(N'' AS nvarchar(20)) AS [工作日期],
+ CAST(NULL AS int) AS [RID],
+ [DID],
+ CAST(N'' AS nvarchar(100)) AS [项目号],
+ CAST(N'' AS nvarchar(100)) AS [物料编码],
+ CAST(N'' AS nvarchar(200)) AS [物料名称],
+ CAST(N'' AS nvarchar(100)) AS [图号],
+ CAST(N'' AS nvarchar(100)) AS [类别],
+ CAST(N'' AS nvarchar(500)) AS [任务描述],
+ CONVERT(varchar(19), MIN([开始时间]), 120) AS [开始时间],
+ CONVERT(varchar(19), MAX([结束时间]), 120) AS [结束时间],
+ COUNT(1) AS [报工次数],
+ CAST(SUM([工时秒数]) / 3600.0 AS decimal(18, 2)) AS [工时小时],
+ CASE
+ WHEN SUM(CONVERT(int, [已校验])) = COUNT(1) THEN N'已校验'
+ WHEN SUM(CONVERT(int, [已校验])) = 0 THEN N'未校验'
+ ELSE N'部分校验'
+ END AS [校验状态],
+ ISNULL(STRING_AGG(
+ CASE WHEN NULLIF(LTRIM(RTRIM([进度说明])), N'') IS NOT NULL
+ THEN CONVERT(nvarchar(max), CONVERT(nvarchar(19), [结束时间], 120) + NCHAR(13) + NCHAR(10) + [进度说明]) END,
+ NCHAR(13) + NCHAR(10) + NCHAR(13) + NCHAR(10)
+ ) WITHIN GROUP (ORDER BY [开始时间], [RID]), N'') AS [进度说明],
+ ISNULL(STRING_AGG(
+ CASE WHEN NULLIF(LTRIM(RTRIM([备注])), N'') IS NOT NULL
+ THEN CONVERT(nvarchar(max), [备注]) END,
+ NCHAR(13) + NCHAR(10)
+ ) WITHIN GROUP (ORDER BY [开始时间], [RID]), N'') AS [备注]
+ FROM base
+ GROUP BY [DID], [操作人]
+ )
+ SELECT *
+ FROM result
+ ORDER BY [DID] DESC, [Level], [操作人];
+END
+GO
diff --git a/gptlog-process/gpdlog.md b/gptlog-process/gpdlog.md
index 726a1aa..baf0a58 100644
--- a/gptlog-process/gpdlog.md
+++ b/gptlog-process/gpdlog.md
@@ -3436,6 +3436,68 @@ pm run build:通过,仅有既有警告。
- 最终生产构建通过。
- 功能提交已成功推送至远程。
+## 2026-07-15 设计工时报表增加任务工时页签
+
+### 用户提问
+- 用户指定修改 `src/views/ProductionManagement/DesignReportTask/Report/index.vue`,说明当前页面为按日期和人员计算的工时报表。
+- 要求在同一页面新增一个按 DID 计算的工时报表,顶部页签切换方式参考 `ProductionManagement/Timesheet/index`。
+- 原报表命名为“作业者工时”,新增报表命名为“任务工时”。
+
+### 执行过程
+1. 检查用户指定的 `Report/index.vue`、设计报工模块全部页面、菜单脚本、项目文档及参考页面 `ProductionManagement/Timesheet/index.vue`。
+2. 确认用户描述的按日期和人员计算报表实际位于 `src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue`,菜单名为“设计工时报表”;指定的 `Report/index.vue` 实际是设计报工开始、结束、完成操作页。
+3. 根据菜单路由和业务意图,选择修改正确的 `HoursReport/index.vue`,避免把报工操作页面误改成工时报表。
+4. 阅读参考 Timesheet 页面“作业者工时”和“任务工时”页签、查询切换、树形数据组装及导出逻辑。
+5. 检查现有设计作业者工时查询过程 `设计报工_工时报表_作业者工时_查询`,确认现有结构为操作人→工作日期→报工明细三级树。
+6. 查询目标数据库现有设计报工记录和现有报表返回结果,确认筛选参数、字段类型、工时秒数、校验状态、进度说明及备注的数据口径。
+7. 修改 `HoursReport/index.vue`:
+ - 增加 Element UI 顶部页签,名称为“作业者工时”和“任务工时”。
+ - 默认显示“作业者工时”,保留原有人员→日期→明细三级树和全部字段。
+ - 新增“任务工时”表格,使用 DID→操作人两级树。
+ - DID 根节点显示任务描述、项目号、物料、图号、类别、报工次数、总工时、最早开始、最晚结束和综合校验状态。
+ - 操作人子节点显示该人员在当前 DID 上的报工次数、工时、起止时间、校验状态、进度说明和备注。
+ - 两个页签共用开始日期、结束日期、操作人、项目号、物料编码、类别和 DID 筛选条件。
+ - 点击页签时查询对应报表过程。
+ - 底部总工时根据当前页签根节点动态计算。
+ - 导出按钮根据当前页签导出对应树形数据,工作表和文件名分别使用“作业者工时”或“任务工时”。
+8. 新增数据库脚本 `db_backups/add_design_report_task_hours_report_20260715.sql`,创建过程 `设计报工_工时报表_任务工时_查询`。
+9. 新过程沿用原作业者工时的全部筛选条件,只统计已正常结束的设计报工记录,并按 DID 汇总根节点、按 DID 和操作人汇总子节点。
+10. 新过程对每个汇总层计算报工次数、工时小时、最早开始时间、最晚结束时间;校验状态区分“已校验”“未校验”“部分校验”;进度说明按结束时间和内容聚合,备注同步聚合。
+11. 执行前端单文件 ESLint 和目标差异空白检查,均通过;仅输出项目依赖的 Browserslist 和 Baseline 数据过期提示。
+12. 在独立 LocalDB 测试实例中创建最小任务和报工表,执行新过程脚本并插入两个人员共同报工同一 DID 的测试数据。
+13. 隔离验证结果:DID 10 根节点汇总 2 次、1.50 小时、状态“部分校验”;张三子节点 1 次、1.00 小时、已校验;李四子节点 1 次、0.50 小时、未校验;任务及人员的进度说明和备注聚合正确。
+14. 删除 LocalDB 测试夹具、测试实例及 MDF/LDF 文件,确认没有临时测试资源残留。
+15. 执行 `npm run build`,生产构建成功;仅有项目原有的大资源体积和浏览器兼容数据过期警告,未生成受版本控制的 `dist` 变更。
+16. 使用用户此前提供的数据库凭据,将 `add_design_report_task_hours_report_20260715.sql` 发布到 `192.168.2.92 / YL_MESDB`;日志不记录明文密码。
+17. 在目标库创建新过程成功,修改时间为 `2026-07-15 18:14:19`。
+18. 使用临时表只读接收目标库作业者工时和任务工时两个过程的完整返回结果,交叉核对真实数据:
+ - 两个报表统计的已结束报工次数均为 30。
+ - 任务工时根节点与人员子节点结构正确。
+ - 多人任务 DID 1 汇总为 3 次、0.02 小时;子节点为超级管理员 2 次、张一帆 1 次。
+ - 两种报表按不同维度分别先保留两位小数,跨全部分组求和存在 0.01 至 0.02 小时累计舍入差,属于分组舍入口径差异,不影响单个 DID 汇总。
+19. 最终再次执行 HoursReport 页面 ESLint、目标文件 `git diff --check`、数据库对象检查和本地服务检查,均通过;`https://localhost:1997/` 返回 HTTP 200。
+
+### 修改文件
+- `src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue`
+- `db_backups/add_design_report_task_hours_report_20260715.sql`
+- `gptlog-process/gpdlog.md`
+
+### 结论
+- 设计工时报表现在同一页面提供“作业者工时”和“任务工时”两个顶部页签。
+- 原作业者工时功能、筛选条件和三级树结构保持不变。
+- 新任务工时按照 DID 汇总,并可展开查看每位操作人的工时贡献。
+- 查询、总工时和 Excel 导出都会随当前页签切换。
+- 新任务工时查询过程已经发布到目标数据库并通过真实数据验证。
+
+### 验证结果
+- HoursReport 单文件 ESLint 通过。
+- 目标文件 `git diff --check` 通过。
+- 隔离 LocalDB 的 DID 及人员汇总验证通过。
+- `npm run build` 生产构建通过。
+- 目标数据库过程发布成功。
+- 目标库真实数据中两个报表的已结束报工次数均为 30,多人 DID 展开结构正确。
+- 本地开发服务返回 HTTP 200。
+
## 2026-07-15 修复及时齐套生产订单 7912 工艺路线颜色
### 用户提问
diff --git a/src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue b/src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue
index dc8c647..0031766 100644
--- a/src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue
+++ b/src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue
@@ -64,7 +64,7 @@