Sfoglia il codice sorgente

docs: add org admin management feature design spec

iwt 3 settimane fa
parent
commit
e15d9da5c7

+ 277 - 0
docs/superpowers/specs/2026-10-22-org-admin-management-design.md

@@ -0,0 +1,277 @@
+# 机构/企业组织管理
+
+**优先级:** P1
+**预计工时:** ~3 天(后端)+ ~2 天(前端 cfc-web)
+**日期:** 2026-10-22
+**状态:** 设计完成
+
+---
+
+## 一、背景与目标
+
+随着平台用户规模增长,机构和企业管理员需要有属于自己的入口来查看和管理其组织内的规划师和用户,同时获得针对本组织的统计大屏,而不依赖平台运营员逐条导出。
+
+**核心目标:**
+1. 平台运营可创建组织(企业/机构),并绑定组织管理员账号
+2. 组织管理员能统一管理组织内规划师和用户成员
+3. 组织管理员拥有一张专属统计大屏,仅展示本组织相关数据
+4. 复用现有 `users` 体系,新成员无需重新注册
+
+---
+
+## 二、用户角色
+
+| 角色 | 数据来源 | 权限范围 |
+|------|----------|----------|
+| 平台角色(admin/operator/finance) | `users.roles` 包含 `admin` 等 | 可管理所有组织,看全平台数据 |
+| 组织管理员(org_admin) | `users.roles` 包含 `org_admin`,`organizations.admin_user_id = userId` | 仅能查看/管理自己所属的组织 |
+| 组织成员 | `org_members` 表 | 普通用户或规划师,通过已有登录体系(家长端/规划师端)进入,不额外提供独立登录 |
+
+---
+
+## 三、数据模型
+
+### 新建表 1:`organizations`(组织主表)
+
+```sql
+CREATE TABLE IF NOT EXISTS organizations (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    name VARCHAR(128) NOT NULL COMMENT '组织名称',
+    type VARCHAR(32) COMMENT 'enterprise/institution/other',
+    code VARCHAR(64) UNIQUE COMMENT '组织编号(唯一标识)',
+    admin_user_id BIGINT COMMENT '组织管理员 userId(关联 users.id)',
+    contact_name VARCHAR(64) COMMENT '联系人姓名',
+    contact_phone VARCHAR(20) COMMENT '联系人手机号',
+    description TEXT COMMENT '组织简介',
+    status VARCHAR(16) DEFAULT 'active' COMMENT 'active/disabled',
+    created_at DATETIME,
+    updated_at DATETIME,
+    INDEX idx_org_admin (admin_user_id),
+    INDEX idx_org_status (status)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='机构/企业组织';
+```
+
+### 新建表 2:`org_members`(组织成员关联表)
+
+```sql
+CREATE TABLE IF NOT EXISTS org_members (
+    id BIGINT AUTO_INCREMENT PRIMARY KEY,
+    org_id BIGINT NOT NULL COMMENT '关联 organizations.id',
+    user_id BIGINT NOT NULL COMMENT '关联 users.id',
+    member_type VARCHAR(32) NOT NULL COMMENT 'planner/user',
+    status VARCHAR(16) DEFAULT 'active' COMMENT 'active/inactive',
+    joined_at DATETIME,
+    INDEX idx_org_member_org (org_id),
+    INDEX idx_org_member_user (user_id),
+    UNIQUE KEY uk_org_member (org_id, user_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='组织成员';
+```
+
+### 关键设计决策
+
+- **不建独立成员表**:直接关联 `users.id`,成员复用现有登录和档案体系
+- **组织管理员独立于 Admin 表**:复用 `users` 表 + `roles` 字段,新增 `org_admin` 角色即可,无需为 Admin 表单独加字段
+- **与 SupplySystem 独立**:两者互不耦合,Org 管理成长规划师与用户,Supply 管理供应链结算
+
+---
+
+## 四、API 接口设计
+
+> 路由前缀 `/api/admin/org/*`,由现有 `JwtInterceptor` 保护;Controller 内手动检查角色。
+
+### 4.1 组织管理(仅平台角色)
+
+| 路径 | 说明 | 关键参数 |
+|------|------|----------|
+| `POST /api/admin/org/list` | 组织列表(分页/筛选) | `keyword`, `type`, `status`, `page`, `size` |
+| `POST /api/admin/org/create` | 创建组织(同步创建管理员账号) | `name`, `type`, `code`, `adminPhone`, `adminRealName` |
+| `POST /api/admin/org/update` | 更新组织信息 | `id`, `name`, `type`, `contactName`, `contactPhone`, `description` |
+| `POST /api/admin/org/disable` | 停用/启用组织 | `id`, `status` |
+| `POST /api/admin/org/detail` | 组织详情(含管理员信息) | `id` |
+
+**`create` 接口逻辑:**
+1. 按 `adminPhone` 查找已有 `users` 记录(如有则复用);否则创建新 `users` 记录
+2. 为新用户设置 `roles = ["org_admin"]`、`role = "org_admin"`
+3. 创建 `organizations` 记录,`admin_user_id` 指向该 userId
+4. 返回 `organization` + `adminUser`
+
+### 4.2 组织成员管理(平台角色 + 组织管理员)
+
+| 路径 | 说明 | 权限说明 |
+|------|------|----------|
+| `POST /api/admin/org/member/list` | 成员列表(含简要家庭/任务/订单信息) | 平台看全量;org_admin 只看自己组织 |
+| `POST /api/admin/org/member/add` | 添加成员 | 同上 |
+| `POST /api/admin/org/member/remove` | 移除成员(软删,status=inactive) | 同上 |
+| `POST /api/admin/org/member/change-type` | 变更成员类型(planner ↔ user) | 同上 |
+
+**`member/list` 返回字段示例:**
+```json
+{
+  "id": 1,
+  "userId": 1001,
+  "nickname": "张三",
+  "phone": "138****1234",
+  "avatar": "/static/avatar.jpg",
+  "memberType": "planner",
+  "status": "active",
+  "joinedAt": "2026-08-01T10:00:00",
+  "familyCount": 3,
+  "totalOrders": 12,
+  "totalConsumption": 58000
+}
+```
+
+### 4.3 统计大屏(平台角色 + 组织管理员)
+
+| 路径 | 说明 |
+|------|------|
+| `POST /api/admin/org/stats/overview` | 总览卡片:成员总数、规划师数、家庭数、总订单、总消费 |
+| `POST /api/admin/org/stats/families` | 家庭维度:活跃家庭数、成员任务完成率、打卡率 |
+| `POST /api/admin/org/stats/active` | 活跃度趋势:近30天/7天 任务完成/打卡/报告上传量 |
+| `POST /api/admin/org/stats/revenue` | 营收:订单金额/会员订阅/佣金,按时间段分组 |
+| `POST /api/admin/org/stats/trend` | 日/周维度趋势图数据(活跃成员数/订单数/收入) |
+
+**实现方式:** 基于 `org_members` 表取出 `user_id` 集合,批量查现有表(`families`/`tasks`/`product_orders`/`commission_records` 等),不新建统计汇总表,避免数据同步问题。组织规模大时可加 Redis 缓存(TTL 5分钟)。
+
+---
+
+## 五、权限规则
+
+```
+requirePlatformOrOrgAdmin(orgId, userId):
+  1. 先取当前用户所属的 orgId(organizations.admin_user_id = userId)
+  2. 若为平台角色 → 放行
+  3. 若 orgId 与请求中的 orgId 一致 → 放行
+  4. 否则 → 403 无权限
+```
+
+**排除规则:** 组织管理员只能访问 `/api/admin/org/**` 下与自身组织相关的接口,不能访问用户管理、商品、佣金等其他管理端接口。
+
+---
+
+## 六、前端设计(cfc-web)
+
+### 新增页面:`src/views/admin/org/`
+
+| 文件 | 路由 | 说明 |
+|------|------|------|
+| `List.vue` | `/org` | 组织列表(搜索/状态筛选/新建入口) |
+| `Form.vue` | `/org/create`、`/org/:id/edit` | 组织信息表单(含管理员账号创建) |
+| `Detail.vue` | `/org/:id` | 成员管理 Tab(成员列表/添加/移除/改类型) |
+| `Dashboard.vue` | `/org/:id/dashboard` | 统计大屏(总览卡片 + 家庭/活跃/营收/趋势图) |
+
+### 菜单配置
+
+在 `Layout.vue`「系统配置」下新增:
+```js
+{ path: '/org', label: '组织管理', icon: 'el-icon-office-building', perm: 'system:org' }
+```
+
+### 组织管理员首页
+
+组织管理员登录管理端后,自动跳转至自己组织的 Dashboard(`/org/:id/dashboard`),不展示列表页。
+
+### 时间格式规范
+
+遵循项目统一规范:
+- 时间场景:`t.replace('T', ' ').substring(0, 19)`  → `yyyy-MM-dd HH:mm:ss`
+- 仅日期场景:截取前 10 位 → `yyyy-MM-dd`
+
+### API 封装
+
+新增 `src/api/org.js`,封装上述所有接口,统一错误处理。
+
+---
+
+## 七、数据库迁移
+
+`DatabaseInitializer.runMigrations()` 新增:
+
+```java
+// 迁移N: 创建 organizations 表(组织管理功能)
+try {
+    jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS organizations (...)");
+    log.info("已创建 organizations 表");
+} catch (Exception e) {
+    // 表已存在,忽略
+}
+
+// 迁移N: 创建 org_members 表(组织成员关联)
+try {
+    jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS org_members (...)");
+    log.info("已创建 org_members 表");
+} catch (Exception e) {
+    // 表已存在,忽略
+}
+```
+
+同步更新 `schema.sql`。
+
+---
+
+## 八、涉及模块清单
+
+### 后端(cfc-backend)
+
+| 新增文件 | 说明 |
+|----------|------|
+| `entity/Organization.java` | 组织实体 |
+| `entity/OrgMember.java` | 组织成员实体 |
+| `mapper/OrganizationMapper.java` | MyBatis Mapper |
+| `mapper/OrgMemberMapper.java` | MyBatis Mapper |
+| `service/OrganizationService.java` | 组织业务逻辑 |
+| `service/OrgMemberService.java` | 组织成员业务逻辑 |
+| `service/OrgStatsService.java` | 统计大屏业务逻辑 |
+| `controller/admin/AdminOrgController.java` | 组织 CRUD 接口 |
+| `controller/admin/AdminOrgMemberController.java` | 成员管理接口 |
+| `controller/admin/AdminOrgStatsController.java` | 统计大屏接口 |
+
+| 修改文件 | 说明 |
+|----------|------|
+| `config/DatabaseInitializer.java` | 新增建表迁移 |
+| `resources/schema.sql` | 新增两张表的 CREATE TABLE 语句 |
+| `common/AdminRoles.java` | 新增 `org_admin` 到 `RESIDENT_ROLES`,添加 `isOrgAdmin()` 方法 |
+
+### 前端(cfc-web)
+
+| 新增文件 | 说明 |
+|----------|------|
+| `src/views/admin/org/List.vue` | 组织列表页 |
+| `src/views/admin/org/Form.vue` | 组织表单页 |
+| `src/views/admin/org/Detail.vue` | 组织详情页(成员管理) |
+| `src/views/admin/org/Dashboard.vue` | 统计大页面 |
+| `src/api/org.js` | API 封装 |
+
+| 修改文件 | 说明 |
+|----------|------|
+| `src/router/index.js` | 新增 4 条路由 |
+| `src/views/Layout.vue` | 新增菜单项 |
+
+---
+
+## 九、验收标准
+
+- [ ] `mvn clean compile` 编译通过
+- [ ] 平台角色可创建/编辑/停用组织,可见所有组织
+- [ ] 组织管理员登录后自动跳转至自己组织的 Dashboard
+- [ ] 组织管理员不可访问其他管理端接口(如 `/api/admin/users`)
+- [ ] 成员列表显示用户昵称/手机脱敏/类型/状态,可搜索和筛选
+- [ ] 添加成员后,可在其家庭/订单/任务统计中看到数据归集到该组织
+- [ ] 统计大屏各维度数据与后端 DB 查询结果一致
+- [ ] 创建组织的 API 响应包含组织信息和管理员账号信息
+- [ ] 移除成员后(status=inactive),该成员不再计入统计
+
+---
+
+## 十、边界与约束
+
+- **不引入新的登录体系**:成员复用现有 `users` 登录,仅通过 `org_members` 表建立归属关系
+- **不修改现有 family/guide 关系**:组织管理是独立的关系维度,不影响现有的家庭/规划师层级
+- **平台总览不含组织数据**:`/api/admin/stats/dashboard` 不做改动;组织管理员看到的大屏是其专属视图
+- **组织数据不导出到 C 端小程序**:大屏和管理功能仅限管理端(cfc-web)
+
+---
+
+## 十一、待确认事项
+
+无。所有设计决策已在讨论阶段确认。