# 三年逐月销售对比权限：只给 admin+gm（2026-08-21）

## 决策

用户明确要求：三年逐月销售对比是公司级敏感数据，**销售员和经理干脆不展示**，只给 admin（刘新元）+ gm（总经理时总/何超锦）看。

此前「三年逐月数据用户隔离（2026-07-29）」方案是"按用户年度销售额占比分摊给非admin"，该方案已被本决策**废弃**。

## 实现

`renderDashboard` 里给「📈 三年逐月销售对比」卡片加 `isAdmin` 条件渲染：

```javascript
(isAdmin ?
  '<div class="card" ...>📈 三年逐月销售对比...</div>' +
  '<div class="card-body" ...><div id="y3mContainer"></div></div></div>'
  : '');
```

`renderThreeYearMonthly()` 内部有 `if (!el) return;` 兜底，卡片不渲染时不会报错，调用处无需改。

## ⚠️ 关键坑：app.html 的 renderDashboard 里没有 isAdmin 变量

- `index.html` 的 `renderDashboard` 里有 `var isAdmin = userRole === 'admin' || userRole === 'gm';`（#84 权限模型）。
- 但 `app.html` 里 `isAdmin` 只在 `renderGroups()` 函数内定义，`renderDashboard` 作用域里**没有**。

改 app.html 的看板权限时，必须先在 renderDashboard 开头补：

```javascript
var isAdmin = (state.user || {}).role === 'admin' || (state.user || {}).role === 'gm';
```

## 铁律

1. 改 app.html 任何权限判断前，先 `grep -n "var isAdmin" app.html` 确认每个定义在哪个函数里——同名变量在不同函数作用域，直接引用会拿到 undefined 走 false 分支。
2. 两个入口（index.html + app.html）权限逻辑要同步，但变量作用域可能不同，不能假设一个文件有的变量另一个也有。
3. gm 账号：时彦祎、何超锦（`user_roles` 集合 role=gm）。

## 验证

- 提取 `<script>` 内容用 `node --check` 验语法（HTML 不能直接 node --check）。
- index.html 部署 `tcb hosting deploy 工具/index.html /workbench/index.html -e bier-sales-d0gatbvlx288724e9`。
- app.html 本地生效（本地 8765 服务 / Tailscale Funnel）。
