diff --git a/docs/product-decisions.md b/docs/product-decisions.md new file mode 100644 index 00000000..386927dd --- /dev/null +++ b/docs/product-decisions.md @@ -0,0 +1,87 @@ +# 产品口径文档 + +> 来源:2026-03-25 产品需求梳理会话 +> 适用版本:R35 之后 + +--- + +## 请假模块 + +### L-1 团队日历可见性 +- `HR / Admin`(具备 `leave.view_all` + `leave.manage`):看全员 +- `部门经理`(具备 `leave.view_all`,仅限本部门):看本部门 +- 普通员工:不可见团队日历 Tab + +实现要点:前端 `canViewAll` 判断需区分"HR 全员视图"和"经理部门视图",查询时经理视图需传 `departmentId` 过滤。 + +### L-2 草稿与已驳回请假的编辑 +- `draft` 和 `rejected` 状态的请假支持原单编辑后再提交 +- 不要求"撤回再新建";直接在已有单据上修改字段后重新 submit +- 实现时需要 `leave.edit_own`(或直接在现有权限下放开)并在 submit 路由内允许此两种状态 + +### L-3 审批中请假的撤回 +- 申请人可主动撤回 `reviewing` 状态的请假,撤回后状态回 `draft` +- `approved` 后不允许直接撤回,需走销假/更正流程(后续另立需求) +- **当前状态**:撤回已实现,此条为确认口径,无需改代码 + +### L-4 `leave.approve` vs `leave.manage` +- `leave.approve`:仅表示"处理分配给自己的审批任务",不赋予查看全量的权利 +- `leave.manage`:HR/管理员运营权限,包括查看全量、人工纠偏/取消、余额与规则维护 +- `leave.manage` 不允许静默改写历史申请内容(需留审计痕迹) + +--- + +## 审批流 / 工作流 + +### W-1 无直接经理时的升级规则 +- 无直接经理 → 升级给 `CEO` +- `CEO` 也不可用 → 明确报错"未配置可审批人",阻断提交 +- 不自动通过,不静默跳过 + +### W-2 转审适用范围 +- 转审是通用审批能力,支持:报销、请假、采购、差旅 +- 条件:只能转给具备对应单据审批权限的人 +- 当前代码仅限报销,需移除 `entity_type !== "reimbursement"` 的硬限制 + +### W-3 转审次数上限 +- 上限保留 3 次,超过后拒绝继续转审 +- 超限后不自动转给固定角色;要求当前审批人自行处理或由管理员走代理机制 + +### W-4 并行会签 +- 当前阶段不做并行会签 +- 大额采购等双签场景,优先做串行多节点(两步顺序审批),不引入并行会签模型 + +--- + +## 通知渠道 + +### N-1 三渠道联动策略 +- 审批类高优先级事件默认三渠道并发:站内通知 + 企微 + 邮件 +- 当前不做用户级"关某渠道"配置 +- 后续通知量上来后再做订阅偏好管理 + +--- + +## Portal 首页 + +### P-1 经理视图判断逻辑 +- 现状:用 `system.users` 或 `report.dashboard.view` 判断,不准确 +- 口径:有任一**审批权限**(`*.approve`)或**域管理权限**(`*.manage` 非 `view_all`)的用户进入经理视图 +- 实现时建议提取 `isManagerRole(permissions)` 工具函数统一判断 + +--- + +## 权限模型 + +### R-1 `view_all` vs `manage` 语义定义 +- `view_all`:对应域全量数据只读可见 +- `manage`:域内管理与运营动作权限(如人工纠偏、配置维护、取消操作) +- `manage` 不是 `approve` 的别名,也不等于"可任意改历史数据" + +### R-2 报销/费用金额分层审批 +- 需按金额分层,但通过**审批规则配置**实现(工作流步骤条件),不通过拆 `manager/ceo` 权限组实现 +- 权限层面两个角色都保留 `expense.approve`,具体金额阈值在工作流定义里配置 + +### R-3 资产转移权限 +- `asset.transfer` 只给 `administration / 资产管理员` +- `finance_mgr` 有 `asset.manage` 但不拥有实物调拨权限,这是有意设计 diff --git a/server/src/constants/permissions.js b/server/src/constants/permissions.js index 90ab4b48..55e470d6 100644 --- a/server/src/constants/permissions.js +++ b/server/src/constants/permissions.js @@ -131,12 +131,9 @@ const ROLE_PERMISSIONS = { "asset.view_all", "report.dashboard.view", "project.view_all", + "project.manage", "budget.view", - "project.view_all", - "project.manage", "budget.manage", - "project.view_all", - "project.manage", ], ceo: [ ...EMPLOYEE_BASE_PERMISSIONS,