# 看板 KPI 卡片三层递进模式 (2026-08-09)

## 改造背景

旧版看板顶部 3 张 KPI 卡片：年度目标（含环形图）+ 本月 vs 上月 + 半年度进度。
"半年度进度"卡片冗余（与年度卡片环形图重复），且缺少季度维度。

## 新布局：当月 → 当季 → 当年

```
┌─────────────────┬─────────────────┬─────────────────┐
│ 📅 8月 当月进展   │ 📊 Q3 当季(7-9月) │ 🎯 年度目标 6950万│
│ 115.7万          │ 469.3万          │ 2631万           │
│ 目标717.9万 16.1%│ Q3目标2027万 23.2%│ 累计·年化3946万   │
│ ██░░░░░░ 16.1%  │ ███░░░░░ 23.2%   │    ╭───╮        │
│ 环比7月 -67.3%   │ Q3剩余 1557.7万   │    │37.9%│       │
└─────────────────┴─────────────────┴─────────────────┘
```

## 数据源

- `kpi_dashboard.json`: `total_target`, `total_h1`, `total_h1_h2`, `depts[].h2_months`（部门级月度目标）
- `three_year_monthly.json`: `["2026"]["7"]` ~ `["8"]`（月度实际）
- `kpi_progress.json`: `total`（当月 MCP 备选值）

## 改造点

### 1. `getKPI()` 新增计算字段

```javascript
// admin 分支：
var h2TargetsArr = [0,0,0,0,0,0];
(dash.depts||[]).forEach(function(dp) { (dp.h2_months||[]).forEach(function(v,i) { h2TargetsArr[i]+=v||0; }); });
var curMon = new Date().getMonth() + 1;
var h2Idx = Math.max(0, curMon - 7); // 0-based Jul=0
var monthActual = h2Actuals[h2Idx] || current || 0;
var monthTarget = h2TargetsArr[h2Idx] || 0;
var q3Target = h2TargetsArr[0] + h2TargetsArr[1] + h2TargetsArr[2];
var q3Actual = h2Actuals[0] + h2Actuals[1] + h2Actuals[2];

return { ..., monthTarget, monthActual, q3Target, q3Actual };

// h2Actuals 从 threeYearMonthly 读取（不只是 [current,0,0,0,0,0]）
var tym = d.threeYearMonthly || {};
var t2026 = tym['2026'] || {};
var h2Actuals = [t2026['7']||0, t2026['8']||0, ...];
```

### 2. `renderDashboard()` 新卡片渲染

使用内联 progress bar（`<div style="height:6px;...">`）替代复杂的 CSS 类。
环形图保留在年度卡片中（`donut-wrap`）。

## 适用范围

- `工具/app.html`（主要工作台，飞书内打开）
- `工具/index.html`（旧版入口，非主力）
