unis_manager/.workbuddy/memory/MEMORY.md

76 lines
8.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 项目长期记忆 · unis_manager
软件部关键任务追踪看板。FastAPI 后端 + 原生 JS 前端 + SQLite。
## 运行环境(Windows)
`run.sh` 是 macOS 专用(`open`、`/Users/jiliu/...` 绝对路径),Windows 上按以下方式手动跑:
- Python 解释器(已装好依赖):`C:/Users/Administrator/.workbuddy/binaries/python/envs/default/Scripts/python.exe`
- 装依赖:`<PY> -m pip install -r requirements.txt`
- 启动:`<PY> -m uvicorn app.main:app --host 127.0.0.1 --port 8770`
- 端口/配置来自 `.env`(`PORT=8770`)。DB 用 SQLite,落在 `data/board.db`,仓库里已带数据。
- 健康检查:`GET /health`;API 文档:`/api/docs`;首页:`/`。
## 关键结构
- `app/` 后端:`main.py`(入口,挂载 `/api` 子应用 + `/static`)、`models.py`、`schemas.py`、`constants.py`、`routers/{board,projects,custom,focus,weekly,staff,ai,export}.py`、`ai_parser.py`、`export.py`、`schema_patch.py`、`config.py`。
- `web/` 前端:`index.html` / `app.js` / `styles.css` / `icons.js`(零构建,no-cache + ETag)。
- `scripts/` 运维脚本:`init_db.py`、`import_excel.py`、`import_staff.py`、`migrate_custom.py`、`shift_year.py`、`fix_period_split.py`、`merge_project.py`、`add_entry_date.py`、**`import_custom_ledger.py`**(把《定开项目.xlsx》市场台账导入 `custom_projects`,支持 `--dry-run`/`--date`,按 项目ID→名称 匹配做 upsert + 变更比对)。
- `.workbuddy/memory/` 存每日工作日志(随仓库提交,2026-09-12 起)。
- `schema_patch.ensure_columns` 会在启动时自动给已有表补上模型里**新增的可空列**(`ALTER TABLE ... ADD COLUMN`),所以加字段只需改 `models.py`,不用写迁移脚本。
## 业务模型
四模块:① 工作看板(只读汇总 `/api/weekly`+`/api/focus`)② 项目管理(`projects`/`tasks`/`updates`)③ 定开项目(原「定制交付」,表 `custom_projects`/`custom_updates`)④ 每周重点工作(`weekly_focus`)。
三支撑页:人力资源(`staff`,全系统负责人唯一来源)、更新录入、设置。
②③ 两套独立项目体系,共用一个花名册。
### 定开项目的两套字段(2026-09-17 起)
`custom_projects` 同时承载两套口径,**互不覆盖**:
- **交付跟踪口径**(原有):`stage`(商务阶段)/`progress`/`revenue_amount`/`invoice_amount`/`received_amount`/`owner`(交付负责人,来自花名册)
- **市场台账口径**(2026-09-17 从《定开项目.xlsx》导入):`origin`(项目归属)/`project_code`(项目ID)/`office`(办事处)/`industry`(行业)/`man_days`(市场下单人天)/`market_owner`(市场责任人,销售侧,**不在花名册**)/`project_status`(已验收/待开发/交付完成/交付中/退单)/`accept_plan`(推动验收计划)/`risk_level`(1.高风险/2.低风险)/`update_date`(更新时间)。**`origin`(项目归属) 取值**:新签订单 / 存量项目 / 汇智直签 / **提前交付**(2026-09-20 增) / 其他;**`progress`**(Float, NOT NULL, 默认 0) 复用为「交付中」项目的**进度(%)**
映射要点:`下单时间→sign_date`、`办事处→region`(归一化)+`office`(原样)、`验收时间→accept_date`(存的是**季度文本** Q1..Q4,不是日期)、`备注→remark`。`accept_date` 与 `accept_plan` 互补(60+59=119)。
**`accept_date` vs `accept_date_real`**(2026-09-17 增):`accept_date` 存季度文本(Q1..Q4),只作展示;新增 **`accept_date_real`**(真实日期 YYYY-MM-DD)专门给「本月/本年验收」统计用。导入脚本会给「已验收 + 季度文本」的行补**当年季度末**占位(Q1→03-31…Q4→12-31),且**只在库中为空时补**,不覆盖界面手改的真日期。**统计口径(2026-09-20 定稿)**:下单看 `sign_date`(本季度/本年按日期归属);**验收看「验收时间」`accept_date`(季度文本 Q1~Q4)**——本季度验收 = `accept_date` 等于当前季度,本年验收 = 有验收时间(全部季度)。**不再用 `accept_date_real`**(它只作参考/展示,历史上有 4 条 Q3 行缺值,曾导致本季度验收少算)。
明细表(`renderCustomList`)列顺序对齐 Excel 14 列 + 更新时间 + 操作;行内**只有「修改」**(详情靠点名称;归档按钮已按要求去掉)。**定开视图有 3 个 tab:项目明细 / 本周进展 / 年度任务**(`state.customTab`;原交付流水线 / 阶段看板 / 财务跟踪已下线)。列表在客户端按 关键字 + **项目归属** + 区域 + 状态 过滤。统计条 `.stat-row` 基于**全部已下单项目**(不随搜索/筛选变化):**已下单项目 / 合同额** + 本季度下单 + 本年新增下单 + 本季度验收 + 本年验收——**已下单 = 项目归属 ∈ {新签订单, 存量项目, 汇智直签}**(`isPlaced()` / `CUSTOM_PLACED`),**提前交付不计入下单**。「本周进展」tab(`renderCustomWeekly`)列出「更新时间」在本周(周一~周日)的项目,上方 3 张卡:**验收情况**(本周更新 ∩ 已验收)/ **本周新增项目**(按「下单时间」`sign_date` 在本周 ∩ 已下单或提前交付)/ **交付项目**(本周更新 ∩ 交付中+交付完成)。「年度任务」tab(`renderCustomAnnual`)按《年度任务.xlsx》出表:季度 + 计收目标(万元,前端常量 `CUSTOM_ANNUAL_TARGETS` = Q1 35/Q2 225/Q3 160/Q4 260)+ 回填列——**计收项目**(`accept_date` == Qn)/ **新增签单**(`isPlaced` 且 `sign_date` 在本年该季度),金额元→万元,完成率 = 计收金额 ÷ 目标。表格 `customTableHtml(rows)` 两个 tab 共用,在「项目状态」后新增**进度**列(`progress`,仅 状态=交付中 或 >0 时显示 `N%`)。项目名称搜索框**回车才查询**(`bindKeyword(id,{enter:true})`;cKeyword 定开 / pKeyword 项目已启用)。导出 Excel 列与明细表一致(15 列),跟随 归档/区域/状态/关键字 筛选。`openNewCustomDialog`(新建,更新录入页共用)字段同样对齐 Excel,提交时 `region` 由后端按 `office` 归一化(深圳→广东)。
**`update_date`(更新时间)的语义**:只在台账字段**确有变化**时才刷新(无变化不刷新)。
- **取值**:导入/初始 = 该行「下单时间」`sign_date`(2026-09-17 全量刷过);界面「修改 / 新建」提交后 = **提交时间** `YYYY-MM-DD HH:MM`(2026-09-18 起)。字段是 `String(16)`,正好放「YYYY-MM-DD HH:MM」。
- 用于明细表按更新时间倒序 + 按周筛选/删除。
- 与 `updated_at`(TimestampMixin 自动时间戳,任何改动都变)不是一回事。
导入「市场责任人」等销售侧人名**不走花名册校验**,不要往 `staff` 里塞。
## 登录与权限(2026-09-23 合并 main V 0.1.1 起)
- 全站需**登录**:未登录访问 `/api/*` 返回 **401**。默认管理员 **admin / admin123**(`app/config.py` 的 `ADMIN_PASSWORD` 默认值,可用 `.env` 覆盖);另有 `user`(部门成员)。
- 权限模型:`roles.menus` 是 JSON(board/custom/focus/intake/projects/rbac/settings/staff,值 `rw` / `ro`);内置角色 管理员 / 部门成员 / 只读访客。代码:`app/security.py`(hashlib+hmac 手写,无新依赖)、`app/routers/auth.py`、`app/routers/rbac.py`;表 `users` / `roles` / `user_sessions`。
## 术语(2026-09-16 起)
模块③ 的正式称呼是 **「定开项目」**(旧称「定制交付」),界面统一用「定开」:定开项目 / 定开项目明细 / 定开合同额 / 定开记录 / 定开动态 / 定开待计收。`categories` 表里也有一行分类叫「定开项目」。
**但这些字面量必须保留「定制」,改了会坏数据或逻辑**:
- `"定制开发"` —— 历史 Excel 的项目容器名,是 `import_excel.py` / `migrate_custom.py` / `fix_period_split.py` / `add_entry_date.py` 里的匹配条件。
- `import_excel.py` 中 `(("定制","交付","项目支撑"), "定开项目")` 的元组键 —— 匹配 Excel 原始分组名,只有映射目标值是「定开项目」。
- `"定制产品组"` —— `staff.group` 的团队名,`constants.py:STAFF_GROUPS` 里有它,7 人属于该组。
代码标识符(`custom` / `custom_projects` / API 路由 / CSS 类名)保持英文原名,未随中文改名。
## 约定
- 当前开发分支:`develop-chezhiqi`(跟踪 `origin/develop-chezhiqi`;main 为发布线)。
- 改代码后重启服务即可(未开 DEV 热加载)。
- 动数据库前先备份:`cp data/board.db data/board.db.bak`。
- 周期标签格式 `9月第1周`,可写 `2027年1月第1周` 显式指定年份。
## Windows 运维小抄
- 查端口占用:`netstat -ano | grep "127.0.0.1:8770.*LISTENING"`
- 停服务:git bash 下 `taskkill //PID` 会被路径转换破坏参数,改用 PowerShell `Stop-Process -Id <PID> -Force` 更稳。
- 服务重启后 `/health` 的 `BOOT_ID` 会变,可据此确认是新进程。