# 周报收入趋势图 · 交接说明

线上地址（Cloudflare Pages）：https://weekly-revenue-chart-5sn.pages.dev

> 本次更新（2026-07-14）：新增 **Group ⑧ 直营新签年费达成子弹图**（人效双目标线 + 序时进度重定义），详见第六节。

## 目录结构

```
周报交接包/
├── README.md                     # 本说明
├── data/                         # 数据源（每周更新的两个 xlsx）
│   ├── 周报数据测试.xlsx           # 主收入表（收入类型 × 团队 × 行业，含子弹图底数）
│   └── 类目收入数据.xlsx           # 类目明细（一级/二级类目）
├── skill/                        # 生成脚本与技能定义
│   ├── weekly_revenue_chart.py   # 趋势图主脚本
│   ├── SKILL.md                  # 趋势图 Skill 元数据
│   ├── 项目agents.md              # 工作区 AGENTS.md
│   ├── echarts-5.5.0.min.js      # ECharts 离线库（用于内联到 HTML）
│   └── bullet-chart/             # 子弹图 Skill（规格定义）
│       └── SKILL.md              # 子弹图视觉规格、数据结构、计算逻辑
└── output/                       # 最新一次生成结果
    ├── 周报趋势图_汇总.html         # 自包含离线 HTML（~1.2MB，内联 ECharts）
    └── 子弹图.html                 # 收入达成子弹图（自包含 HTML，~24KB）
```

## 一、周更流程（每周需要做的事）

### 1. 更新数据源
把最新一周的两个 xlsx 覆盖 data/ 目录：
- 周报数据测试.xlsx：主收入表（顶层指标 SQL 导出），需包含 `目标&达成`、`直营新签人效达成--子弹图底数` 等页签
- 类目收入数据.xlsx：类目明细

### 2. 生成 HTML（一步到位，默认内联 ECharts 离线可用）
```bash
cd data/
python3 ../skill/weekly_revenue_chart.py \
  --file "周报数据测试.xlsx" \
  --output-dir "." \
  --category-file "类目收入数据.xlsx"
```

产出约 1.2MB 自包含 HTML（`周报趋势图_汇总.html`），双击浏览器可直接看。

参数说明：
- 默认内联 ECharts（离线可用）；加 `--cdn` 则走 CDN，用于快速验证。
- 依赖：python3.10+、openpyxl。

### 3.（可选）手动内联 ECharts
若用 `--cdn` 生成的 HTML 需要转为离线版，用下面的 Python 片段替换（重要：不要用 re.sub，min.js 里的 \d 会触发 bad escape 错误）：

```python
html_path = 'data/周报趋势图_汇总.html'
ec_path = 'skill/echarts-5.5.0.min.js'
with open(html_path) as f: html = f.read()
with open(ec_path) as f: ec = f.read()
needle = '<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>'
idx = html.find(needle)
new_html = html[:idx] + '<script>' + ec + '</script>' + html[idx+len(needle):]
with open(html_path, 'w') as f: f.write(new_html)
```

## 二、部署到 Cloudflare Pages

现有部署信息：
- 账号邮箱：hww924316452@gmail.com
- Cloudflare Account ID：d76ef4fce2e044eb854317e8f1fa6eb6
- Pages 项目名：weekly-revenue-chart
- 固定域名：https://weekly-revenue-chart-5sn.pages.dev

首次配置：npx wrangler@latest login（浏览器扫码登录）。

发布：
```bash
mkdir -p /tmp/cf-weekly-deploy
cp output/周报趋势图_汇总.html /tmp/cf-weekly-deploy/index.html
cd /tmp/cf-weekly-deploy
CLOUDFLARE_ACCOUNT_ID=d76ef4fce2e044eb854317e8f1fa6eb6 \
NODE_TLS_REJECT_UNAUTHORIZED=0 \
npx --yes wrangler@latest pages deploy . \
  --project-name=weekly-revenue-chart \
  --commit-dirty=true
```

成功后终端会输出一次性预览地址 https://<hash>.weekly-revenue-chart-5sn.pages.dev；固定域名会自动指向最新版本。

## 三、页面功能

