# CloudBase 部署 + 鉴权迁移模式（2026-07-25）

将本地 `127.0.0.1:8765` 的工作台页面迁移到腾讯云 CloudBase 静态托管，实现公网 HTTPS 访问 + 数据库鉴权。

## 架构

```
CloudBase静态托管（CDN + HTTPS）
├── 工具/index.html    → 销售工作台（接入CloudBase SDK）
├── 工具/logo.png
├── 数据/*.json        → 静态数据文件
└── CloudBase 文档数据库
    └── user_roles 集合 → 用户名/密码/角色/状态
```

## 鉴权流程（匿名登录 + 数据库验证）

```
用户打开页面
  → CloudBase 匿名登录（auth.anonymousAuthProvider().signIn()）
  → 显示自定义登录表单（选择角色+输入密码）
  → 查询 user_roles 集合验证密码
  → 匹配 → 进入系统
```

**优势**：不占 CloudBase 用户配额（体验版仅2用户），不暴露密码。

## 部署步骤

### 1. 开通 CloudBase 环境

```bash
# 腾讯云控制台 → 云开发 → 新建环境 → 获取环境ID
# 安装 CLI
npm install -g @cloudbase/cli

# 登录
tcb login --apiKeyId <SecretId> --apiKey <SecretKey>

# 验证
tcb env list
tcb hosting detail -e <envId>  # 获取域名
```

### 2. 创建用户数据库

```bash
tcb db nosql execute -e <envId> --command '[
  {"TableName":"user_roles","CommandType":"INSERT","Command":"{\"insert\":\"user_roles\",\"documents\":[
    {\"username\":\"gm\",\"password\":\"biorigm\",\"role\":\"gm\",\"name\":\"总经理\",\"admin\":true,\"status\":\"在职\"},
    {\"username\":\"director\",\"password\":\"bioridir\",\"role\":\"director\",\"name\":\"大客户部总监\",\"admin\":true,\"status\":\"在职\"},
    {\"username\":\"zhaoyunhao\",\"password\":\"biorizhao\",\"role\":\"zhaoyunhao\",\"name\":\"赵云浩\",\"admin\":false,\"status\":\"在职\"},
    {\"username\":\"zhangliya\",\"password\":\"bioriliya\",\"role\":\"zhangliya\",\"name\":\"张立娅\",\"admin\":false,\"status\":\"在职\"}
  ]}"}
]'
```

### 3. 配置权限

在 CloudBase 控制台：
- 登录方式 → 开启「匿名登录」
- 数据库 → user_roles 集合 → 权限设置 → **所有用户可读，仅创建者可写**

### 4. HTML 改造

```html
<!-- 引入 SDK -->
<script src="https://static.cloudbase.net/cloudbase-js-sdk/latest/cloudbase.full.js"></script>

<script>
// 去掉硬编码密码
var AUTH = {
  gm:       { label: '👑 总经理', name: '总经理', admin: true },
  director: { label: '📊 大客户部总监', name: '大客户部总监', admin: true },
  zhaoyunhao: { label: '赵云浩', name: '赵云浩' },
  zhangliya:  { label: '张立娅', name: '张立娅' }
};

var CB_ENV = 'bier-sales-d0gatbvlx288724e9';

function init() {
  cbApp = cloudbase.init({ env: CB_ENV });
  cbDb = cbApp.database();
  var auth = cbApp.auth({ persistence: 'local' });
  auth.anonymousAuthProvider().signIn().then(function() {
    var saved = localStorage.getItem(ROLE_KEY);
    if (saved && AUTH[saved]) { state.user = saved; showApp(); loadData(); }
    else { showLoginForm(); }
  });
}

function doLogin() {
  var role = document.getElementById('loginRole').value;
  var pwd = document.getElementById('loginPwd').value;
  cbDb.collection('user_roles').where({ username: role }).get().then(function(res) {
    var user = res.data[0];
    if (!user) throw new Error('用户不存在');
    if (user.status !== '在职') throw new Error('账号已停用');
    if (user.password !== pwd) throw new Error('密码错误');
    finishLogin(role);
  }).catch(function(e) { /* 显示错误 */ });
}
</script>
```

### 5. 部署

```bash
tcb hosting deploy index.html 工具/index.html -e <envId>
tcb hosting deploy logo.png 工具/logo.png -e <envId>
# 部署所有数据JSON
for f in 数据/*.json; do
  tcb hosting deploy "$f" "$f" -e <envId>
done
```

## 数据自动同步

见 `baoyu-workbench-data-pipeline` skill 的「CloudBase 自动同步」节。

## 陷阱

