7.9 KiB
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 的导入解析是否退役。