# state.user 双格式陷阱：字符串 vs 对象（2026-07-29）

## 背景

销售工作台的 `state.user` 在不同时期有两种格式：

| 格式 | 来源 | 示例值 |
|------|------|--------|
| 旧（字符串） | 硬编码 AUTH 登录 | `'zhaoyunhao'`, `'gm'`, `'director'` |
| 新（对象） | CloudBase / API 登录 | `{name:'宋学伟', role:'sales', dept:'诊断原料销售拓展部', email:'songxuewei@biori.com', tabs:{}}` |

## 症状

当 `state.user` 为对象时，所有用字符串 key 查找的代码全部断裂：

### 1. `USER_DEPTS[state.user]` — 订单管理权限过滤失效

```javascript
// ❌ 旧代码：state.user 为对象 → USER_DEPTS[{...}] = undefined → 过滤跳过 → 看到全公司数据
var USER_DEPTS = {
  'zhaoyunhao': ['诊断原料大客户销售部'],
  'zhangliya': ['诊断原料大客户销售部'],
};
var userDepts = USER_DEPTS[state.user];  // undefined!

// ✅ 修复：用 state.user.name 或 creatorEmail 精确匹配
var userName = typeof state.user === 'object' ? state.user.name : state.user;
// 或更优：
orders = orders.filter(function(o) { return o.creatorEmail === state.user.email; });
```

**实际影响**：宋学伟登录后看到「本年累计 2353.7 万」（全公司），实际只有 20.2 万（116 条个人订单）。

### 2. `AUTH[state.user]` — 多处崩溃

```javascript
// ❌ AUTH[{...}] = undefined → .name/.label 崩溃
AUTH[state.user].name    // TypeError
AUTH[state.user].label   // TypeError

// ✅ 统一获取函数
function getUserName() {
  if (!state.user) return '';
  if (typeof state.user === 'object') return state.user.name || '';
  return state.user;
}
```

### 3. `state.user === 'gm'` — 管理员判断失效

```javascript
// ❌ {name:...} === 'gm' → false（对象 ≠ 字符串）
if (state.user === 'gm' || state.user === 'director') ...

// ✅ 用 role 字段判断
function isAdminUser() {
  var r = getUserRole();
  return r === 'admin' || r === 'gm' || r === 'director';
}
```

## 修复模式

在脚本顶部添加三个工具函数，全面替换所有 `state.user` 字符串比较：

```javascript
function getUserName() {
  if (!state.user) return '';
  if (typeof state.user === 'object') return state.user.name || '';
  return state.user;
}
function getUserRole() {
  if (!state.user) return '';
  if (typeof state.user === 'object') return state.user.role || 'sales';
  return state.user;
}
function isAdminUser() {
  var r = getUserRole();
  return r === 'admin' || r === 'gm' || r === 'director';
}
```

## 订单过滤最佳实践

**按 `creatorEmail` 过滤，而非部门映射**：

```javascript
// ✅ 精确、不依赖部门名维护
var userEmail = state.user.email;
orders = orders.filter(function(o) { return o.creatorEmail === userEmail; });

// ❌ 部门名可能变化、需手动维护 USER_DEPTS
orders = orders.filter(function(o) { return userDepts.indexOf(o.dept) >= 0; });
```

`shipment_status.json` 中全部 2033 条订单均有 `creatorEmail` 字段，覆盖率 100%。

## 受影响的代码位置（`销售工作台.html`）

| 行号 | 原始代码 | 问题 | 修复 |
|------|---------|------|------|
| 703 | `state.user === 'gm' \|\| state.user === 'director'` | 对象 ≠ 字符串 | `isAdminUser()` |
| 704 | `AUTH[state.user].name` | AUTH[对象] = undefined | `getUserName()` |
| 1596 | `state.user === 'gm' \|\| state.user === 'director'` | 同上 | `isAdminUser()` |
| 1664 | `AUTH[state.user].label` | 同上 | `getUserName()` |
| 1696 | `AUTH[state.user].label` | 同上 | `getUserName()` |
| 1710-1714 | `USER_DEPTS = {'zhaoyunhao': [...], ...}` | 旧 key 用拼音名 | 改为中文名 + 新增用户 |
| 1734 | `USER_DEPTS[state.user]` | 对象 key 查找失败 | 改为 `creatorEmail` 精确匹配 |

## 历史案例

2026-07-29，宋学伟（新用户，通过 API 登录获取对象格式 `state.user`）在订单管理 Tab 看到全公司 2353.7 万数据。根因是 `USER_DEPTS[state.user]` 对对象格式返回 undefined，过滤被跳过。修复后正确显示个人 20.2 万。