- 顶部月度 / 周度范围下拉筛选，实时刷新所有图
- 多个 group（左堆叠 + 右 YoY）：
  1. 整体收入 × 收入类型
  2. 行业 × 收入类型（医疗 / 教培）
  3. 收入类型 × 团队（总收入 / 新签 / 续签 / 效果广告 / 品牌广告 × 整体 / 医疗 / 教培）
  4. 团队 × 收入类型（直营 / 渠道）
  5. 直营 × 行业
  6. 收入类型 × 类目（一级 → 二级下钻）
  7. **收入达成子弹图**（维度视角 / 指标视角 双 Tab；数据源为「目标&达成」sheet）
  8. **直营新签年费达成子弹图**（按行业筛选；人效指标双目标线；数据源为「直营新签人效达成--子弹图底数」sheet）
- 右侧目标&达成表：每月 YoY 目标 vs 实际

## 四、常见问题

- 右侧目标表空：检查 data/周报数据测试.xlsx 是否含"整月/时间进度"页签，且列顺序未变
- HTML 打开白屏：多半是 ECharts 没内联，用第一步的内联脚本重跑
- Cloudflare 部署报 auth error：wrangler 有账号缓存，重新 npx wrangler login 或删除 ~/.wrangler
- 重新下载 ECharts：curl -sL --insecure -o skill/echarts-5.5.0.min.js https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js

## 五、内容⑦ · 收入达成子弹图（已集成到主 HTML）

### 功能
展示每月各指标（总收入、新签年费、续签年费、效果广告、品牌广告、佣金收入）的实际达成 vs 序时目标 vs 月目标，按行业×团队维度做子弹图对比。支持双 Tab：**维度视角**（选行业+团队看所有指标）和**指标视角**（选指标看所有组合，分行业分组显示）。

### 数据来源
使用 `data/周报数据测试.xlsx` 中的 `目标&达成` sheet：
- 只取 `周期 = 整月` 的最新月份数据
- 序时目标 = 月目标 × (已过天数 / 当月总天数)，天数自动计算

## 六、内容⑧ · 直营新签年费达成子弹图（本次新增）

### 功能
按行业（直营-KA-口腔 / 妇产专科 / 医眼综合 / 亲子教育 / 驾校文印 / 直营-区域 / 合计）下拉切换，展示 5 个指标：

| 指标 | 序时进度 | 说明 |
|-----|---------|------|
| 年费收入 | 有 | 实际新签金额 vs 年费目标 |
| 展业人数 | **无** | 展业人数 vs 人力目标（直接对比，不看时间进度） |
| 人效签约金额 | **双目标线** | 见下 |
| 人效签约量 | **双目标线** | 保留 1 位小数 |
| 年费ARPU | **无** | 实际新签金额/门店 vs 目标 |

### 人效指标的双目标线
人效签约金额、人效签约量各画**两条目标虚线**：
- **橙色线「100%人力目标」**：展业人数达成率 100% 情况下的目标 = 年费目标 / 人力目标（标签在条形上方）
- **红色线「实际人力目标」**：实际人力达成下的目标 = 年费目标 / 展业人数（标签在条形下方）

### 序时进度定义（重要）
人效指标的序时进度（条形内百分比）以「100%人力目标」为基准：
```
序时进度 = (实际值 / 展业人数) / (目标 / 人力目标) / (已过天数 / 当月总天数)
        = actual / seq100
```
例（直营-区域，7/14，天数进度 12/31）：
- 人效签约金额序时进度 = 2026.13 / 4241.42 ≈ **47.77%**
- 人效签约量序时进度 = 0.59 / 1.46 ≈ **40.48%**

### 数据来源
使用 `data/周报数据测试.xlsx` 中的 `直营新签人效达成--子弹图底数` sheet（9 列）：
`月份 / 日期 / 行业线 / 新签门店目标 / 年费目标 / 实际新签金额 / 人力目标 / 展业人数 / 实际新签门店`
- 只取最新月份数据；合计行由各行业基础列求和后再算比率
- 行业下拉由数据动态生成，改行业名直接改 Excel 即可

### 代码位置
均在 `skill/weekly_revenue_chart.py`：
- `_ds_compute_metrics()`：5 指标计算（人效指标返回 3 元素 `[actual, tgt_100pct, tgt_actual]`）
- `build_bullet_data_direct_sales()`：读 Excel 构建数据
- JS `buildBtRowDual()` / `buildBtRowNoSeq()`：双目标线 / 无序时进度的渲染
- `renderBulletDirect()`：Group ⑧ 主渲染逻辑

## 七、子弹图规格（skill/bullet-chart/SKILL.md）
主要定义了子弹条视觉样式（蓝色填充 + 红色序时虚线 + Gap 标签）、达成率色彩规则（绿 ≥100% / 黄 ≥80% / 红 <80%）、数据结构、序时目标计算公式。
