# Phase 1: 企业级能力补齐 — 通知系统 / RBAC 权限 / 多层级 OKR 拆解 日期:2026-05-13 状态:设计完成,待进入实现计划 --- ## 背景 当前系统(医梦AI OKR绩效考核系统)已具备单人 OKR/KPI 双轨评分闭环,但与字节跳动飞书 OKR、Google OKR 等企业级系统相比,缺少 3 项企业上线必须补齐的能力:消息通知、多角色权限、多层级 OKR 拆解与对齐。 本设计覆盖方案 A 的 Phase 1 全部内容。 --- ## 模块一:消息通知系统 ### 目标 建立统一的"事件 → 通知 → 推送"管道,覆盖 7 类关键业务事件。 ### 数据模型 ```sql CREATE TABLE notification ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, type VARCHAR(32) NOT NULL, title VARCHAR(256) NOT NULL, content TEXT, ref_type VARCHAR(32), ref_id INTEGER, is_read INTEGER DEFAULT 0, read_at TEXT, created_at TEXT NOT NULL ); ``` `type` 枚举: `OKR_REVIEW` / `OKR_REVIEWED` / `SCORE_CONFIRM` / `SCORE_CONFIRMED` / `PERIOD_DEADLINE` / `KR_LAGGING` / `FEEDBACK_NOTIFY` `ref_type` 枚举: `period` / `objective` / `score` / `feedback` ### 触发点 | 事件 | 接收人 | 触发时机 | |------|--------|---------| | OKR_REVIEW | 上级 | 下级提交 OKR | | OKR_REVIEWED | 下级 | 上级审核 OKR(通过/驳回) | | SCORE_CONFIRM | 下级 | 上级完成评分 | | SCORE_CONFIRMED | 上级 | 下级确认评分 | | PERIOD_DEADLINE | 周期内全员 | 周期结束前 3 天(由 PeriodScheduler 触发) | | KR_LAGGING | OKR 负责人 | KR 进度落后于时间线(每日检查) | | FEEDBACK_NOTIFY | 下级 | 上级发起/更新面谈记录 | ### 后端架构 - 定义 `NotificationEvent` 事件类,各 Service 在关键动作完成后通过 `ApplicationEventPublisher.publishEvent()` 发布 - `NotificationListener`(`@Async` + `@EventListener`)异步消费事件,写入 `notification` 表 - REST 端点: - `GET /api/notifications/unread-count` — 未读数(前端 60s 轮询) - `GET /api/notifications?page=&size=` — 通知分页列表 - `PUT /api/notifications/{id}/read` — 标记已读 - `PUT /api/notifications/read-all` — 全部已读 ### 前端 - 顶部导航栏右侧新增铃铛图标 + 红色未读角标 - 点击展开下拉面板(最近 20 条),点击条目跳转到关联页面并标记已读 - 通知列表页(`/notifications`):分页、已读/未读筛选、类型筛选 --- ## 模块二:RBAC 权限体系 ### 目标 从"SUPER_ADMIN + 上下级树推导"升级到 5 级标准角色 + 声明式权限 + 数据范围控制。 ### 角色定义 | 角色 | 权限范围 | 授予对象 | |------|---------|---------| | `SUPER_ADMIN` | 全局 | 系统管理员 | | `HR_ADMIN` | 全部人员数据 + 考核配置 + 报表 | HRBP | | `DEPT_LEADER` | 本部门及下级部门 + 评分审批 | 部门负责人 | | `TEAM_LEADER` | 直属下级 | 团队主管 | | `EMPLOYEE` | 仅自己 | 普通员工 | ### 数据库变更 ```sql -- role 字段已有 VARCHAR(20),值域扩展为上述 5 种 -- 新增数据范围字段 ALTER TABLE sys_user ADD COLUMN scopes TEXT DEFAULT '[]'; ``` `scopes` 为 JSON 数组,格式: `["dept:3", "dept:5"]`,表示该角色可见的部门范围。`DEPT_LEADER` 自动获得本部门 scope。 ### 权限矩阵 | API 操作 | SUPER_ADMIN | HR_ADMIN | DEPT_LEADER | TEAM_LEADER | EMPLOYEE | |----------|:-----------:|:--------:|:-----------:|:-----------:|:--------:| | 组织管理 CRUD | Y | Y | N | N | N | | 考核周期管理 | Y | Y | N | N | N | | 查看本部门全部 OKR | Y | Y | Y | N | N | | 查看下级 OKR | Y | Y | Y | Y | N | | 打分下级 | Y | Y | Y | Y | N | | 自己的 OKR/分数 | Y | Y | Y | Y | Y | | 导出报表 | Y | Y | Y | N | N | | 操作日志 | Y | Y | N | N | N | ### 后端实现 - 新增 `@RequireRole` 注解: ```java @RequireRole({UserRole.SUPER_ADMIN, UserRole.HR_ADMIN}) ``` - AOP 切面 `RoleAspect` 在 Controller 方法执行前校验角色,无权限返回 403 - `SecurityUtils` 新增方法: - `hasRole(UserRole role)` — 角色判断 - `getDataScopes()` — 获取当前用户数据范围 - `hasSubordinate(Long userId)` — 保留现有上下级树逻辑 - 数据范围过滤:Mapper 层查询时拼接 `AND (dept_id IN (?) OR user_id = ?)` 条件 ### 前端 - 组织管理页用户列表增加角色选择器(仅 SUPER_ADMIN / HR_ADMIN 可见和操作) - 侧边栏菜单项根据角色显示/隐藏: - 组织架构:SUPER_ADMIN / HR_ADMIN - 绩效考核模板:SUPER_ADMIN / HR_ADMIN - 考核维度配置:SUPER_ADMIN / HR_ADMIN - 操作日志:SUPER_ADMIN / HR_ADMIN --- ## 模块三:多层级 OKR 拆解与对齐 ### 目标 支持四层 OKR(公司 → 部门 → 团队 → 个人)的逐级拆解与对齐,新增对齐可视化视图。 ### 数据模型变更 ```sql ALTER TABLE okr_objective ADD COLUMN level VARCHAR(16) NOT NULL DEFAULT 'INDIVIDUAL'; ALTER TABLE okr_objective ADD COLUMN parent_objective_id INTEGER DEFAULT NULL; ALTER TABLE okr_objective ADD COLUMN sort_order INTEGER DEFAULT 0; ALTER TABLE okr_objective ADD COLUMN progress REAL DEFAULT 0; ``` `level` 取值: `COMPANY` / `DEPARTMENT` / `TEAM` / `INDIVIDUAL` ### 层级规则 | 层级 | 创建权限 | 可视范围 | 每周期建议数量 | |------|---------|---------|:---:| | COMPANY | SUPER_ADMIN / HR_ADMIN | 全员 | 3-5 | | DEPARTMENT | DEPT_LEADER / HR_ADMIN | 本部门及下级 | 3-5 | | TEAM | TEAM_LEADER | 本团队 | 1-3 | | INDIVIDUAL | 本人 | 汇报链内 | 3-5 | ### 对齐流程 ``` 周期 DRAFT → OKR_ALIGN 阶段: 1. 管理员创建 COMPANY 级 O + KR(全员可见,作为对齐参照) 2. DEPT_LEADER 创建部门 O,选择对齐到某一公司 O 3. 员工创建个人 O,对齐到上级 O 或公司 O 4. 上级审核对齐关系,标记孤立/错位目标 ``` ### 进度汇总 - **KR → O**: Σ(KR.current / KR.target × KR.weight) / Σ(KR.weight),百分制 - **下级 O → 上级 O**: 等权平均 - 触发时机:KR 进度更新时重算关联 O 的 progress ### 新增 API | 端点 | 说明 | |------|------| | `GET /api/okr/period/{periodId}/tree` | OKR 对齐树(全层级) | | `GET /api/okr/period/{periodId}/orphans` | 未对齐的个人 OKR | | `POST /api/okr/{id}/align` | 设置/修改 parent_objective_id | | `GET /api/okr/{id}/children` | 获取对齐到该目标的下级 O | ### 前端 - **OKR 对齐视图**(`/okr/alignment?periodId=X`): - 左侧树形面板:el-tree 组件,四级展开/折叠,节点显示 O 标题 + 进度条 - 右侧详情面板:选中节点后展示该 O 的 KR 列表、子目标列表、对齐链路 - 孤立目标警告:未对齐的个人 O 在树中置灰并显示警告图标 --- ## 通用约束 - 所有表使用 SQLite 兼容语法,不使用存储过程或触发器等不可移植特性 - 前端路由在 `MainLayout.vue` 子路由中注册,侧边栏自动展示 - 通知轮询间隔:60 秒 - 仅 SUPER_ADMIN 可修改他人角色和 scopes --- ## 不变更 - 现有单 JAR 部署方式不变 - 现有 OKR/KPI 双轨评分逻辑不变 - 现有周期状态机不变(DRAFT → OKR_ALIGN → EXECUTING → ASSESSING → ARCHIVED) - 现有审计修正留痕机制不变 - 现有前端技术栈不变(Vue 3 + Element Plus)