107 lines
7.9 KiB
Markdown
107 lines
7.9 KiB
Markdown
# 2026-09-13 周期错位修复
|
||
|
||
## 问题
|
||
系统里「2026年8月第4周」混进了「9月第1周」的内容(两块录到同一周期)。
|
||
|
||
## 根因
|
||
原始 Excel《周工作情况总结》最后一次导入时,表尾**只有一个「8月第4周」标签**,其内容里连着贴了两段。
|
||
`scripts/import_excel.py` 按 (项目, 子任务, 周期) 去重,同周期内重复出现就 append 到同一条记录
|
||
(见 import_excel.py:170-197),于是两周内容被揉在一起。Excel 文件后来(2026-09-13 16:08)被拆成了
|
||
「8月第4周」(行838-862) 和「9月第1周」(行863-890) 两个块。
|
||
|
||
## 修复
|
||
脚本 `scripts/fix_period_split.py`(--dry-run 预演,默认执行,自动备份 data/board.db)
|
||
按 Excel 现状把数据库对齐:
|
||
- 2026年8月第4周 → 只留 8月第4周内容(9 常规 + 1 定制)
|
||
- 2026年9月第1周 ← 从 8月第4周拆出的 9月第1周内容(10 常规 + 1 定制「金昌视综平台定制开发」)
|
||
- 2026年9月第2周 ← 原误放在 9月第1周 的数据(用户手工录入的 NEX 云桌面 2 条)
|
||
- 顺带重算受影响项目的进度/状态、受影响定制项目的入库时间
|
||
|
||
## 全量核查结论(内容级比对 Excel vs DB)
|
||
- 无跨周污染残留(8月第4周/9月第1周 那个是唯一一起,已修)
|
||
- 另有 7 条「DB 内容比 Excel 多」:
|
||
- 2025年3月第1周 3 条(云桌面产品培训/公司内IT平台规划/云屏V1.2版)
|
||
- 2026年5月第3周 2 条、5月第4周 1 条、6月第1周 1 条
|
||
→ **同一周内同一子项在源表里占多行**,导入时合并成一条;非跨周问题
|
||
- Excel 里存在**同标签重复块**:2024年9月第二周(行143/160)、2025年5月第3周(行503/528),
|
||
导入必然合并,属源表歧义,未擅自拆分
|
||
- 「智听云」→ 改名「iMeeting 语音智能体」、「智空无人机平台」→ 合并进「智飞无人机平台」,
|
||
在全量比对中表现为 Excel/DB 互不匹配,属正常
|
||
|
||
## 教训
|
||
导入脚本对「同周期同子项重复出现」采用 append 合并,源表一旦把两周内容贴在同一标签下就会静默串周。
|
||
后续若发现某周期记录数明显偏多,优先怀疑源表标签缺失。
|
||
|
||
---
|
||
|
||
# 重点项目 / 定制项目:多负责人 + 团队成员
|
||
|
||
## 需求
|
||
重点项目和定制项目都可以指定多个负责人,并新增「团队成员」。
|
||
|
||
## 兼容策略(关键决定)
|
||
- `owner` 列语义不变 = **主负责人** = `owners[0]`。列表、看板、导出、人力负载、KPI 全部照旧读 `owner`,**一行未改**。
|
||
- **不建关联表**:两张项目表各加 `other_owners`(其他负责人,不含主)与 `members`(团队成员)两个 `String(512)` 列,
|
||
存**首尾带逗号**的 CSV:`,张三,李四,` 或 NULL。于是 `LIKE '%,张三,%'` 是精确整名匹配,
|
||
「张三」不会命中「张三丰」(已测)。
|
||
- 新列靠 `app/schema_patch.py: ensure_columns` 启动时自动 `ALTER TABLE`,**无需迁移脚本**;真实库 `data/board.db` 本次未被写入。
|
||
- API 字段:`owners`(= 主 + 其他,主在首位)、`members`。PATCH **整体替换**:不传=不改,传 `[]`=清空。
|
||
老调用方只传 `owner` 时 `other_owners` 保留 → `owners` 自动变成 `[新主, ...其他]`,不会写出脏数据。
|
||
- 工具函数集中在 `app/models.py`:`split_people / dedupe_people / join_people / people_like / all_owners / set_people`;
|
||
`set_people` 同时负责「`owners[0]` 回写 `owner`」。
|
||
|
||
## 口径(容易误解,已和用户对齐的说法)
|
||
- 「负责人」筛选(项目列表 / 定制列表 / 周看板)**主负责人和其他负责人都算命中**;**团队成员不参与**该筛选(有意)。
|
||
- 列表、导出、人力负载、KPI 只按主负责人统计;列表负责人列只显示主负责人。
|
||
- 人员改名(`routers/staff.py`)会同步改写 `other_owners` / `members` 里的名字。
|
||
|
||
## 入口
|
||
只在详情抽屉的「修改」档(`peopleEditorHtml` / `peopleValues` / `bindDrawerPeople`,增删按钮一次性委托在 `#drawerBody`)。
|
||
第 0 行:负责人档标「主」不给删;成员档空占位行不给删,有值就能删。列表行仍然只有 详情/修改/归档。
|
||
**新建弹窗(npOwner/ncOwner)保持单个负责人**——假设:建好后进详情面板补名单。
|
||
|
||
## 并发提醒
|
||
`web/app.js` 同期被另一个任务改(人力资源表的星标计数),期间出现过一次模板串语法错误导致整站 JS 不解析(对方已自行修复)。
|
||
改这个文件前先 `node --check web/app.js` + `shasum`。
|
||
|
||
---
|
||
|
||
# 周工作 Focus:只显示当周 + 上周延期结转;录入期数 ≠ 预计完成时间
|
||
|
||
## 需求
|
||
> 周工作Focus的只显示当周和上周延期过来的。录入的时候也要注意这点,选择的结束时间并不是作为录入的期数。
|
||
|
||
老逻辑把 `due_date` 反查成 `periods` 里的一周存进 `period_id`,于是本周录一条「两周后交付」的活儿直接掉进「未来」堆,本周看不见。
|
||
|
||
## 语义变更(核心)
|
||
- `WeeklyFocus.period_id` 语义由「预计完成时间所属周」改成**录入周**,和 `Update.period_id`(反馈所属周)一致。
|
||
字段名/`to_dict` 键名(`period_id / period_label / period_full / sort_key`)全部保留 → 前端与导出零连锁改动。
|
||
- `due_date` 退化成纯目标日期:`focus.py: _resolve_period()` → `_entry_period(db, period_id)`,
|
||
**不再按日期反查周期**;POST 传 `period_id`=顶栏当前周,没传(脚本/API 直调)按 `constants.week_of_date(date.today())` 补;
|
||
PATCH 只有显式传 `period_id` 才搬周,改 `due_date` 不再动归属。
|
||
- 导出列「所属周」→「录入周」(`export.py`,排序仍按 period.sort_key desc)。
|
||
|
||
## 分堆口径(`web/app.js: focusBuckets`)
|
||
- `week` = 录入周 == 基准周;`overdue` = 录入周 < 基准周 且 `delayed` 且未完成(上周及更早的结转);`done` 仍是交叉视图。
|
||
- **删掉「未来」堆**(chip 从 5 个变 4 个:本周/延期/已完成/全部);`restoreUI` 里把存量的 `focusFilter==="later"` 复位成 `week`,否则老会话进来会看到空表。
|
||
- 取舍(已明确告知用户):更早周次录入、**没标延期**又没完成的条目不进当周视图,只能在「全部」里查 → 每周收尾要手动勾「延期」才会结转。
|
||
- 抽屉:录入周只读一行(新增取顶栏周,编辑显示原周);预计完成时间与录入周在详情里拆成两行;`#fdSave` 只在 `mode==="create"` 时带 `period_id`。
|
||
- 列表「预计完成时间」下的小字改为「录入 X月第N周」;看板左栏结转条目多挂一个「录入 …」标签。
|
||
|
||
## 顺带修的默认值问题(会导致本周看起来是空的)
|
||
`/api/periods` 里已预建了未来的周(库里已有 9月第3周),而 `loadPeriods` 的默认周取「列表最后一期」→ 顶栏会落在**下周**,
|
||
新的录入周口径下当周直接空掉。改为 `/periods` 多返回 `today_id`(`constants.week_of_date(date.today())` 命中的周),
|
||
默认周取 `today_id || 最后一期`。仅在「存的 weekId 不在列表里」时生效,不覆盖用户手选的周。
|
||
|
||
## 数据
|
||
库里 3 条 focus(全是 2026-09-13 建的)`period_id` 本来就是 9月第2周 = 今天所在周 → **无需回填**,语义切换后归属不变(已断言)。
|
||
|
||
## 验证
|
||
`/tmp/umtest/t_focus.py`(TestClient + `data/board.db` 副本):due=两周后仍归本周 / 不传 period_id 归今天所在周 /
|
||
改 due 不搬周 / 显式 period_id 才搬周 / 旧数据不漂移 / 导出 200。
|
||
UI(8791 + 副本库,插 5 条造结转场景):本周 3(含 due 9-20 那条)· 延期 3(9月第1周×2 + 8月第4周×1,未标延期与已完成的都不进来)·
|
||
已完成 2 · 全部 8;新增 due=09-27 立即进本周;改成 12-31 仍在本周;切到 9月第3周本周空态文案正确;`dev.logs()` 为空。
|
||
|
||
## 待办(历史遗留,未动)
|
||
`scripts/import_excel.py` 里旧台账 `LedgerItem` 的导入解析是否退役。
|