12451 f3f841b1f0 feat(users): 用户管理表格内直接分配组织(超管)
## 起因

用户指出「所属组织要可以分配」。核查后发现两件事:

1. **组织没丢** —— 生产 46 个组织、28 个项目、68 个柜子都在;
2. **但 5 个用户里 0 个被分到组织**,所以那一列全是 `-`。
   其中 2 个是总管理员(按规则本就不属组织,正确),
   另 3 个(李四/企业管理员、张三/王五/操作员)**从未分配**,违反
   「操作员必须有企业归属」的规则。

原流程要「点编辑图标 → 弹窗里选组织 → 保存」三步才能改一个用户,
3 个用户要重复 3 次。现改成**表格里直接分配**。

## 改动

`users.tsx` 的「所属组织」列:
- 超管 + 非总管理员 ⇒ 渲染成内联 `Select`,选完即存(`PUT /users/:id` 只传
  `organization_id`,后端 `UpdateUserInput` 本就支持,无需改后端);
- 总管理员行仍显示 `-`(后端 `resolve_update_org_id` 对 `role=2` 强制 `None`);
- 非超管操作者仍只读。

顺带修 `api/user.ts`:`fetchUsers` 的参数类型漏了 `role`(上一轮加了角色过滤
但类型没跟上,靠结构兼容蒙混过关)。

## 实测(测试环境,临时账号用完即删)

```
PUT 只传 organization_id        → HTTP 200,库中 organization_id 已更新   OK
改分配到另一组织                → HTTP 200,库中已更新                  OK
只改名不传组织                  → 组织保持原值,未被清空                  OK
给总管理员分组织                → HTTP 200 但库中仍为 None(被强制忽略)   OK
列表 organization_name          → 正确返回组织名                        OK
```

## ⚠️ 两个我自己出的岔子(都已修正)

1. **断言写错**:我原以为「给总管理员分组织」应返回 400,实测返回 200。
   读库确认 `organization_id` 仍是 `None` —— 后端是**静默忽略**而非拒绝,
   行为符合规则。是测试预期错,不是代码错。
2. **测试脚本留了脏数据**:临时用户删不掉,因为 `operation_logs` 有外键引用
   (`log_operation` 写了日志)。已补删 `operation_logs` → `user_roles` → `users`
   清理干净,测试库恢复 1 用户 / 1 组织 / 1 项目 / 1 柜子。

## 待用户决定(生产数据,我不擅自改)

李四 / 张三 / 王五 三个账号要分到哪个组织?生产有 46 个组织可选。
现在超管可以在表格里直接点选分配,你也可以告诉我分配方案我来执行。

## 验收

- web `npm run typecheck`:exit 0
- `npm run build`:exit 0
- 已发布生产(web 已更新,0 ERROR、域名 401/200)
2026-09-21 05:20:38 +08:00
..