feat(projects): 1、执行、任务、工作日志开发调试;2、增加富文本、附件等支撑

This commit is contained in:
2026-05-12 21:41:39 +08:00
parent 28c47b14a3
commit 5615399a68
59 changed files with 8046 additions and 919 deletions

View File

@@ -11,6 +11,8 @@
默认回答保持精简,优先给结论、改动点、验证方式和必要风险;如果用户只要求分析、审阅或方案,就停留在分析层,不主动扩展到实现层。
分析、解释、方案类回答优先用业务和逻辑语言把结构、差异与结论说清楚,不要大段贴源码、罗列 `file:line` 或把实现细节当解释;只有用户明确要求看代码、或某行确实是讨论焦点的关键佐证时,才贴最小必要的代码片段。
## 交互与执行原则
- 进入实施阶段前,先说明目标、涉及模块、预计改动点和验证方式。
@@ -173,6 +175,31 @@
- 涉及路由、菜单、权限的改动时,同时检查 `build/plugins/router.ts``src/router/routes/*``src/store/modules/route/*` 和相关文档。
- 对于可再生的路由产物,优先修改源配置并执行 `pnpm gen-route`,不要把手工修补生成文件当成常规方案。
## 防重复提交(两层联防)
用户快速双击、键盘连按 Enter、`ElMessageBox.confirm` 的"确定"按钮内置无 loading 等场景,都可能让同一写操作发出多次。仓库采用两层防御,新增写操作功能时按顺序检查:
### 第一层:业务按钮的 loading 锁(视觉防御)
- 新增、编辑入口优先使用 `src/components/custom/business-form-dialog.vue``src/components/custom/business-form-drawer.vue`,它们在 `submit` 流程内 await 接口期间会自动将"确认"按钮置为 `loading` + `disabled`
- 不要裸手写 `<ElButton @click="submit">` 直接调接口;若必须使用裸 `ElButton`,需要自行绑定 `:loading` 并在 await 接口期间锁住按钮。
- 删除二次确认使用 `ElMessageBox.confirm` 时,其内部"确定"按钮没有 loading 能力,必须依赖第二层兜底,不要尝试改造 confirm 的内部按钮。
### 第二层:请求层全局去重(逻辑兜底)
- 入口:`src/service/request/dedupe.ts` 提供 `withDedupe`,已在 `src/service/request/index.ts` 包住统一的 `request` 实例;`demoRequest` 未启用。
- 指纹:`method + 完整 URL + 排序后的 params + 稳定序列化的 body`body 内对象按 key 排序,数组保序。
- 行为:写操作(`POST` / `PUT` / `DELETE` / `PATCH`)在第一次请求 pending 期内,若再次发起指纹相同的请求,自动复用第一次的 Promise不发出第二次实际请求调用方两次拿到完全相同的返回对象。
- 跳过条件(即不去重,按原逻辑发出):`GET` / `HEAD` / `OPTIONS`,请求体为 `FormData``Blob`(上传场景),调用方显式传 `{ dedupe: false }`
- 业务调用方零感知:新增接口默认即享受兜底,不需要在 `src/service/api/*` 或页面层做任何改动。
- 极少数业务确实允许短时间内并发提交完全相同的写请求时,在调用处显式传 `request({ ..., dedupe: false })` 单接口关闭。
- 兜底超时 30 秒:极端情况下若某次 Promise 未 settlepending 条目过期后下一次相同请求视为新请求,避免内存泄漏。
### 设计责任划分
- 视觉层负责"按下立刻锁住按钮"的用户感知;逻辑层负责"即使锁失败也只发一次"的实际接口保护。
- 不要因为有第二层兜底就省略第一层 loading 锁:用户没有视觉反馈会再次点击;也不要试图在业务页面再造一套请求去重逻辑。
## 运行时字典使用口径
- 运行时字典统一由 `src/store/modules/dict/index.ts` 管理,登录后通过 `/system/dict-data/frontend-cache` 初始化;不要在业务页面重复直调字典接口。