| 陷阱 | 现象 | 修复 |
|------|------|------|
| 数据库权限默认禁止匿名读 | 登录报"用户不存在" | 设置 user_roles 权限为「所有用户可读」 |
| 体验版用户数限制 2 人 | tcb user create 第3个报 "超过配额限制" | 改用匿名登录 + 数据库自建用户表 |
| 数据路径不一致 | 本地 `../数据/` → CloudBase 找不到 | 部署时保持相同目录结构（`工具/` → `数据/`） |
| `tcb login` 不支持直接传 key | 交互式输入堵塞 | 使用 `--apiKeyId` + `--apiKey` 参数 |
| 部署后 CDN 缓存旧版 | 修改不生效 | URL 加 `?v=N` 或浏览器无痕模式验证 |
| MCP token 无写权限 | create_workitem 报 "user has not enabled this MCP feature" | 用户在飞书项目 → 个人设置 → 开启 MCP 写权限；或用跳转 URL 替代 |
| **飞书网页应用中文URL被拒** | 含 `/工具/index.html` 提示"请填写有效URL" | 部署到根目录 `index.html`，飞书应用主页用纯英文路径 |
| `tcb fn deploy` 交互式选择 | 命令行阻塞在"请选择操作" | 云函数通过 CloudBase 控制台手动创建更可靠 |

## 飞书活动集成模式

### 跳转新建活动

**两种跳转方式**：

| 方式 | URL | 适用场景 |
|------|-----|---------|
| 活动主页（列表+新建） | `https://project.feishu.cn/xsguanli/sj/homepage` | 无客户上下文，打开让销售员浏览+手动新建 |
| 新建活动（预填客户名） | `https://project.feishu.cn/baoyu/workitem/create?project_key=6593cd71471290e3cc6be6e6&work_item_type_key=65ae1e5d44338dbe7c39a29a` | 有客户名，自动预填标题 |

URL 格式：`project.feishu.cn/{simple_name}/{api_name}/homepage`。simple_name/ api_name 从 MCP `search_project_info` 和 `list_workitem_types` 获取。**简单跳转不需要 MCP 写权限**，比 `create_workitem` API 更可靠。

```javascript
var FEISHU_NEW_ACTIVITY = 'https://project.feishu.cn/baoyu/workitem/create' +
  '?project_key=6593cd71471290e3cc6be6e6' +
  '&work_item_type_key=65ae1e5d44338dbe7c39a29a';

function openFeishuCreateActivity(customerName) {
  var url = FEISHU_NEW_ACTIVITY;
  if (customerName) {
    url += '&name=' + encodeURIComponent('拜访' + customerName + ' - ' + today());
  }
  window.open(url, '_blank');
}
```

活动类型 option_id 映射：`线下拜访=v4zlj721e, 线上跟进=5vezmmm1y, 陌拜=wg15dd75b, 协同拜访=wsxnxsd60`

### 后端 MCP 创建（API 端点）

在 `销售工作台服务.py` 中添加 `/api/create_activity` 端点，调用 MCP `create_workitem`。需要 MCP token 有写权限。

### 访前准备 Tab

5 步准备清单（客户档案→历史活动→待办→订单→新建纪要）+ 重点客户快捷入口（一键带客户名跳转飞书新建活动）。

### 我的活动 Tab

展示当前登录用户的飞书活动记录。数据源为 `数据/my_activities.json`，由 cb_sync.sh cron 从 MCP 拉取。当前数据未同步时显示引导页+飞书项目链接。

## 权限管理后台页面模式\n\n独立管理页 `admin.html`，管理员勾选每个用户的Tab权限和角色，保存到 CloudBase `user_roles` 集合。\n\n### 核心设计\n\n```\nadmin.html (管理员密码登录)\n  → 从 user_roles 加载用户列表\n  → 表格：姓名 | 部门 | 角色下拉 | 各Tab勾选框\n  → 「保存全部修改」→ 逐条 upsert 到 CloudBase\n```\n\n### 用户数据模型\n\n```json\n{\n  \"name\": \"李江辉\",\n  \"dept\": \"诊断原料销售拓展部\",\n  \"role\": \"sales\",\n  \"email\": \"lijianghui@biori.com\",\n  \"status\": \"在职\",\n  \"tabs\": {\n    \"dashboard\": 0, \"customers\": 1, \"visitPrep\": 1,\n    \"oppSandbox\": 1, \"complaints\": 1, \"orders\": 1,\n    \"myActivities\": 1, \"todos\": 1\n  }\n}\n```\n\n### 部署\n\n```bash\ntcb hosting deploy admin.html admin.html -e <envId>\n# 访问: https://<envId>.tcloudbaseapp.com/admin.html\n# 密码: biorigm (与GM密码一致)\n```\n\n### 权限体系\n\n| 角色 | 全公司看板 | 客户 | 商机 | 客诉 | 订单 |\n|------|:--:|:--:|:--:|:--:|:--:|\n| admin (GM/总监) | ✅ | 全部 | 全部 | 全部 | 全部 |\n| manager (部门经理) | ❌* | 本部门 | 本部门 | 本部门 | 本部门 |\n| sales (销售员) | ❌ | 本人 | 本人 | 本人 | 本人 |\n\n\\* manager/sales 不显示全公司KPI看板，但保留个人维度数据。\n\n## Cron 自动同步模式

```bash
# Hermes cronjob 方式（推荐）
cronjob create --name "CloudBase数据同步" --schedule "0 */2 * * *" \
  --script 脚本/cb_sync.sh --no_agent --deliver local
```

`--no_agent` 模式直接运行脚本，不消耗 LLM token。日志输出到 `数据/cb_sync.log`。
