# 工作时间系统实施计划 ## 一、需求概述 ### 1.1 核心需求 1. **工作时间配置**:在系统设置中增加上班时间设置(开始时间、结束时间) 2. **动态计算**:一天的工作时间根据设置的上班时间段作为自然日(替换硬编码的8小时) 3. **截止时间计算**:计算截止时间时只计算到上班时间段内 4. **延误扣分限制**:延误扣分时间也需要限制在上班时间段内才扣分,超过上班时间不扣分 ### 1.2 涉及场景 - 截止时间计算(任务创建、子任务分配时) - 延误扣分计算(任务完成时、进行中任务检查时) - 时效格式化显示(前端显示、钉钉通知) - 子任务截止日期显示(前端任务卡片) --- ## 二、数据库设计 ### 2.1 使用系统配置表(sys_config) **方案选择**:使用现有的 `sys_config` 表存储工作时间配置(参考 `site_url` 配置的实现方式) **配置项设计**: - `config_key`: `work_hours.start_time`(上班开始时间,格式:HH:mm,如 "09:00") - `config_key`: `work_hours.end_time`(上班结束时间,格式:HH:mm,如 "18:00") - `config_group`: `system` - `value_type`: `string` - `built_in`: `1`(系统内置,不可删除) **默认值**: - `work_hours.start_time`: `"09:00"` - `work_hours.end_time`: `"18:00"` - 工作时间长度:9小时(9:00-18:00,不含午休) ### 2.2 数据库迁移文件 创建 `V12__add_work_hours_config.sql`: ```sql -- 添加上班时间配置 INSERT INTO `sys_config` (`config_key`, `config_value`, `config_group`, `config_name`, `description`, `value_type`, `built_in`, `sort_order`, `create_time`, `update_time`, `deleted`) VALUES ('work_hours.start_time', '09:00', 'system', '上班开始时间', '工作日上班开始时间,格式:HH:mm(24小时制),例如:09:00', 'string', 1, 20, NOW(), NOW(), 0), ('work_hours.end_time', '18:00', 'system', '上班结束时间', '工作日上班结束时间,格式:HH:mm(24小时制),例如:18:00', 'string', 1, 21, NOW(), NOW(), 0) ON DUPLICATE KEY UPDATE `update_time` = NOW(); ``` --- ## 三、后端实现 ### 3.1 工作时间计算工具类 **文件路径**:`backend/src/main/java/com/designhub/util/WorkHoursCalculator.java` **核心方法**: 1. `getWorkHoursConfig()`:从系统配置获取工作时间(开始时间、结束时间、工作时长) 2. `calculateDeadline(LocalDateTime startTime, BigDecimal workHours)`:计算截止时间(只计算工作时间段) 3. `calculateDelayHours(LocalDateTime deadline, LocalDateTime actualTime)`:计算延误时间(只计算工作时间段内的延误) 4. `formatWorkHours(BigDecimal hours)`:格式化工时显示(X天X小时,基于工作时间段) **计算逻辑**: - **截止时间计算**: - 从开始时间(接单时间)开始,累加工时 - 只在工作时间段内累加(跳过非工作时间) - 如果当前时间不在工作时间内,先移动到下一个工作日的开始时间 - 如果工时跨越多天,跳过周末(可选,根据需求) - **延误时间计算**: - 从截止时间到实际完成时间 - 只统计工作时间段内的小时数 - 跳过非工作时间(下班后、周末) ### 3.2 系统配置 Service 扩展 **文件路径**:`backend/src/main/java/com/designhub/service/SystemConfigService.java` **新增方法**: - `getWorkHoursConfig()`:获取工作时间配置(返回 WorkHoursConfig 对象) **新增内部类**: ```java public static class WorkHoursConfig { private LocalTime startTime; // 上班开始时间 private LocalTime endTime; // 上班结束时间 private int workHoursPerDay; // 每天工作小时数 } ``` ### 3.3 需要修改的后端文件清单 #### 3.3.1 时效格式化(替换硬编码的8小时) - `TaskService.java`:`formatHours()` 方法 - `TaskItemService.java`:`formatEstimatedHours()` 方法 - `TaskApprovalService.java`:`formatEstimatedHours()` 方法 **修改方式**: - 从 `WorkHoursCalculator.formatWorkHours()` 获取格式化结果 - 使用动态的工作时长(从配置读取)替换硬编码的8小时 #### 3.3.2 截止时间计算 - `TaskService.java`:任务创建时的截止时间计算 - `TaskItemService.java`:子任务创建时的截止时间计算 - `TaskApprovalService.java`:任务审批通过后的截止时间计算 **修改方式**: - 使用 `WorkHoursCalculator.calculateDeadline()` 计算截止时间 #### 3.3.3 延误扣分计算 - `AnalyticsService.java`: - `getDesignerPerformance()`:设计师绩效统计中的延误扣分 - `getDesignerDeductionDetails()`:设计师扣分明细中的延误扣分 - `DelayPenaltyService.java`:`calculateDelayPenalty()` 方法(如果有使用) - `TaskService.java`:任务完成时的延误扣分计算(`completeTask()` 方法) **修改方式**: - 使用 `WorkHoursCalculator.calculateDelayHours()` 计算延误时间 - 只计算工作时间段内的延误 --- ## 四、前端实现 ### 4.1 工作时间配置 UI **文件路径**:`frontend/src/views/Settings.vue` **新增标签页**:在"网站设置"标签页中添加"工作时间设置"区域 **UI 组件**: - 开始时间选择器(TimePicker,格式:HH:mm) - 结束时间选择器(TimePicker,格式:HH:mm) - 工作时间长度显示(自动计算,只读) - 保存按钮 **配置项**: - `work_hours.start_time`:上班开始时间 - `work_hours.end_time`:上班结束时间 ### 4.2 需要修改的前端文件清单 #### 4.2.1 截止时间计算 - `frontend/src/components/TaskCard.vue`:`getSubTaskDeadline()` 方法 - `frontend/src/views/TaskHall.vue`:`getSubTaskDeadline()` 方法 - `frontend/src/views/CreateTask.vue`:`estimatedDeadline` 计算属性 **修改方式**: - 从系统配置获取工作时间 - 使用工作时间计算截止时间(调用后端API或前端计算) #### 4.2.2 时效格式化显示 - `frontend/src/views/TaskHall.vue`:`formatEstimatedTime()` 函数 - `frontend/src/views/CreateTask.vue`:`formatWorkHours()` 函数 **修改方式**: - 从系统配置获取工作时长 - 使用动态工作时长替换硬编码的8小时 --- ## 五、API 设计 ### 5.1 获取工作时间配置 **接口**:`GET /api/system-config/work-hours` **响应**: ```json { "code": 200, "data": { "startTime": "09:00", "endTime": "18:00", "workHoursPerDay": 9 }, "message": "操作成功" } ``` ### 5.2 更新工作时间配置 **接口**:`PUT /api/system-config/work-hours` **请求体**: ```json { "startTime": "09:00", "endTime": "18:00" } ``` **响应**: ```json { "code": 200, "data": true, "message": "操作成功" } ``` ### 5.3 计算截止时间(可选,如果需要前端计算) **接口**:`POST /api/system-config/calculate-deadline` **请求体**: ```json { "startTime": "2026-01-14T09:00:00", "workHours": 16 } ``` **响应**: ```json { "code": 200, "data": "2026-01-16T10:00:00", "message": "操作成功" } ``` --- ## 六、实施步骤 ### 阶段一:数据库和基础工具类 1. ✅ 创建数据库迁移文件 `V12__add_work_hours_config.sql` 2. ✅ 创建 `WorkHoursCalculator` 工具类 3. ✅ 在 `SystemConfigService` 中添加 `getWorkHoursConfig()` 方法 4. ✅ 创建工作时间配置 API(`SystemConfigController` 或新 Controller) ### 阶段二:后端核心逻辑修改 5. ✅ 修改 `TaskService.formatHours()` 使用动态工作时长 6. ✅ 修改 `TaskItemService.formatEstimatedHours()` 使用动态工作时长 7. ✅ 修改 `TaskApprovalService.formatEstimatedHours()` 使用动态工作时长 8. ✅ 修改任务创建时的截止时间计算逻辑 9. ✅ 修改子任务创建时的截止时间计算逻辑 10. ✅ 修改 `AnalyticsService` 中的延误扣分计算 11. ✅ 修改 `TaskService.completeTask()` 中的延误扣分计算 ### 阶段三:前端实现 12. ✅ 在 `Settings.vue` 中添加工作时间配置 UI 13. ✅ 创建前端 API 调用(`api/system.ts`) 14. ✅ 修改 `TaskCard.vue` 中的截止时间计算 15. ✅ 修改 `TaskHall.vue` 中的截止时间计算 16. ✅ 修改 `CreateTask.vue` 中的截止时间计算 17. ✅ 修改前端时效格式化函数 ### 阶段四:测试和优化 18. ✅ 测试工作时间配置的保存和读取 19. ✅ 测试截止时间计算(跨天、跨周末等场景) 20. ✅ 测试延误扣分计算(工作时间段内、外) 21. ✅ 测试时效格式化显示 22. ✅ 测试钉钉通知中的时效显示 23. ✅ 修复发现的 bug --- ## 七、技术难点和注意事项 ### 7.1 工作时间计算复杂性 - **跨天计算**:工时可能跨越多天,需要跳过非工作时间 - **跨周末**:是否需要跳过周末?建议第一版先不考虑,只处理工作日的工作时间段 - **时区问题**:确保使用系统时区 ### 7.2 性能考虑 - 工作时间配置需要频繁读取,建议缓存(可以使用 Spring Cache) - 截止时间计算可能涉及循环,需要优化算法 ### 7.3 向后兼容 - 如果配置不存在,使用默认值(9:00-18:00,9小时) - 确保旧数据不会因为配置缺失而出错 ### 7.4 数据迁移 - 现有任务的截止时间是否需要重新计算? - **建议**:不重新计算,只影响新创建的任务和新的延误扣分 - 现有延误扣分记录是否需要重新计算? - **建议**:不重新计算,只影响新产生的延误扣分 --- ## 八、测试用例 ### 8.1 工作时间配置 - 测试保存和读取工作时间配置 - 测试配置格式验证(HH:mm 格式) - 测试开始时间不能晚于结束时间 - 测试配置不存在时使用默认值 ### 8.2 截止时间计算 - 测试同一工作日内完成的任务 - 测试跨天的任务(例如:16小时工时,从上午开始) - 测试从非工作时间开始的任务(例如:晚上接单,从第二天早上开始计算) - 测试跨周末的任务(如果实现) ### 8.3 延误扣分计算 - 测试在工作时间内延误的扣分 - 测试跨越下班时间的延误(只计算工作时间内的延误) - 测试跨越周末的延误(只计算工作日的延误) - 测试提前完成的任务(不扣分) ### 8.4 时效格式化 - 测试小时数少于1天的情况 - 测试小时数等于1天的情况 - 测试小时数超过1天的情况 - 测试小数点小时数(如 1.5 小时) --- ## 九、预计工作量 - **数据库设计**:0.5 天 - **后端工具类开发**:2 天 - **后端逻辑修改**:3 天 - **前端 UI 开发**:1 天 - **前端逻辑修改**:1.5 天 - **测试和修复**:2 天 **总计**:约 10 个工作日 --- ## 十、风险点 1. **计算逻辑复杂性**:工作时间计算涉及复杂的日期时间处理,容易出现边界情况 2. **性能问题**:如果计算逻辑复杂,可能影响性能 3. **向后兼容性**:确保现有功能不受影响 4. **数据一致性**:确保前后端计算逻辑一致 --- ## 十一、后续优化建议 1. **支持多时间段**:支持上午、下午两个时间段(考虑午休) 2. **支持周末配置**:允许配置周末是否工作 3. **支持节假日配置**:支持配置节假日,跳过计算 4. **历史数据重算**:提供工具重新计算历史任务的截止时间和延误扣分