# 云超服 OPC 培训站 · FastAPI 子应用（已并入 server-core）

> 📍 现位于 `code/server-core/app/training/`（培训子应用，原 `code/opc-training/server/`）。由 server-core `dispatcher.py` 统一对外 `opc.pinesound.cn`：`/api/*` 路由到本子应用。关联前端 `code/training/website/`、`code/training/miniprogram/`。

原 mock 后端（`website/server/mock-api.mjs`）的完整迁移，FastAPI + SQLite（`serverdata/data/opc.db`）。**子应用已异步化**：43 个路由 `async def`，同步 SQLite 经 `asyncio.to_thread` 原子调用（不阻塞事件循环）。

## 启动（已并入 server-core，无需单独启动）

```bash
cd code/server-core
uv run uvicorn dispatcher:app --host 0.0.0.0 --port 8090 --reload   # /api/* 由此提供
```

> 文档/健康检查：
> - Swagger: `http://127.0.0.1:8090/docs`
> - 健康: `http://127.0.0.1:8090/api/health`

## 数据

- 落盘 `serverdata/data/opc.db`（SQLite，WAL 模式），与平台库 `serverdata/data/app.db` 并列。
- 首次启动自动建表并种子：内置账号 `pine/123456`、8 场活动。
- OPC 测评题库由 `code/training/website/server/opcTest.js` 生成到 `app/training/opc_data.py`（勿手改；改题需重跑生成脚本）。

## 覆盖的接口（与原 mock 完全一致）

- 认证：`/api/auth/register|login|send-code|phone-login|logout|verify|wx-login|me|bind-phone`
- 活动：`/api/events`（`?current=1` / `?bookable=1`）、`/api/events/:id`、管理端 POST/PUT/DELETE
- 报名：`/api/bookings`、`/api/bookings/mine`、`/api/checkins`、管理端 GET/PATCH/DELETE
- 测评：`/api/tests/opc/questions`、`/api/tests/opc/calculate`、`/api/tests`
- 日志：`/api/policy-logs`、`/api/plan-logs`、`/api/survey-logs`
- 统计：`/api/ops/stats`

## 前端接入

- **web** `code/training/website/src/services/*.js` 的 `API_BASE` → `https://opc.pinesound.cn`（已默认）。
- **小程序** `code/training/miniprogram/src/utils/api.js` 的 `API_BASE` → `https://opc.pinesound.cn`（真机需 HTTPS + 配置合法域名）。

## 真实微信登录（配置步骤）

小程序 `wx.login` / `getPhoneNumber` 真实登录，需配置微信 `AppID/AppSecret`：

1. 微信公众平台 mp.weixin.qq.com → 开发 → 开发设置 → 复制 **AppID / AppSecret**。
2. 复制 `code/server-core/.env.example` 为 `code/server-core/.env`，填入两个值（或部署时设置环境变量 `WX_APPID` / `WX_SECRET`）。
3. 后端启动时自动读取 `.env`。配置后：
   - `POST /api/auth/wx-login`：用 `code` 调微信 `jscode2session` 换真实 `openid` 建号/登录。
   - `POST /api/auth/wx-phone`：一键绑定手机号（`getPhoneNumber` 的 code → 真实手机号）。
   - 未配置时自动降级为"演示伪 openid"（开发可用，`configured:false`），不影响开发。

> ⚠️ 仅在本机/开发者工具调试；小程序**真机必须**配置业务域名（request 合法域名 = 后端 HTTPS 地址）与 AppID，微信手机号授权也需在真机 + 已认证小程序下才可用。
