# 2026-09-14 负责人 / 团队成员:去掉主次 + 横向排列 ## 需求(用户原话) > 负责人、团队成员 不要分主次,横向排列(显示和管理页面) 采用的解读:① 界面不再出现「主」标记与首行特权,名单里每一位平级、都可删; ② 无论显示处(列表列、详情只读)还是管理处(抽屉修改档的人员编辑器),都改成横向一排,不再纵向堆叠。 ## 改动(纯前端,未动后端与库) `web/app.js` - `peopleEditorHtml()`:去掉 `opts.primary`(「主」徽标)与「首行不可删」的特殊分支, 每一行都是 `人名下拉 + ×`;「+ 添加负责人 / 添加成员」从名单下方挪进名单容器末尾。 - `bindDrawerPeople()`:新增行 `box.insertBefore(row, add)`(原来 appendChild 会把新行甩到按钮后面)。 - 删掉 `ownersHtml()`(原「第一位用正文、其余用小标签」),只读处统一用 `nameChips()` 对等小标签; `nameChips(list, empty)` 多一个占位符参数,供卡点/待回款两表保留「未指派」文案。 - 4 处负责人列/行改为全部负责人:项目列表、定制「项目明细」、定制「卡点提醒」、定制「待回款排行」。 后两处原来只显 `x.p.owner`,现在 `nameChips(x.p.owners, "未指派")`。 - 新增 `OWNER_HINT`(两处抽屉共用):界面不标主次,但如实写明「看板、筛选、导出与人力负载取名单第一位做归属统计」。 `web/styles.css` - `.people-rows`:`flex-direction: column` → `flex-wrap: wrap`(横向一排、放不下自动换行); `.people-row` 改 `inline-flex`;删掉随本次改动失效的 `.people-tag`。 - 新增 `.people-cell { display:flex; flex-wrap:nowrap; gap:4px }` 给表格里的负责人列。 (先试了 `wrap + max-width:152px`,结果 table 自动布局把列压到 47px、每人一行,等于还是竖排,故改成一排不换行。) `README.md`:功能表「负责人与团队」行、负责人下拉小节、数据模型 `owner=主负责人` 措辞、API 备注同步。 ## 口径没动(重要) - 存储照旧:`owner` 列 = `owners[0]`(`models.set_people` 负责回写)。UI 不再暗示主次, 但**看板、列表筛选、导出、人力负载、财务「按负责人汇总」仍按那一位归属**——删掉第一位就自动由后一位顶上(已实测)。 - 故意没改:新建弹窗的 `npOwner`/`ncOwner` 仍是单人下拉(建完去抽屉加人); 周看板卡片与右侧详情头仍是单个负责人 chip(该视图的负责人筛选下拉也按主负责人生成); 人力负载表、财务「按负责人汇总」是按人归属的统计表,不是展示位。 - 列表仍未加「团队成员」列(保持列表精简,成员在抽屉里看)。 ## 验证(临时实例 8791 + `data/board.db` 副本,未写真实库) - `node --check web/app.js` 通过;`dev.logs()` 全程为空。 - 项目列表:AI Agent 4 位负责人一排(`.people-cell` 内 chip 的 top 全等);无负责人显示「—」。 - 详情只读:负责人/团队成员首元素即 `.tag-mini`(不再有正文态的第一位),单行。 - 修改档:`#dwOwners`/`#cdOwners` 子项 `flex-wrap: wrap`、无 `.people-tag`、4 行都带 `[data-pdel]`、 添加按钮在末尾;点添加后空行插在按钮之前。 - 删掉第一位(付艾)保存 → `GET /api/projects/83` 得 `owner=潘朝钊`、`owners=[潘朝钊,汤全昆,钟文俊]`。 - 定制「项目明细 / 卡点提醒 / 待回款排行」三表负责人列一排显示,空值文案仍分别是「—」和「未指派」。 - 收尾:8791 已停(`lsof -iTCP:8791 -sTCP:LISTEN` 空),临时库已删;用户实例 8770(PID 44988/99343)未动, 本轮无 .py 改动,浏览器刷新即可看到新界面。 ## 待办(历史遗留,未动) `scripts/import_excel.py` 里旧台账 `LedgerItem` 的导入解析是否退役。 --- # 2026-09-14 多负责人只对重点项目生效(定制交付改回单负责人) ## 需求(用户原话) > 多负责人仅对于重点项目适用,请把相关的页面都做调整。 采用的解读:① 多负责人(`owners` 名单)这套能力**只保留在重点项目**; ② 定制交付回到**单个「交付负责人」下拉**,但**上一轮新增的「团队成员」保留**(用户没说要撤); ③ 定制侧所有展示位(列表列、只读档、项目明细、卡点提醒、待回款排行)与筛选口径都按单负责人走。 ## 前端 `web/app.js` - 定制抽屉修改档 2044:`#cdOwners` 人员编辑器 → `ownerSelectHtml(p.owner, 'id="cdOwner" style="width:150px"')` 单人下拉;2045 的 `peopleEditorHtml("cdMembers", …)` 团队成员编辑器原样保留。 - 定制保存 body 2147-2148:`owner: $("#cdOwner").value || null` + `members: peopleValues("cdMembers")`,不再送 `owners`。 - 定制只读档 2058-2059:`ro("交付负责人", esc(p.owner||"—"))`(回到纯文本)、`ro("团队成员", nameChips(p.members))`。 - 定制三表负责人列改回单人名:项目明细 1831、卡点提醒 1674、待回款 1780。 - 顺手清掉本轮造的孤儿:`OWNER_HINT` 常量删除并内联到唯一使用点(重点项目 2775,文案改口径); `nameChips(list)` 去掉 `empty` 参数(上一轮为定制两表加的,现在没人传了)。 - 新建弹窗 `ncOwner`(1895)/`npOwner` 本就是单人下拉,未动。 - 重点项目侧**一行未改**:列表 1350 `.people-cell`+`nameChips(p.owners)`、抽屉 2775/2780/2789/2790、保存 2943-2944。 (`.people-cell` CSS 还有这一处使用,故保留。) ## 后端(收口理由:界面已不可达的写路径必须一起关掉,否则库里会有两份真相) - `app/routers/custom.py`:`CustomProjectIn.owners` 字段删除;孤儿 import `or_`、`people_like` 清掉; 列表筛选 → `q.filter(CustomProject.owner == owner)`; POST `model_dump(exclude={"members"})` + `set_people(cp, None, payload.members)`; PATCH → `set_people(cp, None, payload.get("members"))`。传了 `owners` 也直接被忽略(已实测)。 - `app/routers/weekly.py`:124(定制段)→ `if owner and cp.owner != owner`;81(重点项目段)保留 `all_owners(...)`。 - `app/models.py`:`CustomProject.to_dict` 删 `"owners"` 键;`other_owners` 列注释 → `# 已停用:定制交付不做多负责人`。 **列不删、不加迁移**:`set_people(cp, None, …)` 不写该列,旧值原样躺在库里静默隐藏(已实测改写 owner 后旧值仍在)。 - `staff.py` 人名改名同步逻辑未动(对 custom 成为 no-op,但代码仍正确,不顺手重构)。 ## `README.md` 功能表「负责人与团队」行改成「多负责人仅重点项目;定制 = 交付负责人(单人)+团队成员」; 筛选口径写明「重点项目命中任一负责人、定制按交付负责人命中」; `peopleEditorHtml` 小节注明现在只剩重点项目抽屉在用;数据模型 / API 定制行同步(custom 不再接受 `owners`)。 ## 迁移决策 真实库 `data/board.db` 的 `custom_projects` 119 行里 `owner`/`other_owners`/`members` **三列全空** → 无数据可迁, 故不做任何迁移脚本,只让界面与 API 停止读写 `other_owners`。 ## 验证(临时实例 8792 + `/tmp/umtest/single.db` = 真实库副本 + 造数据,真实库只读) - `node --check web/app.js`、`py_compile app/models.py app/routers/custom.py app/routers/weekly.py` 通过;`dev.logs()` 全程 `[]`。 - API:定制 `#5` 响应**无 `owners` 键**,`owner=陈玉婷`、`members=[潘远银,向上]`;重点 `#83` `owners=[付艾,潘朝钊]` 不变。 POST/PATCH 带 `owners` 被忽略;定制筛选「陈玉婷」→`[5]`,重点筛选「潘朝钊」→`[83,80]`; `/weekly`、`/stats`、`/custom/board`、`/custom/stats`、`/staff`、`/focus`、`/export/*` 全 200。 注:`GET /api/custom/projects/{id}` 返回 `{project, updates, timeline}` 包壳,`owner` 在 `project` 下。 - UI(iab tab 30):定制只读档 labels = …交付负责人|团队成员…,无 `#cdOwners`;修改档 `#cdOwner` value=陈玉婷、 `#cdMembers` 2 行+添加按钮;端到端改「陈玉婷→汤全昆」保存 → toast「已保存」→ 库 `(5,'汤全昆',',况春华,陈航,',',潘远银,向上,')`(other_owners 未被改写)→ 只读档显示正确; 筛选「汤全昆」命中、筛选遗留名「况春华」不再命中(符合预期)。 - 重点项目回归:列表一排多负责人(AI Agent = 付艾|潘朝钊);只读档 ownerChips/memberChips 各 2 个; 修改档 `#dwOwners`=[付艾,潘朝钊]、`#dwMembers`=[梁帅超,罗帮旺]、`.people-rows` 横向。 - 收尾:8792 已停、临时库已删;用户实例 8770(PID 520/44988)未动,`.py` 由 run.sh 热重载,前端刷新浏览器即可。 ## 待办(未动,等用户定) 1. 周看板卡片与重点项目列表的负责人 chip 仍只显主负责人 `owner`,要不要改成显示全部负责人。 2. `scripts/import_excel.py` 旧台账 `LedgerItem` 导入是否退役(历史遗留)。