docs: complete developer documentation (5 guides + index)

- 01-快速开始: local setup for all 3 modules, common issues
- 02-配置说明: all env vars, WeChat/Pay/DB/COS config details
- 03-架构说明: system overview, directory structure, data flows
- 04-部署指南: Tencent Cloud SCF/COS deployment, launch checklist
- 05-API接口文档: all 42 endpoints with params and response format
- README index with audience guide and quick links
这个提交包含在:
Guoguo
2026-05-18 08:11:30 -07:00
父节点 7e036576e3
当前提交 0feb900a1d
修改 6 个文件,包含 2630 行新增0 行删除
+232
查看文件
@@ -0,0 +1,232 @@
# 快速开始
## 项目概述
jw-beauty 是一款光子美容仪配套系统,包含三个子项目:
- **微信小程序** (`miniprogram/`) — 用户端,蓝牙连接设备、护理流程、订阅管理
- **后端服务** (`server/`) — Express.js API,部署为腾讯云 SCF HTTP 函数
- **H5 管理后台** (`admin-console/`) — Vue 3 + uni-app H5,管理设备/用户/订阅/固件
## 前置要求
| 工具 | 版本要求 | 说明 |
|------|---------|------|
| Node.js | >= 18 | 后端使用 Express 5,管理后台使用 Vite 5 |
| npm | >= 8 | 随 Node.js 一起安装 |
| MySQL | >= 5.7 | 本地开发用,推荐 8.0;也可用 Docker |
| 微信开发者工具 | 最新稳定版 | 小程序调试用 |
| Git | 任意 | 版本管理 |
## 获取代码
```bash
git clone <仓库地址>
cd jw-beauty
```
## 后端启动
### 1. 安装依赖
```bash
cd server
npm install
```
### 2. 配置环境变量
```bash
cp .env.example .env
```
编辑 `.env`,至少填写数据库连接信息:
```ini
NODE_ENV=development
PORT=3000
# 数据库(必填)
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=你的MySQL密码
DB_NAME=jw_beauty
# 微信登录(本地开发可暂不填,有 mock 登录)
WECHAT_APPID=
WECHAT_SECRET=
# JWT 密钥(开发环境用默认值即可,会自动 fallback)
JWT_SECRET=replace-with-a-long-random-secret
ADMIN_JWT_SECRET=replace-with-a-different-long-random-secret
# 管理员账号(开发环境默认 admin/admin
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin
# 腾讯云(头像上传/COS 功能需要,本地开发可暂不填)
TENCENT_SECRET_ID=
TENCENT_SECRET_KEY=
TENCENT_REGION=ap-guangzhou
COS_BUCKET=jw-bucket-1426323813
COS_REGION=ap-guangzhou
```
### 3. 创建数据库
先手动创建数据库:
```bash
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS jw_beauty DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;"
```
然后运行初始化脚本(建表 + 插入默认设置 + 创建管理员账号):
```bash
npm run db:init
```
### 4. 启动服务
```bash
npm start
```
看到以下输出说明启动成功:
```
Server listening on http://localhost:3000
```
### 5. 验证
```bash
curl http://localhost:3000/health
```
期望返回:
```json
{"code":0,"data":{"status":"ok"}}
```
## 小程序启动
### 1. 打开项目
用微信开发者工具打开 `miniprogram/` 目录。
项目的 AppID 已在 `project.config.json` 中配置为 `wxc4045074ef298510`。如果你没有该 AppID 的权限,可以用测试号或在开发者工具中选择"测试号"。
### 2. 指向本地后端
编辑 `miniprogram/config/env.js`,将 `ENV` 改为 `local`
```js
var ENV = 'local' // 改为 local,API 请求会发到 http://localhost:3000
var API_BASES = {
local: 'http://localhost:3000',
test: 'https://api.vsai.net.cn',
prod: 'https://api.vsai.net.cn'
}
```
### 3. 注意事项
- **不校验合法域名**:在开发者工具「详情 > 本地设置」中勾选「不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书」,否则 localhost 请求会被拦截
- **BLE 蓝牙功能需要真机调试**:模拟器无法使用蓝牙,设备连接/护理流程必须在真机上测试
- **`__DEV__` 标志**:当 `ENV` 不是 `prod` 时,`__DEV__``true`,会启用 mock 绑定、mock 购买等开发便捷功能
- **权限**:小程序使用了蓝牙、位置(蓝牙依赖)、相机(扫码)权限,真机调试时需要授权
## 管理后台启动
### 1. 安装依赖
```bash
cd admin-console
npm install
```
### 2. 指向本地后端
编辑 `admin-console/src/config/env.js`,将 `ENV` 改为 `local`
```js
const ENV = 'local' // 改为 local
const API_BASES = {
local: 'http://localhost:3000',
test: 'https://api.vsai.net.cn',
prod: 'https://api.vsai.net.cn'
}
```
### 3. 启动开发服务器
```bash
npm run dev
```
启动后访问终端输出的地址,通常是 `http://localhost:5173/admin/`
> 注意路径末尾的 `/admin/`,这是 `vite.config.js` 中配置的 `base` 路径。
### 4. 登录
使用默认管理员账号登录:
- 用户名:`admin`
- 密码:`admin`
(与 `.env``ADMIN_USERNAME` / `ADMIN_PASSWORD` 一致)
### 5. 构建生产版本
```bash
npm run build:h5
```
构建产物在 `dist/build/h5/` 目录,部署到 COS
```bash
npm run deploy:cos
```
## 常见问题
### 端口 3000 被占用
修改 `.env` 中的 `PORT`,同时更新小程序和管理后台的 `env.js``local` 对应的地址。
### 数据库连接失败
1. 确认 MySQL 服务已启动
2. 确认 `.env``DB_HOST``DB_PORT``DB_USER``DB_PASSWORD` 正确
3. 确认已创建 `jw_beauty` 数据库
4. 如果用 Docker 跑 MySQL,注意 host 应为 `127.0.0.1` 而非 `localhost`(避免 socket 连接问题)
### 微信登录在开发环境怎么测试
开发环境(`NODE_ENV=development`)下,服务端提供了 mock 端点:
- **mock 绑定设备**:不需要真实蓝牙握手
- **mock 购买订阅**:不需要真实微信支付
小程序端 `__DEV__``true` 时会显示对应的开发快捷入口。
如果需要测试真实微信登录,需要在 `.env` 中填写 `WECHAT_APPID``WECHAT_SECRET`(从微信公众平台获取)。
### 管理后台页面空白
确认访问地址包含 `/admin/` 路径前缀。直接访问 `http://localhost:5173/` 会 404。
### npm install 报错
确认 Node.js 版本 >= 18。可以使用 nvm 管理多版本:
```bash
nvm install 18
nvm use 18
```
+291
查看文件
@@ -0,0 +1,291 @@
# 配置说明
## 环境变量总表
后端所有配置通过 `server/.env` 文件管理(通过 dotenv 加载)。下表列出全部变量:
| 变量名 | 用途 | 示例值 | 必填 | 默认值 |
|--------|------|--------|------|--------|
| `NODE_ENV` | 运行环境 | `development` / `production` | 否 | `development` |
| `PORT` | 监听端口 | `3000` | 否 | `3000` |
| `DB_HOST` | MySQL 主机地址 | `127.0.0.1` | 是 | 无 |
| `DB_PORT` | MySQL 端口 | `3306` | 否 | `3306` |
| `DB_USER` | MySQL 用户名 | `root` | 否 | `root` |
| `DB_PASSWORD` | MySQL 密码 | `mypassword` | 是 | 无 |
| `DB_NAME` | 数据库名 | `jw_beauty` | 否 | `jw_beauty` |
| `WECHAT_APPID` | 微信小程序 AppID | `wxc4045074ef298510` | 生产必填 | 无 |
| `WECHAT_SECRET` | 微信小程序 AppSecret | `abcdef1234567890...` | 生产必填 | 无 |
| `JWT_SECRET` | 用户 JWT 签名密钥 | `a-long-random-string` | 生产必填 | `dev-user-secret` |
| `ADMIN_JWT_SECRET` | 管理员 JWT 签名密钥 | `another-long-random-string` | 生产必填 | `dev-admin-secret` |
| `ADMIN_USERNAME` | 初始管理员用户名 | `admin` | 否 | `admin` |
| `ADMIN_PASSWORD` | 初始管理员密码 | `strongpassword` | 生产必填 | `admin` |
| `TENCENT_SECRET_ID` | 腾讯云 API SecretId | `AKIDxxxx` | COS 功能需要 | 无 |
| `TENCENT_SECRET_KEY` | 腾讯云 API SecretKey | `xxxx` | COS 功能需要 | 无 |
| `TENCENT_REGION` | 腾讯云默认地域 | `ap-guangzhou` | 否 | `ap-guangzhou` |
| `COS_BUCKET` | COS 存储桶名称 | `jw-bucket-1426323813` | 否 | `jw-bucket-1426323813` |
| `COS_REGION` | COS 存储桶地域 | `ap-guangzhou` | 否 | 同 `TENCENT_REGION` |
| `COS_CDN_DOMAIN` | COS CDN 加速域名 | `tx.vsai.net.cn` | 否 | `tx.vsai.net.cn` |
### 生产环境安全检查
`NODE_ENV=production` 时,服务启动会强制检查以下条件,不满足则拒绝启动:
- `JWT_SECRET` 不能是默认值 `dev-user-secret`
- `ADMIN_JWT_SECRET` 不能是默认值 `dev-admin-secret`
- `ADMIN_USERNAME``ADMIN_PASSWORD` 不能是默认值 `admin`
## 微信配置
### 获取 WECHAT_APPID 和 WECHAT_SECRET
1. 登录 [微信公众平台](https://mp.weixin.qq.com/) -> 开发管理 -> 开发设置
2. AppID(小程序ID) 即为 `WECHAT_APPID`
3. AppSecret(小程序密钥) 即为 `WECHAT_SECRET`(需要管理员扫码后才能查看,只显示一次)
```ini
WECHAT_APPID=wxc4045074ef298510
WECHAT_SECRET=你的AppSecret
```
### 开发环境
本地开发时不填这两个值也能运行,但微信登录(`wx.login` -> `code2Session`)会失败。此时可以通过 mock 端点绕过。
## 数据库配置
### 本地开发
```ini
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=你的本地MySQL密码
DB_NAME=jw_beauty
```
使用 Docker 快速启动 MySQL
```bash
docker run -d \
--name jw-mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=rootpass \
-e MYSQL_DATABASE=jw_beauty \
mysql:8.0 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
```
然后 `.env` 中填:
```ini
DB_HOST=127.0.0.1
DB_PASSWORD=rootpass
```
### 腾讯云 TencentDB
SCF 函数部署时,需要将函数放在与 TencentDB 同一 VPC/子网中:
```ini
DB_HOST=10.0.0.x # VPC 内网地址
DB_PORT=3306
DB_USER=root
DB_PASSWORD=腾讯云数据库密码
DB_NAME=jw_beauty
```
### 数据库表结构
共 10 张表(定义在 `server/sql/schema.sql`):
| 表名 | 说明 |
|------|------|
| `users` | 小程序用户,openid 唯一索引 |
| `devices` | 美容仪设备,device_id 为主键 |
| `bindings` | 用户-设备绑定关系 |
| `subscriptions` | 用户订阅记录(月卡/年卡) |
| `treatment_records` | 护理记录,含时长、模式、光密度等 |
| `device_events` | 设备事件日志(错误、告警等) |
| `device_commands` | 下发给设备的远程指令 |
| `operation_logs` | 操作审计日志 |
| `admin_accounts` | 管理员账号 |
| `system_settings` | 系统设置键值对(定价、功能开关等) |
| `firmware_files` | 固件版本记录 |
初始化时会自动插入默认系统设置:月卡 99 元、年卡 899 元、试用 7 天等。
## COS 配置
COS(对象存储)用于存储用户头像和固件文件,通过 CDN 域名对外提供访问。
```ini
TENCENT_SECRET_ID=AKIDxxxx # 腾讯云控制台 -> 访问管理 -> API密钥管理
TENCENT_SECRET_KEY=xxxx
COS_BUCKET=jw-bucket-1426323813 # 存储桶名称(含 APPID 后缀)
COS_REGION=ap-guangzhou # 存储桶所在地域
COS_CDN_DOMAIN=tx.vsai.net.cn # CDN 加速域名(可选,不填有默认值)
```
### 获取密钥
1. 登录 [腾讯云控制台](https://console.cloud.tencent.com/)
2. 访问管理 -> API 密钥管理 -> 新建密钥
3. 复制 SecretId 和 SecretKey
> 建议创建子用户,只授予 COS 相关权限,不要使用主账号密钥。
### 本地开发
不配置 COS 相关变量时,头像上传和固件上传功能会报错,但不影响其他功能开发。
## 安全配置
### JWT_SECRET
用于签发用户端 JWT token,有效期 7 天。生成方法:
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
将输出填入 `.env`
```ini
JWT_SECRET=生成的64位十六进制字符串
```
### ADMIN_JWT_SECRET
用于签发管理后台 JWT token,必须与 `JWT_SECRET` 不同。用同样的方法生成:
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
```ini
ADMIN_JWT_SECRET=另一个64位十六进制字符串
```
### 管理员初始密码
`npm run db:init` 会使用 `.env` 中的 `ADMIN_USERNAME``ADMIN_PASSWORD` 创建管理员账号(bcrypt 哈希存储)。
```ini
ADMIN_USERNAME=admin
ADMIN_PASSWORD=一个强密码
```
> 生产环境不能使用默认值 `admin/admin`,服务启动时会报错退出。
### CORS
当前 CORS 设置为 `Access-Control-Allow-Origin: *`(见 `server/src/app.js`),允许所有来源。这是开发阶段的配置,生产环境应收紧为具体域名。
允许的自定义请求头:
```
Content-Type, Authorization, X-Device-Id, X-App-Version, X-Platform
```
## 小程序配置
### env.js
文件路径:`miniprogram/config/env.js`
```js
var ENV = 'test' // 可选值:local / test / prod
var API_BASES = {
local: 'http://localhost:3000',
test: 'https://api.vsai.net.cn',
prod: 'https://api.vsai.net.cn'
}
var __DEV__ = ENV !== 'prod'
```
#### ENV 取值说明
| 值 | API 地址 | `__DEV__` | 说明 |
|----|---------|-----------|------|
| `local` | `http://localhost:3000` | `true` | 本地开发 |
| `test` | `https://api.vsai.net.cn` | `true` | 连接测试环境 |
| `prod` | `https://api.vsai.net.cn` | `false` | 生产环境 |
#### `__DEV__` 的作用
`__DEV__``true` 时:
- 启用 mock 绑定设备(无需蓝牙握手)
- 启用 mock 购买订阅(无需微信支付)
- 可能显示额外的调试信息
发布正式版时务必将 `ENV` 设为 `prod`
### project.config.json
文件中的 `appid` 字段需要与实际的小程序 AppID 一致:
```json
{
"appid": "wxc4045074ef298510",
"projectname": "hox-beauty"
}
```
如果没有该 AppID 权限,在微信开发者工具中可以选择测试号。
## 管理后台配置
### env.js
文件路径:`admin-console/src/config/env.js`
```js
const ENV = 'test' // 可选值:local / test / prod
const API_BASES = {
local: 'http://localhost:3000',
test: 'https://api.vsai.net.cn',
prod: 'https://api.vsai.net.cn'
}
```
与小程序的 `env.js` 功能一致,本地开发时改为 `local`
### Vite base path
`admin-console/vite.config.js` 配置了 base 路径:
```js
export default defineConfig({
base: process.env.PUBLIC_PATH || '/admin/',
plugins: [uni()]
})
```
- 默认 base 为 `/admin/`,意味着所有静态资源路径都会加上 `/admin/` 前缀
- 部署到 COS 后通过 `https://你的域名/admin/` 访问
- 本地开发时访问地址为 `http://localhost:5173/admin/`
- 如需改变路径前缀,设置环境变量 `PUBLIC_PATH`
```bash
PUBLIC_PATH=/console/ npm run build:h5
```
### 构建与部署
```bash
# 开发
npm run dev
# 构建 H5 产物
npm run build:h5
# 构建并部署到 COS
npm run deploy:cos
```
`deploy:cos` 脚本会将 `dist/build/h5/` 目录的文件上传到 COS 存储桶,需要在 `server/.env`(或管理后台自己的 `.env`)中配置好 `TENCENT_SECRET_ID``TENCENT_SECRET_KEY``COS_BUCKET` 等变量。
+441
查看文件
@@ -0,0 +1,441 @@
# 架构说明
## 1. 系统架构总览
```
+-----------------+
| 腾讯云 COS |
| (头像/固件存储) |
+--------^--------+
|
+------------------+ +--------+--------+ +------------------+
| | | | | |
| 微信小程序 +--->+ SCF 云函数 +<---+ 管理后台 |
| (用户端) | | (Express) | | (uni-app H5) |
| +<---+ +--->+ |
+-------+----------+ +--------+--------+ +------------------+
| |
| BLE | mysql2
v v
+-------+----------+ +--------+--------+
| 光子美容仪 | | MySQL |
| (蓝牙设备) | | (腾讯云) |
+------------------+ +-----------------+
```
三端关系:
- **小程序** 通过 HTTPS 调用后端 API,通过 BLE 连接硬件设备
- **管理后台** 通过同一套后端 API(`/api/v1/admin/*`)管理数据
- **后端** 部署为腾讯云 SCF 云函数,连接 MySQL 和 COS
## 2. 后端架构
### 2.1 目录结构
```
server/src/
├── index.js # SCF 入口,导出 main_handler
├── app.js # Express 应用,中间件 + 路由挂载
├── config.js # 环境变量配置
├── middleware/
│ └── auth.js # JWT 认证中间件
├── routes/
│ ├── auth.js # 登录/刷新 token
│ ├── user.js # 用户信息
│ ├── device.js # 设备绑定/解绑/指令
│ ├── subscription.js # 订阅计划/购买/试用
│ ├── treatment.js # 护理记录同步/查询
│ ├── firmware.js # 固件版本管理
│ └── admin.js # 管理后台全部接口
├── dao/
│ ├── index.js # barrel export
│ ├── user.dao.js # users 表
│ ├── device.dao.js # devices 表
│ ├── binding.dao.js # device_bindings 表
│ ├── subscription.dao.js # subscriptions 表
│ ├── treatment.dao.js # treatment_records 表
│ ├── command.dao.js # device_commands 表
│ ├── device-event.dao.js # device_events 表
│ ├── admin.dao.js # admin_accounts 表
│ ├── log.dao.js # operation_logs 表
│ ├── settings.dao.js # system_settings 表
│ └── firmware.dao.js # firmware_versions 表
└── lib/
├── serverless.js # SCF event → Express 适配器
├── db.js # mysql2 连接池 (query/one/transaction)
├── auth.js # JWT 签发/密码哈希/Bearer 读取
├── response.js # 统一响应 { code, message, data }
├── settings-cache.js # system_settings 内存缓存 (TTL 60s)
├── wechat.js # 微信 code2Session / 获取手机号
├── cos.js # 腾讯云 COS 客户端
└── utils.js # 日期格式化工具
```
### 2.2 请求处理流程
```
SCF event
serverless.js 将 SCF event 转换为 http.IncomingMessage + ServerResponse
Express app(req, res)
├── express.json() 解析 JSON body
├── CORS 中间件 设置跨域头,处理 OPTIONS
├── rate limiter 对 login/upload 路径限流
├── authMiddleware 提取 x-forwarded-for → req.ip
├── /health 健康检查
├── /api/v1/auth/* → routes/auth.js
├── /api/v1/user/* → routes/user.js (requireUser)
├── /api/v1/device/* → routes/device.js (requireUser)
├── /api/v1/subscription/* → routes/subscription.js
├── /api/v1/treatment/* → routes/treatment.js (requireUser)
├── /api/v1/admin/* → routes/admin.js (requireAdmin)
├── /api/v1/firmware/* → routes/firmware.js
├── 404 handler
└── error handler 记录错误日志,返回 3001
```
### 2.3 认证机制
JWT 双密钥体系:
| 角色 | 签发函数 | 密钥 | payload 字段 |
|-------|-------------|---------------------|----------------------------|
| user | signUser() | config.jwt.secret | type, user_id, openid |
| admin | signAdmin() | config.jwt.adminSecret | type, admin_id, username, role |
中间件层级:
- `authMiddleware` — 全局,仅提取 IP,不验证 token
- `requireUser` — 路由级,验证 user token,查库确认用户存在且 status=1,挂载 `req.user`
- `requireAdmin` — 路由级,验证 admin token,查库确认管理员存在且 status=1,挂载 `req.admin`
token 刷新:客户端在 token 剩余 <24h 时自动调用 `/auth/refresh`,过期后有 1 天宽限期。
### 2.4 DAO 层
每个 DAO 文件只操作一张表,通过 `db.js` 提供的 `query/one/transaction` 与数据库交互:
| DAO 文件 | 负责表 | 核心操作 |
|-----------------------|---------------------|----------------------------------|
| user.dao.js | users | CRUD、openid 查找、分页列表 |
| device.dao.js | devices | 设备列表、按用户绑定关系查询 |
| binding.dao.js | device_bindings | 创建/确认/取消绑定、活跃绑定查询 |
| subscription.dao.js | subscriptions | 试用创建、购买(extend)、查有效订阅 |
| treatment.dao.js | treatment_records | 创建记录、按用户分页、更新设备状态 |
| command.dao.js | device_commands | 创建指令、拉取待执行、标记完成 |
| device-event.dao.js | device_events | 设备异常事件记录 |
| admin.dao.js | admin_accounts | 管理员查找/验证 |
| log.dao.js | operation_logs | 操作日志写入与分页查询 |
| settings.dao.js | system_settings | 全量读取系统配置 |
| firmware.dao.js | firmware_versions | 固件版本列表/最新版查询 |
### 2.5 工具库
| 文件 | 职责 |
|-------------------|-------------------------------------------------------------|
| response.js | `ok(data)` / `fail(code, msg)` 统一响应格式 |
| settings-cache.js | system_settings 内存缓存,TTL 60秒,`invalidateCache()` 手动失效 |
| wechat.js | 微信登录 `code2Session`、获取手机号 `getPhoneNumber` |
| cos.js | 腾讯云 COS 签名 URL 生成 |
| utils.js | `toMysqlDate()` 日期格式化(UTC+8) |
| wxpay.js | (规划中) 微信支付下单、回调签名验证 |
## 3. 小程序架构
### 3.1 目录结构
```
miniprogram/
├── app.js / app.json / app.wxss # 应用入口
├── config/
│ └── env.js # API_BASE 配置
├── pages/ # 18 个页面
│ ├── login/ # 微信登录
│ ├── register/ # 补充信息
│ ├── index/ # 首页 (tab)
│ ├── scan/ # 扫码绑定
│ ├── auto-scan/ # 自动扫描蓝牙设备
│ ├── ble-connect/ # BLE 连接
│ ├── bind-success/ # 绑定成功
│ ├── subscribe-prompt/ # 订阅提示
│ ├── subscribe-plans/ # 选择计划
│ ├── subscribe-success/ # 订阅成功
│ ├── wear-check/ # 佩戴检测
│ ├── treatment-setup/ # 护理参数设置
│ ├── treating/ # 护理进行中
│ ├── treatment-done/ # 护理完成
│ ├── history/ # 护理记录 (tab)
│ ├── profile/ # 我的 (tab)
│ ├── help/ # 帮助
│ └── contact/ # 联系我们
├── services/
│ ├── ble.js # proxy → ble/index.js
│ ├── ble/ # BLE 模块(见 3.3
│ └── command-sync.js # 远程指令拉取与执行
└── utils/
├── request.js # HTTP 请求封装
└── api.js # 命名 API 函数
```
### 3.2 页面导航流程
完整用户旅程(从登录到护理完成):
```
login ──→ register(新用户) ──→ index(首页)
┌───────┴──────┐
▼ ▼
scan auto-scan
(扫码绑定) (自动扫描BLE)
│ │
└──────┬───────┘
ble-connect
(蓝牙连接设备)
bind-success
(绑定成功)
┌──────┴──────┐
▼ ▼
subscribe-prompt (已订阅则跳过)
(提示订阅)
subscribe-plans
(选择计划)
subscribe-success ──→ wear-check
(佩戴检测)
treatment-setup
(设置护理参数)
treating
(护理中)
treatment-done
(护理完成,同步记录)
```
底部 Tab 页:首页(index) | 记录(history) | 我的(profile)
### 3.3 BLE 模块拆分
```
services/ble.js # proxy,直接 re-export ble/index.js
services/ble/
├── index.js # barrel,统一导出所有 API
├── protocol.js # 协议常量 + 帧编解码
├── connection.js # 扫描/连接/断开/自动重连
└── commands.js # 指令发送 + ACK 管理
```
**协议模式**`PROTOCOL_MODE = 'vendor_33'`,使用自定义 BLE 服务(FFE0/FFE1/FFE2)而非标准 GATT profile。
**关键设计决策**
- connection.js 维护共享状态(`_deviceId`, `_connected`, `_chars`),commands.js 通过 getter 访问
- 事件系统在 connection.js 中实现(`on/off/emit`),心跳和状态通知作为独立事件分发
- command-sync.js 负责从服务器拉取待执行指令,逐条执行后上报结果
### 3.4 API 调用层
```
页面代码
│ var api = require('../../utils/api')
│ api.getProfile()
api.js 命名函数,封装路径和参数
│ http.get('/api/v1/user/profile')
request.js 统一封装 wx.request
├── 自动附加 Authorization / X-App-Version / X-Platform
├── token 过期前 <24h 自动刷新
├── code 1001/1002 → 清除 token → reLaunch 到登录页
└── 统一错误格式 { code, message }
```
## 4. 管理后台架构
### 4.1 SPA 架构
基于 uni-app (Vue 2) 构建的 H5 单页应用。不使用 vue-router,而是通过动态组件实现页面切换:
```
AdminLayout 固定侧边栏 + 顶栏
└── <keep-alive>
└── <component :is="currentComponent"> 动态视图
```
### 4.2 VIEW_MAP 与 KEEP_ALIVE_VIEWS
`pages/admin/index.vue` 中定义了两个核心映射:
```js
VIEW_MAP = {
dashboard: DashboardView,
device: DeviceListView,
'device-detail': DeviceDetailView,
user: UserListView,
'user-detail': UserDetailView,
subscription: SubscriptionView,
record: RecordView,
log: LogView,
settings: SettingsView
}
KEEP_ALIVE_VIEWS = [
'DeviceListView', 'UserListView',
'SubscriptionView', 'RecordView', 'LogView'
]
```
列表页被 keep-alive 缓存,从详情页返回时保留滚动位置和筛选状态。详情页(device-detail, user-detail)通过 `viewKey` 携带 ID,保证每次进入重新挂载。
导航通过 `$emit('navigate', viewName, props)` 冒泡到 index.vue,由 `onNavigate` 更新 `currentView``viewProps`
### 4.3 API 调用模式
```
View 组件
│ import { get, post } from '../utils/request'
│ get('/api/v1/admin/users')
utils/request.js 基于 uni.request 封装
├── 自动附加 admin_token (Bearer)
├── code 1001/1002 → 清除 token → reLaunch 到登录页
└── 统一 resolve(data) / reject(error)
```
状态管理:Pinia store (`store/user.js`) 管理 admin token 和登录信息。
### 4.4 构建和部署
- 框架:uni-app,编译目标 H5
- 部署方式:构建产物上传至腾讯云 COS 静态托管,或直接部署到 SCF
- 菜单项:仪表盘、设备管理、用户管理、订阅管理、护理记录、操作日志、系统设置
## 5. 数据流
### 5.1 支付流程
```
用户点击购买 后端 微信支付
│ │ │
│ api.purchase(plan) │ │
├─────────────────────────────>│ │
│ │ (当前: 返回 order_id) │
│ { order_id, payment_params }│ │
│<─────────────────────────────│ │
│ │ │
│ === 正式支付流程(规划中) ====│ │
│ wx.requestPayment(params) │ │
│ ────────────────────────────┼───────────────────────────>│
│ │ 支付回调 (notify) │
│ │<───────────────────────────│
│ │ 验签 → 更新 subscription │
│ │ subscriptionDao.purchase() │
│ │ (extend 模式,叠加天数) │
│ │ │
│ === 开发环境替代方案 ========│ │
│ api.mockPurchase(plan) │ │
├─────────────────────────────>│ │
│ │ 直接激活订阅 │
│ { status: 'active' } │ │
│<─────────────────────────────│ │
```
订阅模型:`subscriptionDao.purchase()` 采用 extend 模式 —— 如已有有效订阅,在现有到期日基础上叠加天数,而非覆盖。
### 5.2 护理记录同步流程
```
treating 页面 BLE 设备 后端
│ │ │
│ ble.setParams({...}) │ │
├─────────────────────────────>│ │
│ ACK │ │
│<─────────────────────────────│ │
│ ble.startTreatment() │ │
├─────────────────────────────>│ │
│ status notify (周期) │ │
│<─────────────────────────────│ │
│ ...护理进行中... │ │
│ ble.stopTreatment() │ │
├─────────────────────────────>│ │
│ treatment_complete notify │ │
│<─────────────────────────────│ │
│ │ │
│ 跳转 treatment-done 页面 │
│ │
│ api.syncTreatment({ │
│ device_id, session_id, │
│ start_time, end_time, │
│ regions, duration_ms, │
│ mode, wavelength, │
│ battery, temperature, │
│ pd_values ... │
│ }) │
├───────────────────────────────────────────────────────>│
│ treatmentDao.create() │
│ treatmentDao. │
│ updateDevice() │
│ { record_id } │
│<───────────────────────────────────────────────────────│
```
### 5.3 设备绑定流程
```
用户 小程序 后端
│ │ │
│ 扫码/自动扫描获取 device_id│ │
│─────────────────────────────│ │
│ │ api.bindDevice(deviceId) │
│ ├───────────────────────────>│
│ │ │ 检查:用户未绑定其他设备
│ │ │ 检查:设备存在于 devices 表
│ │ │ 取消旧的 pending 绑定
│ │ │ 创建 pending 绑定 + bind_token
│ │ { device_id, bind_token } │
│ │<───────────────────────────│
│ │ │
│ │ BLE 连接设备 │
│ │ ble.connect(deviceId) │
│ │ ble.bindDevice(bind_token) │
│ │ ──BLE──> 设备 │
│ │ <──ACK── 设备 │
│ │ │
│ │ api.confirmBind( │
│ │ deviceId, bind_token) │
│ ├───────────────────────────>│
│ │ │ bindingDao.confirmBind()
│ │ │ pending → active
│ │ { message: 'success' } │
│ │<───────────────────────────│
│ │ │
│ 跳转 bind-success 页面 │ │
│<────────────────────────────│ │
```
绑定约束:一个用户同时只能绑定一台设备;绑定前需先通过 BLE 与设备完成配对确认。
+335
查看文件
@@ -0,0 +1,335 @@
# 部署指南
本文档面向将 jw-beauty 项目部署到腾讯云生产环境的运维人员。
---
## 1. 部署架构
```
┌─────────────┐ HTTPS ┌──────────────────┐
│ 微信小程序 │ ───────────────► │ SCF HTTP 函数 │
└─────────────┘ │ jw-beauty-api │
│ (Node.js 18) │
┌─────────────┐ HTTPS │ │ VPC 内网 ┌──────────────┐
│ 管理后台H5 │ ──► COS/CDN │ scf_bootstrap │ ──────────────────► │ TencentDB │
│ (UniApp) │ │ → local-server │ │ MySQL 5.7+ │
└─────────────┘ └──────────────────┘ └──────────────┘
│ COS SDK
┌──────────────────┐
│ COS Bucket │
│ 头像/固件/后台H5 │
└──────────────────┘
```
| 组件 | 服务 | 说明 |
|------|------|------|
| 后端 API | 腾讯云 SCF (HTTP 函数) | Express 应用,通过 scf_bootstrap 启动 |
| 数据库 | TencentDB for MySQL | 同 VPC 内网连接,端口 3306 |
| 对象存储 | COS | 存放头像、固件包、管理后台静态文件 |
| API 域名 | api.vsai.net.cn | 指向 SCF 函数 URL / API 网关 |
| CDN 域名 | tx.vsai.net.cn | COS 自定义域名,用于头像和固件下载 |
| 小程序 | 微信小程序 | 通过微信开发者工具上传并提审 |
---
## 2. 后端部署(SCF
### 2.1 打包
部署包以 `server/` 为根目录打包,包含以下文件和目录:
```
index.js # SCF 入口 (exports.main_handler)
package.json
package-lock.json
scf_bootstrap # HTTP 函数启动脚本
scripts/ # local-server.js 等
src/ # 应用源码
sql/ # schema.sql
node_modules/ # 依赖
```
**不要**`.env` 文件打进部署包。
打包命令:
```bash
cd server
npm install --production
rm -f /tmp/hox-http-function.zip
zip -qry /tmp/hox-http-function.zip \
index.js package.json package-lock.json \
scripts scf_bootstrap src sql node_modules
```
### 2.2 scf_bootstrap 配置
当前使用 HTTP 函数模式,`scf_bootstrap` 内容:
```bash
#!/bin/bash
set -e
export PORT=9000
node scripts/local-server.js
```
`scf_bootstrap` 必须有可执行权限。SCF 平台会直接运行此文件启动 HTTP 服务,监听 `PORT` 端口。
> 备注:`index.js` 中的 `main_handler` 是事件函数入口,目前未使用。如果切换到事件函数触发模式,SCF 入口改为 `index.main_handler`。
### 2.3 环境变量设置
在 SCF 控制台的函数配置中添加以下环境变量:
| 变量名 | 必填 | 说明 |
|--------|------|------|
| `NODE_ENV` | 是 | 必须设为 `production` |
| `PORT` | 否 | 默认 `9000`,scf_bootstrap 已设置 |
| `TENCENT_SECRET_ID` | 是 | 腾讯云 API 密钥 IDCOS 签名用) |
| `TENCENT_SECRET_KEY` | 是 | 腾讯云 API 密钥 Key |
| `TENCENT_REGION` | 否 | 默认 `ap-guangzhou` |
| `DB_HOST` | 是 | 数据库内网地址 |
| `DB_PORT` | 否 | 默认 `3306` |
| `DB_USER` | 是 | 数据库用户名 |
| `DB_PASSWORD` | 是 | 数据库密码 |
| `DB_NAME` | 否 | 默认 `jw_beauty` |
| `COS_BUCKET` | 否 | 默认 `jw-bucket-1426323813` |
| `COS_REGION` | 否 | 默认 `ap-guangzhou` |
| `COS_CDN_DOMAIN` | 否 | 默认 `tx.vsai.net.cn` |
| `WECHAT_APPID` | 是 | 微信小程序 AppID |
| `WECHAT_SECRET` | 是 | 微信小程序 AppSecret |
| `JWT_SECRET` | 是 | 用户 JWT 签名密钥(随机长字符串) |
| `ADMIN_JWT_SECRET` | 是 | 管理员 JWT 签名密钥(随机长字符串) |
| `ADMIN_USERNAME` | 是 | 初始管理员用户名(不要用默认 admin) |
| `ADMIN_PASSWORD` | 是 | 初始管理员密码(不要用默认 admin) |
> 生产环境安全检查:代码在 `NODE_ENV=production` 时会校验 `JWT_SECRET` 和 `ADMIN_JWT_SECRET` 不是默认值,`ADMIN_USERNAME` / `ADMIN_PASSWORD` 不是 `admin/admin`,否则启动报错。
参考模板文件:`server/.env.production.example`
### 2.4 VPC 网络配置
SCF 函数必须配置与 TencentDB 相同的 VPC 和子网,才能通过内网地址访问数据库。
操作步骤:
1. 在 SCF 控制台 → 函数管理 → 选择函数 → 函数配置 → 网络配置
2. 选择与 TencentDB 实例相同的 VPC 和子网
3. 确认安全组允许 SCF 访问数据库端口(默认 3306)
### 2.5 注意事项
- **冷启动**SCF 冷启动时需加载 Node.js 运行时和 `node_modules`,首次请求延迟较高(约 1-3 秒)。可配置预置并发实例减少冷启动。
- **超时设置**:建议函数超时设为 30 秒以上。
- **内存**:建议 256MB 或以上。
- **日志**:错误日志通过 `console.error` 输出,可在 SCF 日志服务中查看。
---
## 3. 数据库初始化
### 3.1 连接 TencentDB
本地连接 TencentDB 需要:
- 数据库已开启公网访问,或通过 VPN/跳板机连接内网
- 安全组白名单中已添加本机公网 IP
- `DB_PORT` 使用控制台显示的公网端口
`server/.env` 中配置连接信息后执行:
```bash
cd server
npm install
npm run db:init
```
### 3.2 执行 schema.sql
`db:init` 脚本会自动执行 `sql/schema.sql`,创建以下业务表:
| 表名 | 说明 |
|------|------|
| `users` | 用户信息 |
| `devices` | 设备(产品码) |
| `bindings` | 用户-设备绑定关系 |
| `subscriptions` | 订阅记录 |
| `treatment_records` | 护理记录 |
| `device_events` | 设备事件 |
| `device_commands` | 远程指令队列 |
| `operation_logs` | 操作日志 |
| `admin_accounts` | 管理员账户 |
| `system_settings` | 系统设置 |
| `firmware_files` | 固件版本 |
同时写入默认系统设置(月卡价格、年卡价格、试用天数等)。
### 3.3 初始管理员创建
`db:init` 会使用环境变量 `ADMIN_USERNAME` / `ADMIN_PASSWORD` 创建初始管理员账户。
首次登录后应立即在管理后台修改默认密码。
---
## 4. 管理后台部署(COS
### 4.1 构建
确认 `admin-console/src/config/env.js``ENV` 已设为 `prod`(或 API 地址正确):
```js
const ENV = 'prod'
```
然后构建:
```bash
cd admin-console
npm install
npm run build:h5
```
构建产物位于 `admin-console/dist/build/h5/`
### 4.2 上传到 COS
方式一:使用部署脚本(推荐)
```bash
cd admin-console
npm run deploy:cos
```
脚本会读取 `server/.env` 中的 COS 凭证,将构建产物上传到 COS bucket 的 `admin/` 前缀下。
可通过环境变量自定义前缀:
```bash
ADMIN_COS_PREFIX=admin-test/ npm run deploy:cos
```
方式二:手动上传
通过 COS 控制台或 COSCMD 工具将 `dist/build/h5/` 目录下所有文件上传到 bucket 的 `admin/` 目录。
### 4.3 CDN/域名配置
管理后台通过 COS 的自定义域名(`tx.vsai.net.cn`)访问:
- 在 COS 控制台为 bucket 绑定自定义域名
- 配置 CDN 加速(可选)
- 访问地址:`https://tx.vsai.net.cn/admin/`
### 4.4 base path 设置
管理后台的路由 base path 为 `/admin/`,确保 COS 上传前缀与此一致。
如果需要配置单页应用(SPA)的 history 模式回退,可在 COS 静态网站配置中设置错误文档为 `/admin/index.html`
---
## 5. 小程序发布
### 5.1 环境切换
发布前将 `miniprogram/config/env.js` 中的 `ENV` 改为 `prod`
```js
var ENV = 'prod'
```
### 5.2 微信开发者工具上传
1. 打开微信开发者工具
2. 导入项目目录 `miniprogram/`
3. 确认 AppID 正确
4. 点击"上传",填写版本号和备注
5. 在微信公众平台 → 版本管理 → 提交审核
### 5.3 审核注意事项
- **用户协议** 和 **隐私政策** 页面必须存在且内容完整,否则审核不通过
- 涉及蓝牙权限的小程序需要在 `app.json` 中声明并说明用途
- 隐私信息收集弹窗需符合微信规范
- 建议提交审核前在体验版充分测试
---
## 6. 域名和证书
### 6.1 API 域名
| 域名 | 用途 | 指向 |
|------|------|------|
| `api.vsai.net.cn` | 后端 API | SCF 函数 URL / API 网关 |
需要配置 HTTPS 证书(腾讯云可申请免费 SSL 证书)。
### 6.2 COS CDN 域名
| 域名 | 用途 | 指向 |
|------|------|------|
| `tx.vsai.net.cn` | 头像/固件下载/管理后台 | COS bucket CDN |
在 COS 控制台绑定自定义域名并配置 HTTPS。
### 6.3 小程序合法域名配置
在微信公众平台 → 开发管理 → 开发设置 → 服务器域名中配置:
| 类型 | 域名 |
|------|------|
| request 合法域名 | `https://api.vsai.net.cn` |
| downloadFile 合法域名 | `https://tx.vsai.net.cn` |
| uploadFile 合法域名 | `https://api.vsai.net.cn` |
---
## 7. 上线检查清单
### 环境配置
- [ ] `NODE_ENV=production` 已设置
- [ ] `JWT_SECRET``ADMIN_JWT_SECRET` 已更换为强随机字符串
- [ ] `ADMIN_USERNAME` / `ADMIN_PASSWORD` 已更换默认值
- [ ] 数据库连接使用 VPC 内网地址
- [ ] 安全组规则正确(SCF → MySQL 3306
- [ ] COS 凭证配置正确
### 数据库
- [ ] `schema.sql` 已执行成功,所有表已创建
- [ ] 初始管理员已创建并更改了默认密码
- [ ] 默认系统设置已写入 `system_settings`
### 后端
- [ ] `GET /health` 返回 `{"code":0}`
- [ ] `POST /api/v1/admin/login` 可正常登录
- [ ] `GET /api/v1/admin/dashboard` 返回统计数据
- [ ] `GET /api/v1/admin/settings` 返回系统设置
### 管理后台
- [ ] 构建时 `ENV` 已设为 `prod`
- [ ] 构建产物已上传到 COS `admin/` 目录
- [ ] `https://tx.vsai.net.cn/admin/` 可正常访问
- [ ] 管理员可登录并查看仪表盘
### 小程序
- [ ] `miniprogram/config/env.js``ENV='prod'`
- [ ] 微信公众平台已配置 request/download/upload 合法域名
- [ ] 小程序登录流程正常
- [ ] 蓝牙扫码绑定流程正常
- [ ] 护理记录同步正常
- [ ] 用户协议和隐私政策页面内容完整
### 安全
- [ ] `.env` 文件未包含在部署包中
- [ ] 生产环境 `mock-bind``mock-purchase` 接口已自动禁用
- [ ] CORS 策略按需收紧(当前为 `*`
- [ ] Rate limiting 已生效(登录 15min/10次,管理员 15min/5次)
文件差异内容过多而无法显示 加载差异
+34
查看文件
@@ -0,0 +1,34 @@
# 开发文档
光子美容仪项目开发文档,面向开发者和运维人员。
## 目录
| 文档 | 说明 | 适合谁读 |
|------|------|---------|
| [01-快速开始](01-快速开始.md) | 本地环境搭建、三端启动步骤、常见问题 | 新加入的开发者 |
| [02-配置说明](02-配置说明.md) | 所有环境变量详解、微信/支付/数据库/COS 配置 | 开发者、运维 |
| [03-架构说明](03-架构说明.md) | 系统架构、目录结构、数据流、模块设计 | 需要改代码的开发者 |
| [04-部署指南](04-部署指南.md) | 腾讯云 SCF/COS 部署、数据库初始化、上线检查清单 | 运维、负责发布的人 |
| [05-API接口文档](05-API接口文档.md) | 全部 42 个 API 接口的方法、参数、响应格式 | 前后端开发者 |
## 项目结构
```
jw-beauty/
├── miniprogram/ 小程序(微信原生)
├── server/ 后端(Express + SCF
├── admin-console/ 管理后台(Vue 3 + uni-app H5
└── docs/ 文档
├── dev/ 开发文档(本目录)
├── design/ 设计文档
├── protocols/ BLE 协议文档
└── deploy/ 部署笔记
```
## 快速链接
- 本地启动后端:`cd server && npm install && npm start`
- 健康检查:`curl http://localhost:3000/health`
- 管理后台开发:`cd admin-console && npm install && npm run dev:h5`
- 数据库初始化:`cd server && npm run db:init`