# 个人 OKR 与执行进度可视化设计 ## 目标 修复“我的 OKR”和“执行进度”无法稳定继承当前周期、执行进度页在缺少 `periodId` 时完全不调用接口的问题,并按 Open Design 参考图实现个人 OKR 的核心进度可视化。 ## 范围边界 - “我的 OKR”和“执行进度”只展示当前登录人的全部 Objective 与 KR。 - 团队成员的 OKR 和执行进度继续从“团队 OKR”进入,不混入个人执行页。 - `admin` 等没有参与周期或没有个人 OKR 的系统账号显示明确空态,不伪造演示数据。 - 不改变现有 OKR 创建、审核、进度更新和团队查看权限模型。 ## 根因 1. 侧边栏使用固定路径 `/okr/my` 与 `/okr/execution`,没有携带顶部当前周期。 2. `OkrExecutionView.fetchData()` 仅在 `route.query.periodId` 存在时请求数据;缺少参数时直接结束,所以没有网络请求。 3. “我的 OKR”自行选择周期,与工作台顶部当前周期不是同一数据源,并把请求异常转换为空数组。 4. 执行图受 `timelineItems.length` 控制,数据链路未启动时整个核心区域消失。 5. 当前 execution-timeline 后端会混入直属下属 OKR,不符合已确认的个人页面范围。 ## 数据流设计 1. `workspace.periodId` 是当前周期的唯一来源,URL 查询参数是可分享、可刷新恢复的外部表示。 2. 侧边栏导航到周期相关页面时自动附加当前 `periodId`。 3. 页面优先读取 URL `periodId`;缺失时等待工作台加载推荐周期并补写 URL,然后加载数据。 4. 周期切换后页面监听 `periodId` 变化并重新请求,防止只在 `onMounted` 调用一次。 5. “我的 OKR”调用 `getMyOkrSet(periodId)`;“执行进度”调用 `getMyOkrSet(periodId)` 和个人版 `execution-timeline`。 6. 页面分别呈现加载、接口错误、未选周期、当前账号无 OKR 四种状态,不再静默吞错。 ## 接口设计 - 保留 `GET /api/okr/period/{periodId}/my-set`,返回当前用户的全部 Objective。 - 调整 `GET /api/okr/period/{periodId}/execution-timeline` 为仅返回当前用户的 KR 时间线。 - 时间线每条 KR 至少返回:Objective 信息、KR 标识与标题、当前值、目标值、单位、状态、开始日期、截止日期、进度更新历史。 - 前端统一使用 `src/api/index.js` 的 `okrApi`,避免两个 axios 客户端造成返回结构认知不一致。 ## 页面设计 ### 我的 OKR - 按 Objective 分组展示,支持多个目标。 - Objective 卡片使用医梦深紫主边和浅青强调边,标题、说明、权重建立清晰层级。 - 每条 KR 显示编号、标题、当前值、目标值、单位、状态与横向进度条。 - 延迟或阻塞使用危险色,正常执行使用深紫或浅青;不使用深色容器嵌套浅色容器。 ### 执行进度 - 顶部显示当前周期及整体完成度摘要。 - 主视图按 Objective 渲染复杂进度卡片,与参考图保持一致的信息密度和布局:Objective 标题与权重、KR 行、当前值、目标值、状态标签、彩色进度条。 - 每条 KR 提供“更新进度”入口,沿用现有 `newValue/status/remark` 契约。 - 第二层时间线展示计划区间、历史更新节点和阻塞/延期标记;没有历史记录时仍显示计划区间和当前进度,不隐藏整个视图。 ## 测试与验收 - 前端契约测试:无 URL 周期时使用 workspace 周期;周期变化会重新加载;个人页调用 `getMyOkrSet` 与 `getExecutionTimeline`。 - API 客户端测试:返回结构统一解包。 - 后端服务测试:execution-timeline 不包含直属下属,只包含当前用户全部 Objective 的 KR。 - 集成测试:有 OKR 的用户返回非空 Objective 和时间线;无 OKR 的用户返回空集合而非异常。 - 浏览器验收:桌面端与用户截图并排比较,验证 Objective 卡片、KR 进度条、状态颜色、排版与更新入口;同时检查移动端无横向溢出。