# 项目长期记忆 · 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` - 装依赖:` -m pip install -r requirements.txt` - 启动:` -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-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 -Force` 更稳。 - 服务重启后 `/health` 的 `BOOT_ID` 会变,可据此确认是新进程。