# 工作进度-25:修复「报表设计打不开」+ 补上「生产-考勤 · 考勤登记」 > **协作规则(长期生效)**:**每次对话结尾都要生成工作进度**。 > 即在每轮对话结束前,把本轮完成的内容追加为 `工作进度/工作进度-N.md`,并在文档中保留本条规则,方便下一轮接续。 ## 一、用户反馈 1. 报表设计页面打不开(之前可以用,今天突然不行) 2. 生产-考勤也没有 ## 二、报表问题:两个根因,都已修复 ✅ ### 根因 A:vite 开发服务器挂死(最直接的"打不开") | 检查 | 结果 | | --- | --- | | 后端 3000 | ✅ 正常(`/sys/report` 列表、模板下载、预览全部 200) | | 前端 5173 早期请求 | ✅ 200(`report/manage`、`ReportEditor`、`ReportDesign`、`grlib/grhtml5-7-min.js`) | | 稍后 `/`、`/src/views/prod/lsjl/index.vue` | ❌ **全部超时**(进程 25640 仍在 LISTENING,CPU 近乎 0 → 卡死不服务) | → 页面请求全部挂住,表现为"点了没反应 / 打不开"。 **修复**:按端口定位 PID → `Stop-Process -Id 25640 -Force` → 用完整路径 node 重启 vite(npm 不在 PATH): ```powershell Start-Process -FilePath 'C:\Users\32453\.workbuddy\binaries\node\versions\22.22.2-6\node.exe' ` -ArgumentList 'node_modules/vite/bin/vite.js' -WorkingDirectory 'd:/f9webaitest/f9-web-ai-test/web' -WindowStyle Minimized ``` 重启后 PID **26328**:`/` 200、`prod/kaoqin/index.vue` 200、`report/manage/index.vue` 200。 ### 根因 B:f9designer:// 宿主脚本解析 URL 失败(点「设计器编辑」无反应) 日志 `tools/report-designer/logs/designer_20261026.log` 里今天 6 次唤起全部报错: ``` 错误: 缺少 base / rid 参数(Url=f9designer://open/?base=...) ``` 原因:**Windows Shell 会在协议主机后补一个 `/`**,实际收到的是 `f9designer://open/?base=...`, 而脚本按固定前缀 `^f9designer://open\?` 剥离失败 → `base` 解析为空 → 直接 throw。 注册表里是 `-WindowStyle Hidden`,失败无提示 → 用户看到"点了没反应"。 **修复** `tools/report-designer/F9ReportDesignerHandler.ps1`: 1. 解析改为「取第一个 `?` 之后的全部内容」,兼容 `open?` 与 `open/?` 2. `base` 缺失时回退 `http://localhost:5173`(并记日志) 3. 新增 `Show-Error`:失败时弹 Windows MessageBox(含日志路径),不再静默 4. ⚠️ **踩坑**:编辑工具把文件存成了 **UTF-8 无 BOM**,Windows PowerShell 5.1 按 ANSI 读取导致中文注释/字符串乱码、脚本解析失败。 已用 `UTF8Encoding($true)` 重写为 **UTF-8 with BOM**,`ParseFile` 复检通过。 **下次改这个脚本后务必确认 BOM 仍在**(`[System.IO.File]::ReadAllBytes($p)[0..2]` 应为 239,187,191)。 **端到端实测**(用 `F9_GR7_DESIGNER` 指向一个立刻退出的程序代替设计器): ``` base=http://localhost:5173 rid=141374578868883456 code=PROD_QS_1 已下载 8300 字节 → 启动设计器(等待关闭)→ 设计器已关闭 → 上传结果: OK → 完成 ``` 模板回传后长度仍为 7639 字节、报表 `hasTemplate=True`,未损坏。 ## 三、生产-考勤:本轮补上「考勤登记(CQDJ)」✅ > 「没有」的原因:23 轮按计划**删除了旧考勤**(`/attendance`),而「生产-职工考勤」移植尚未开始。 ### 后端(新增) | 文件 | 说明 | | --- | --- | | `Domain/Entities/Prod/Cqdj.cs` | `Cqdj`(表 `biz_prod_kq_cqdj`)+ `CqdjItem`(表 `biz_prod_kq_cqdj_item`),继承 `BaseEntity`,**自动建表**(`DbSeeder.SyncStructure` 反射扫描) | | `Application/Dtos/Prod/KaoqinDtos.cs` | `CqdjItemDto / CqdjRowDto / CqdjViewDto / CqdjSaveDto / CqdjEmpOptionDto` | | `Application/Services/Prod/KaoqinService.cs` | 接口+实现同文件:整组查询 / 整组覆盖保存 / 整组删除 / 可选职工 | | `Api/Controllers/Prod/KaoqinController.cs` | `[Route("api/prod/kaoqin")]` `[Authorize]`:`GET|POST|DELETE /cqdj`、`GET /cqdj/employees` | | `Application/DependencyInjection.cs` | `services.AddScoped();` | 规则按 23 轮调研落地: - 查询口径:日期 + 部门(必选)+ 工种(0=全部)+ 班次(甲1/乙2)+ 关键字 - 职工来源:本部门、工种≠0、非离职;未登记者生成默认值 9 小时 + 一条「正常」明细 - **正常明细倒挤**:`正常 = 标准 - 请假 - 旷工 - 流动 - 外派 - 代班 - 工伤`;`出勤 = 正常+流动+代班+外派+工伤` - 保存 = **先软删该(日期+部门+工种+班次)旧登记与明细,再整批新增**(非增量 diff) - 校验:每人必须有且仅有一条「正常」;请假必须选请假类型、非请假必须为「无」;出勤不能为负 ### 前端(新增) - `web/src/views/prod/kaoqin/index.vue`:上表(职工行 + 标准时长/夜班/备注 + 各时长实时汇总)下表(选中职工的明细:出勤类型/请假类型/时长/机组/车台/挡车数/备注), 工具栏含 查询 / 设标准时长 / 添加职工 / 删除整组 / 保存 - `web/src/router/index.js`:`'prod/kaoqin/index': () => import('../views/prod/kaoqin/index.vue')` ### 菜单(`DbSeeder.SeedProdMenus`) ```csharp EnsureTopMenuWithChildren(fsql, snowflake, "/prod/kaoqin", "生产-考勤", "Clock", 8, new[] { ("考勤登记", "/prod/kaoqin/cqdj", "prod/kaoqin/index", "prod:kaoqin:cqdj:list", "EditPen", 1) }); ``` 同时**清理了遗留旧考勤菜单**(页面组件已删,留着会点开空白页): 删除 `sys_rbac_menus` 中 `path LIKE '/attendance%'` 的记录及其 `role_permissions`, 并删除 `code LIKE 'attendance:%'` 的权限单元。 ### 验证 | 项 | 结果 | | --- | --- | | 解决方案编译 | **0 个错误** | | `GET /auth/menus` | ✅ 出现 `生产-考勤 → 考勤登记`,旧「考勤管理」已消失 | | `GET /prod/kaoqin/cqdj?date=2026-10-26&depId=34&banci=1` | ✅ 46 人,每人默认 9 小时 + 1 条正常明细 | | `POST /prod/kaoqin/cqdj` | ✅ `count=46`;复查 `saved=46` | | `DELETE /prod/kaoqin/cqdj` | ✅ `count=46`;复查 `saved=0`(测试数据已清理) | | 前端模块编译 | ✅ vite 200 | ## 四、待办 1. **考勤统计(CQTJ)**:月快照,强依赖工种薪资配置 `ConfGz`(已有)+ 职工薪资配置 CONFEMPLOYEE / 账期薪资配置 CONFZQ(**后端还没有,需先建**) 2. 老系统「添加其他车间」功能无页面引用,不移植 3. 报表设计:可视化画布与锐浪设计器二选一(用设计器保存后产物为 `_WR7_`,画布将不可解析) 4. `views/notification/type/index.vue` 里的 `/attendance/approve?leaveId=` 仍是示例文本,建议改成中性示例 ## 五、下次接续提示 - 改后端代码后**必须重启后端**(先按端口 Stop-Process,否则 DLL/obj 锁定导致编译失败);改前端 vite 热更新,但 **vite 卡死时要按端口杀掉重启** - 登录 admin / 123456;后端 3000(PID 23968),前端 5173(PID 26328) - 考勤相关文件:`Domain/Entities/Prod/Cqdj.cs`、`Dtos/Prod/KaoqinDtos.cs`、 `Services/Prod/KaoqinService.cs`、`Controllers/Prod/KaoqinController.cs`、`views/prod/kaoqin/index.vue` - 报表相关:`views/report/manage/index.vue`、`components/report/ReportEditor.vue`、`ReportDesign.vue`、 `tools/report-designer/F9ReportDesignerHandler.ps1`(**务必保持 UTF-8 BOM**) - **每轮对话结尾记得生成本工作进度文档**