diff --git a/关心人功能-API接口文档.html b/关心人功能-API接口文档.html deleted file mode 100644 index e5554c3..0000000 --- a/关心人功能-API接口文档.html +++ /dev/null @@ -1,1144 +0,0 @@ - - -
- -userId
- 列表通过
- watcherUserIds
- 字段一并提交到现有的
- create-with-team
- 接口即可。后端自动给这些用户授予
- 产品/项目关心人
- 角色,让他们后续能在列表 / 详情看到这个对象(菜单按 watcher 角色权限渲染)。
- - "关心人"(watcher)是 - 对产品 / 项目本身长期感兴趣,但不参与交付 - 的人。典型场景: -
- -| 身份 | -角色 code | -能看什么 | -能做什么 | -
|---|---|---|---|
| 产品经理 / 项目负责人 | -
- product_manager
- /
- project_manager
- |
- 对象内全部 tab | -所有操作(分配任务、改预算、删对象等) | -
| 团队成员(开发 / 测试 / 协办等) | -各业务角色 | -对象内执行细节(任务、代码、文档等) | -跟自己角色 / 任务挂钩的写操作 | -
| 关心人 watcher | -
-
- product_watcher
- /
- project_watcher
-
- |
- 对象主要 tab(概览 / 进度 / 需求) | -只读 — 不参与交付 | -
visibility_config
- (粒度=方向 or 全局,由系统管理员配)
-
- 关心人记录最终落到
- rdms_user_object_role
- 表(与 member 同表,只是
- role_id
- 指向 watcher 角色)。系统按这个角色让用户进入"数据权限通道 1(自己参与)",跟普通成员路径一致 —— 区别只在
- 菜单 / 按钮粒度
- 由 watcher 角色绑定的权限决定。
-
- 建议 UI:第 2 步页面里在"团队成员"列表下方加一个独立区块" - 关心人(选填) - ",含一个用户多选控件。 -
- -┌─────────────────────────────────────────────────────────┐
-│ 第 2 步:维护初始团队 │
-├─────────────────────────────────────────────────────────┤
-│ │
-│ 团队成员 * │
-│ ┌────────────────────────────────────────────────────┐ │
-│ │ [+] 添加成员 │ │
-│ │ · 张三 产品经理 操作 ▾ │ │
-│ │ · 李四 开发 操作 ▾ │ │
-│ └────────────────────────────────────────────────────┘ │
-│ │
-│ 关心人(选填) │
-│ ┌────────────────────────────────────────────────────┐ │
-│ │ [多选用户] 王五 ╳ 赵六 ╳ │ │
-│ └────────────────────────────────────────────────────┘ │
-│ 提示:关心人将获得"产品/项目关心人"角色,能在列表和概览看到此对象, │
-│ 但不开放代码 / 任务 / 文档等执行细节。可与团队成员重叠。 │
-│ │
-│ [取消] [上一步] [完成] │
-└─────────────────────────────────────────────────────────┘
-
- - 点击"完成"时,按 - §4 - / - §5 - 的 ReqVO 结构组装: -
- -product
- /
- project
- 块 = 第 1 步表单
- members
- 块 = 第 2 步团队成员列表
- watcherUserIds
- = 第 2 步关心人多选控件的 userId 数组
-
- (可空 / 可省略字段)
- | 方法 | -路径 | -用途 | -本次是否新接口 | -
|---|---|---|---|
| POST | -/project/product/create-with-team |
- 创建产品(含初始团队 + 关心人) | -
- 已有接口;本次只是 ReqVO 多了
- watcherUserIds
- 字段
- |
-
| POST | -/project/project/create-with-team |
- 创建项目(含初始团队 + 关心人) | -
- 已有接口;本次只是 ReqVO 多了
- watcherUserIds
- 字段
- |
-
| GET | -
- /system/user/list-all-simple
- - (别名 - /system/user/simple-list
- )
- |
- 获取启用用户精简列表(前端选关心人下拉用) | -已有接口,无需任何改动 | -
- 事务性原子接口:产品基础资料 + 初始团队 + 关心人在同一事务内完成,任一步失败整体回滚。 -
- -
- @PreAuthorize("@ss.hasPermission('project:product:create')")
- — 创建产品权限码
-
ProductCreateWithTeamReqVO
- )
- {
- "product": {
- "code": "CNPD2026001",
- "directionCode": "system",
- "name": "RDMS 产品平台",
- "managerUserId": 1024,
- "description": "面向研发管理的一体化产品"
- },
- "members": [
- { "userId": 1024, "roleId": 3100000002001, "remark": "产品经理本人" },
- { "userId": 1025, "roleId": 3100000002002, "remark": "开发" }
- ],
- "watcherUserIds": [2001, 2002]
-}
-
- | 路径 | -类型 | -必填 | -说明 | -
|---|---|---|---|
product |
- object | -必填 | -产品基础资料,结构见下 | -
product.code |
- string ≤ 64 | -选填 | -产品编码;为空时由后端按规则生成 | -
product.directionCode |
- string ≤ 32 | -必填 | -
- 产品方向字典值(字典类型
- object_direction
- )
- |
-
product.name |
- string ≤ 128 | -必填 | -产品名称 | -
product.managerUserId |
- Long | -必填 | -
- 产品经理 user_id;必须在
- members
- 列表里有对应的产品经理角色记录
- |
-
product.description |
- string | -选填 | -产品描述 | -
members |
- array<object> | -必填 | -
- 初始团队,
-
- 必须包含 userId == product.managerUserId 且 roleId 是
- product_manager
- 的记录
-
- ;后端不会自动追加经理
- |
-
members[].userId |
- Long | -必填 | -成员 user_id | -
members[].roleId |
- Long | -必填 | -
- 对象域角色 ID(
- scope_type='object'
- ,
- object_type='product'
- );前端用 role code 反查得到(如
- product_manager
- )
- |
-
members[].remark |
- string ≤ 500 | -选填 | -成员备注 | -
- watcherUserIds
- |
- array<Long> | -选填 | -- 关心人 user_id 数组 - 。允许为空 / 省略字段 / 与 members 重叠;后端按 (user, object, role) 三元组写入,重复跳过 / INACTIVE - 复活;后端会自动去 null 去重 - | -
{
- "code": 0,
- "data": 30001, // 新创建的 productId
- "msg": ""
-}
-
- | 错误码 / 信息 | -触发条件 | -
|---|---|
产品基础资料不能为空 |
-
- product
- 字段缺失
- |
-
初始团队成员不能为空 |
-
- members
- 空数组或缺失
- |
-
产品经理不能为空 |
-
- product.managerUserId
- 缺失
- |
-
产品方向不能为空 |
-
- product.directionCode
- 缺失
- |
-
PRODUCT_MEMBER_ALREADY_EXISTS |
-
- members
- 里同 user 同 role 重复(multi-role 唯一索引拦截)
- |
-
PRODUCT_INTERNAL_ROLE_NOT_CONFIGURED |
-
- 后端启动校验通过但运行时找不到
- product_watcher
- 角色(理论上不会发生 — 启动校验会拦)
- |
-
- 事务性原子接口:项目基础资料 + 初始团队 + 关心人在同一事务内完成,任一步失败整体回滚。 -
- -
- @PreAuthorize("@ss.hasPermission('project:project:create')")
- — 创建项目权限码
-
ProjectCreateWithTeamReqVO
- )
- {
- "project": {
- "projectCode": "CNPJ2026001",
- "projectName": "客户交付项目 A",
- "projectType": "delivery",
- "directionCode": "system",
- "productId": 30001,
- "managerUserId": 1024,
- "plannedStartDate": "2026-06-01",
- "plannedEndDate": "2026-09-30",
- "projectDesc": "为客户 XX 定制交付"
- },
- "members": [
- { "userId": 1024, "roleId": 3100000003001, "remark": "项目负责人本人" },
- { "userId": 1030, "roleId": 3100000003002, "remark": "前端开发" }
- ],
- "watcherUserIds": [2001, 2002]
-}
-
- | 路径 | -类型 | -必填 | -说明 | -
|---|---|---|---|
project |
- object | -必填 | -
- 项目基础资料;新建场景不传
- actualStartDate
- /
- actualEndDate
- (实际日期由执行阶段才有值)
- |
-
project.projectCode |
- string ≤ 64 | -选填 | -项目编码;为空时由后端按规则生成 | -
project.projectName |
- string ≤ 200 | -必填 | -项目名称 | -
project.projectType |
- string ≤ 32 | -必填 | -项目类型字典值 | -
project.directionCode |
- string | -条件必填 | -- 项目方向; - 未选产品时必填;选了产品则后端按产品方向覆盖 - ,前端可不传 - | -
project.productId |
- Long | -选填 | -所属产品 ID;不选表示无产品归属 | -
project.managerUserId |
- Long | -必填 | -
- 项目负责人 user_id;同产品规则,必须在
- members
- 里出现且对应负责人角色
- |
-
- project.plannedStartDate
- /
- plannedEndDate
- |
-
- date
- YYYY-MM-DD
- |
- 选填 | -计划日期 | -
project.projectDesc |
- string ≤ 4000 | -选填 | -项目说明 | -
members |
- array<object> | -必填 | -
- 结构同
- ProjectMemberSaveReqVO
- ,与产品对称。必须包含 userId == project.managerUserId 且 roleId 为
- project_manager
- 的记录
- |
-
members[].userId |
- Long | -必填 | -成员 user_id | -
members[].roleId |
- Long | -必填 | -
- 对象域角色 ID(
- scope_type='object'
- ,
- object_type='project'
- )
- |
-
members[].remark |
- string ≤ 500 | -选填 | -成员备注 | -
- watcherUserIds
- |
- array<Long> | -选填 | -- 关心人 user_id 数组 - 。规则与产品端一致:允许空 / 省略 / 与 members 重叠;后端去 null 去重,按三元组幂等写入 - | -
{
- "code": 0,
- "data": 40001, // 新创建的 projectId
- "msg": ""
-}
-
- | 错误码 / 信息 | -触发条件 | -
|---|---|
项目基础资料不能为空 |
-
- project
- 字段缺失
- |
-
项目名称不能为空 |
-
- project.projectName
- 缺失
- |
-
项目负责人不能为空 |
-
- project.managerUserId
- 缺失
- |
-
初始团队成员不能为空 |
-
- members
- 空
- |
-
PROJECT_MEMBER_ALREADY_EXISTS |
-
- members
- 里同 user 同 role 重复
- |
-
PROJECT_INTERNAL_ROLE_NOT_CONFIGURED |
-
- 后端运行时找不到
- project_watcher
- 角色(理论上不会发生)
- |
-
- 获取所有
- 已启用
- 用户的精简信息,用于前端下拉 / 多选控件。也可访问别名
- /system/user/simple-list
- 。
-
登录态即可(无显式权限码限制)。
- -无参数。
- -List<UserSimpleRespVO>
- )
- {
- "code": 0,
- "data": [
- { "id": 1024, "nickname": "张三" },
- { "id": 1025, "nickname": "李四" },
- { "id": 2001, "nickname": "王五" }
- ],
- "msg": ""
-}
-
- GET /system/user/page
- 走分页查询;或者拉一次全量后在前端做 search filter。
-
- 可以。多角色合法,会落两条
- rdms_user_object_role
- 记录(一条 member 角色 + 一条 watcher 角色),数据权限
- 取并集
- 。这种情况通常不会出现 —— 已经在团队里的人不需要再设为 watcher —— 但允许重叠不报错,前端不需要做"过滤已在
- members 里的 user"的校验,让后端兜底。
-
- 当前
- create-with-team 是唯一的批量入口
- 。创建后维护 watcher 的接口暂未单独提供 —— 如果业务后续需要"在产品 /
- 项目编辑页面再加关心人",需要再拉一条接口(沿用现有的
- add member
- /
- remove member
- 模式即可,roleId 传 watcher 角色 ID)。
-
- 取决于业务侧给
- product_watcher
- /
- project_watcher
- 角色在权限管理界面绑了哪些菜单(对象域菜单
- system_menu.scope_type='object'
- )。建议粒度:
-
product_manager
- /
- project_manager
- — 负责人
- product_creator
- /
- project_creator
- — 创建者(非负责人)
- product_watcher
- /
- project_watcher
-
- —
- 关心人
- implicit_observer_product
- /
- implicit_observer_project
- — 隐式只读 observer(不会出现在 members 列表里,后端运行时兜底返回)
-
- 完全等价于传空数组。
- watcherUserIds
- 是可选字段 —— 不写 / 写 null / 写
- []
- 都不会落任何 watcher 记录,接口正常完成。
-
- 当前没有上限校验。从产品语义看,关心人本来就是"少量长期看的人",前端可以加个软性提示(如超过 20 - 人时提示考虑用方向级 visibility_config 配置),但不阻塞提交。 -
- -- 看不到。工时是敏感数据,按对象内身份控制:协办人只看自己填报的工时;任务/项目负责人可看团队成员工时。 - watcher 既不是协办人也不是负责人,工时列表对其不可见 - 。 -
- -| 维度 | -关心人 watcher | -用户可见性配置 visibility_config | -
|---|---|---|
| 粒度 | -单个产品 / 项目 | -整个方向 or 全局(all / directions) | -
| 谁来加 | -产品 / 项目创建人在新建表单里加 | -系统管理员在用户管理 / 可见性配置页加 | -
| 典型场景 | -外部顾问盯几个产品 / 长期评审人 | -跨方向工程师看一片方向的所有产品 / 技术支持组协调全部 | -
| 底层存储 | -
- rdms_user_object_role
- (一条对象成员记录)
- |
-
- system_user_visibility_config
- (一条用户级配置)
- |
-
GET /system/user/list-all-simple
- watcherUserIds: number[]
- ,可空 / 可省略
- additionalRoleNames: string[]
- 字段返回。前端只需要把这个数组拼到角色名旁边显示即可。
-
- 多角色改造后,
-
- 产品/项目的"创建者"角色会自动落一条
- rdms_user_object_role
- 行
-
- 。当
- 创建者本人就是负责人
- 时,同一用户在同一对象内会出现两条 ACTIVE 记录:
-
product_manager
- /
- project_manager
- product_creator
- /
- project_creator
- - 如果后端原样返回,前端列表会出现"同一个人重复两行"。讨论后约定:后端在 - 列表接口 - 层做合并展示, - 不影响 - 底层数据(每个角色行仍独立存在,便于后续可能的"按角色单独操作")。 -
- -creator + manager
- 这一种组合
-
- 会让同人多角色出现。其他角色(产品专员、开发等)仍是一人一角色。所以前端可以放心按"主角色 + 附加角色名"
- 的方式渲染,附加列表通常是 0 或 1 个元素。
- /admin-api/project/product/{productId}/members
- 产品团队成员列表
-/admin-api/project/project/{projectId}/members
- 项目团队成员列表
-
- 响应结构两个接口对称,本文档下文统一用
- RespVO
- 表示,字段路径一致。
-
- 假设:产品 P 里
- 用户A
- 是产品经理(同时创建了该产品,所以也有
- product_creator
- 角色),
- 用户B
- 是产品专员,
- 用户C
- 是已退场的历史成员。
-
[
- { id: "100", userId: "A", roleCode: "product_manager",
- roleName: "产品经理", status: 0, ... },
- { id: "101", userId: "A", roleCode: "product_creator",
- roleName: "产品创建者", status: 0, ... },
- { id: "102", userId: "B", roleCode: "product_specialist",
- roleName: "产品专员", status: 0, ... },
- { id: "103", userId: "C", roleCode: "product_specialist",
- roleName: "产品专员", status: 1, leftTime: "..." }
-]
- 用户 A 出现 2 次 — 前端要么重复显示,要么自己去重。
-[
- { id: "100", userId: "A", roleCode: "product_manager",
- roleName: "产品经理",
- additionalRoleNames: ["产品创建者"], // ← 新增字段
- status: 0, ... },
- { id: "102", userId: "B", roleCode: "product_specialist",
- roleName: "产品专员",
- additionalRoleNames: [],
- status: 0, ... },
- { id: "103", userId: "C", roleCode: "product_specialist",
- roleName: "产品专员",
- additionalRoleNames: [],
- status: 1, leftTime: "..." }
-]
-
- 用户 A 1 行 — 主行 manager,creator 名字进
- additionalRoleNames
- 。
-
| 规则 | -说明 | -
|---|---|
| 仅合并 ACTIVE 行 | -
- status = 0
- 的多角色行才聚合;
- status = 1
- 的历史 INACTIVE 行
- 保持每条独立成行
- (历史角色留痕,便于审计)
- |
-
| 主角色选择 | -
- 同人多角色时,
- product_manager
- /
- project_manager
- 角色行优先做主;不在则按
- roleId
- 升序选第一条(理论不该走到这条兜底)
- |
-
| 主行字段 | -
- id
- /
- roleId
- /
- roleCode
- /
- roleName
- /
- joinedTime
- /
- leftTime
- /
- remark
- 等都按主角色行的值返回
- |
-
| 非主角色名顺序 | -
- additionalRoleNames
- 按角色中文名字典序升序,前端可以直接顺序渲染
- |
-
additionalRoleNames
- | 字段名 | -类型 | -状态 | -说明 | -
|---|---|---|---|
additionalRoleNames |
- string[] |
- 本次新增 | -
- 非主角色的中文名列表,多角色场景使用;
-
- 单角色时为空数组
- []
-
- ,前端可以放心
- length
- 判空
- |
-
- 所有
- 原有字段保持不变
- (
- id
- 、
- userId
- 、
- userNickname
- 、
- roleId
- 、
- roleName
- 、
- roleCode
- 、
- managerFlag
- 、
- status
- 、
- joinedTime
- 、
- leftTime
- 、
- remark
- ),前端原有代码不会因为字段消失而报错。
-
const displayRoleName = additionalRoleNames?.length
- ? `${roleName} + ${additionalRoleNames.join(', ')}`
- : roleName;
-//
-// 例:roleName="产品经理", additionalRoleNames=["产品创建者"]
-// → "产品经理 + 产品创建者"
-//
-// 例:roleName="产品专员", additionalRoleNames=[]
-// → "产品专员"
-
- <span class="role-main">{{ roleName }}</span>
-<span v-for="extra in additionalRoleNames" :key="extra" class="role-tag">
- {{ extra }}
-</span>
-//
-// CSS:role-tag 设计成浅色 background + 小圆角,跟主角色拉开视觉层级
-
- | 用户 | 角色 | 状态 |
-|-----------|---------------------------|------|
-| 灿能管理 | 产品经理 [产品创建者] | 有效 |
-| 洪圣文 | 产品专员 | 有效 |
-| 李凡 | 游客 | 历史 |
-
-
-
- | 场景 | -预期返回 | -前端展示 | -
|---|---|---|
| 用户 A 仅是产品经理(不是创建者) | -
- 1 行,
- additionalRoleNames=[]
- |
- "产品经理" | -
| 用户 A 同时是产品经理 + 创建者 | -
- 1 行(主行 manager),
- additionalRoleNames=["产品创建者"]
- |
- "产品经理 + 产品创建者" | -
| 用户 A 仅是创建者(罕见,理论上创建后立即把 manager 转给别人才会出现) | -
- 1 行,主行就是 creator,
- additionalRoleNames=[]
- |
- "产品创建者" | -
| 用户 A 是产品专员(单角色非 manager) | -
- 1 行,
- additionalRoleNames=[]
- |
- "产品专员" | -
| 用户 A 退场(status=1 INACTIVE 历史行) | -
- 每条 INACTIVE 行独立 1 行,
- additionalRoleNames=[]
- |
- "产品专员(已退场)"等灰显 | -
| - 用户 A 同时有 - 历史失效 - 的角色行 + - 当前生效 - 的角色行 - | -ACTIVE 行合并 1 行 + 每条 INACTIVE 行各占 1 行;同用户在列表里会出现多次(不同 status) | -分别用"有效 / 历史"区分;不要再二次合并 | -
- 以下接口 - 不变 - ,前端原有调用方式保持: -
- -| 接口 | -说明 | -
|---|---|
- POST /admin-api/project/product/{productId}/members
- - POST /admin-api/project/project/{projectId}/members
- |
-
- 新增成员 — 仍按"一个角色一条记录"操作,传
- userId + roleId
- |
-
PUT /admin-api/project/.../members/{memberId} |
-
- 更新成员 — 按
- memberId
- (即
- rdms_user_object_role.id
- )定位具体角色行操作
- |
-
PUT /admin-api/project/.../members/{memberId}/inactive |
-
- 失效成员 — 同上,按
- memberId
- 操作
- |
-
- GET /admin-api/project/product/{productId}/context
- - GET /admin-api/project/project/{projectId}/context
- |
-
- 对象上下文 —
- currentRole.additionalRoleNames
- 字段早已存在,
- 不在本次变更范围
- |
-
memberId
- 是
-
- 主角色行的
- id
-
- (也就是 manager 那条)。
- 不会影响
- 同人的 creator 角色行 — creator 角色仍保留。
- id
- ),后续
- 是否要单独提供"列出某 user 所有角色行"接口
- 取决于业务实际诉求,目前没有这个接口。
- additionalRoleNames
- 数组加到 TypeScript 类型定义(ProductMemberRespVO / ProjectMemberRespVO 两处)
- additionalRoleNames
- 拼到
- roleName
- 旁边显示(字符串或 chip 标签均可)
- additionalRoleNames
- 应该是
- []
- ,不影响展示
- status=1
- ),仍按原方式各占一行
- memberId
- 操作主角色行;若业务需要"踢人整体",后端再补接口
-
- 本次后端改动仅在
- ProductMemberServiceImpl.getProductMemberList
- 和
- ProjectMemberServiceImpl.getProjectMemberList
- 两个方法中实现,
- 不修改底层数据
- (
- rdms_user_object_role
- 仍按一行一角色存储)。即使前端暂时不读
- additionalRoleNames
- 字段,也只是看不到"+ 产品创建者"字样,不会出现数据错误或重复行问题。
-