Files
thebet365/docs/四套主题Docker部署任务.md
Mars e0ce36cc48 docs: 新增四套主题 Docker 部署与邀请链接选主题任务文档
汇总多 player 容器部署、分支同步、发版流程及后台按主题生成邀请链接的阶段 F 设计,便于下次直接实施。
2026-06-22 14:57:56 +08:00

595 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 四套主题 Docker 生产部署任务
> **目标**:在同一台服务器、**同一套 Docker Compose 栈**内,同时运行 4 套玩家端主题4 个 player 容器 + 1 套共用 api/admin/db
> **适用分支**`main`(暗金)、`theme-2`Pinnacle 蓝白)、`theme-3`(统一移动端视觉)、`theme-4`(海军蓝暗色极简)。
> **关联文档**[Docker部署指南.md](./Docker部署指南.md)、[docker/镜像构建与导出.md](./docker/镜像构建与导出.md)、[AGENTS.md](../AGENTS.md)「主题分支」章节。
---
## 一、架构总览
```text
域名 A主站 → 127.0.0.1:8082 → thebet365-player 镜像 tag: main
域名 Btheme-2 → 127.0.0.1:8083 → thebet365-player2 镜像 tag: theme-2
域名 Ctheme-3 → 127.0.0.1:8084 → thebet365-player3 镜像 tag: theme-3
域名 Dtheme-4 → 127.0.0.1:8085 → thebet365-player4 镜像 tag: theme-4
管理后台 → 127.0.0.1:8081 → thebet365-admin 镜像 tag: latest或统一 IMAGE_TAG
thebet365-apiDocker 内网,不映射宿主机端口)
thebet365-postgres + thebet365-redis
```
| 要点 | 说明 |
|------|------|
| 不是「一个容器四套皮肤」 | 是 **4 个 player 容器**,各跑各自构建好的静态资源 |
| 后端共用 | api / postgres / redis / uploads **只有一套**,账号与余额互通 |
| 本地开发 | 仍只需 `pnpm dev:player``:5173`**切分支**预览不同主题;不必本地开 4 端口 |
| `deploy-update.sh` | 默认只维护 **一套** api/player/admin多主题 player2~4 需 **单独 load + compose up** |
| 邀请注册链接 | 当前仅 `VITE_PLAYER_URL` 单域名;需 **阶段 F** 实现后台按主题选链接(见第十三节) |
---
## 二、任务清单(实施顺序)
按顺序勾选,下次上线可直接照着做。
### 阶段 A — 仓库改动(一次性)
- [ ] **A1** 新增 `docker-compose.themes.yml`player2 / player3 / player4 服务定义)
- [ ] **A2** 更新 `.env.docker.example``PLAYER2_*` ~ `PLAYER4_*``CORS_ORIGINS` 示例)
- [ ] **A3** 更新 `docker-compose.prod.yml``player` 使用 `PLAYER_IMAGE_TAG`(与 `IMAGE_TAG` 解耦,见下文片段)
- [ ] **A4**(可选)在 `docs/Docker部署指南.md` 增加「多主题」小节链接到本文
- [ ] **A5**(可选)在 `AGENTS.md` 文档索引增加本文链接
### 阶段 B — 各主题分支同步 main 功能(发版前每个 theme 分支各做一遍)
- [ ] **B1**`theme-2` / `theme-3` / `theme-4` 同步 API、Admin、shared、迁移**禁止**整目录覆盖 player
- [ ] **B2** Player 侧只做逻辑/i18n **增量合并**,保留各分支 `styles.css` 与主题资源
- [ ] **B3** 各分支本地 `pnpm build``pnpm dev:player` 冒烟
- [ ] **B4** `main` 分支照常维护;若 api/admin 有变更,四个 player 镜像可共用同一 api/admin 包
### 阶段 C — 本地打镜像Windows 构建机)
- [ ] **C1** 四个分支分别打 **player** 镜像tag 互不相同)
- [ ] **C2****api + admin** 一包(在 `main` 或任意已同步分支tag 如 `latest`
- [ ] **C3** 核对 `.manifest.txt``git_commit` 与分支一致
- [ ] **C4** 上传 tar 到服务器(勿覆盖 `.env.docker`
### 阶段 D — 服务器首次启用多主题
- [ ] **D1** 备份:执行 `deploy-update` 前会自动备份;首次改 compose 前建议手动 `./scripts/backup-prod.sh`
- [ ] **D2** `docker load` 四个 player tar + api/admin tar
- [ ] **D3** 编辑 `.env.docker`(端口、镜像 tag、CORS、域名
- [ ] **D4** `docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d`
- [ ] **D5** 宝塔为 4 个玩家域名 + 1 个管理域名配置反代
- [ ] **D6** 执行下方「验收清单」
### 阶段 E — 日常更新(重复)
- [ ] 仅换某一主题 UI → 只 rebuild/load 对应 player tag → `up -d playerN`
- [ ] API/Admin/迁移变更 → `deploy-update.sh` 更新 api/admin必要时四个 player 无需重建
- [ ] 发版后强刷浏览器 / 清 CDN
### 阶段 F — 邀请链接按主题选择(功能开发,可与 D 并行)
- [ ] **F1** API`SystemConfig` 存四套玩家站域名配置(见第十三节)
- [ ] **F2** 管理端「全局设置」可编辑主题名称 + 公网 URL + 默认项
- [ ] **F3** 邀请面板 / 邀请历史:下拉选择主题后再复制注册链接
- [ ] **F4** 代理端邀请弹窗同样可读主题列表并选择(只读,不能改 URL
- [ ] **F5** 部署四套主题后,在全局设置填齐 4 个 https 域名并验收邀请链接
---
## 三、仓库待实现:`docker-compose.themes.yml`
> **任务 A1**:在仓库根目录新建此文件,与 `docker-compose.prod.yml` 合并使用。
```yaml
# 四套主题扩展 — 与 docker-compose.prod.yml 一起使用:
# docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d
services:
player2:
image: thebet365-player:${PLAYER2_IMAGE_TAG:-theme-2}
container_name: thebet365-player2
depends_on:
api:
condition: service_healthy
ports:
- '${BIND_ADDR:-127.0.0.1}:${PLAYER2_PORT:-8083}:80'
healthcheck:
test: ['CMD-SHELL', 'wget -q -O /dev/null http://127.0.0.1/ || exit 1']
interval: 10s
timeout: 5s
retries: 6
start_period: 10s
restart: unless-stopped
networks:
- thebet365
player3:
image: thebet365-player:${PLAYER3_IMAGE_TAG:-theme-3}
container_name: thebet365-player3
depends_on:
api:
condition: service_healthy
ports:
- '${BIND_ADDR:-127.0.0.1}:${PLAYER3_PORT:-8084}:80'
healthcheck:
test: ['CMD-SHELL', 'wget -q -O /dev/null http://127.0.0.1/ || exit 1']
interval: 10s
timeout: 5s
retries: 6
start_period: 10s
restart: unless-stopped
networks:
- thebet365
player4:
image: thebet365-player:${PLAYER4_IMAGE_TAG:-theme-4}
container_name: thebet365-player4
depends_on:
api:
condition: service_healthy
ports:
- '${BIND_ADDR:-127.0.0.1}:${PLAYER4_PORT:-8085}:80'
healthcheck:
test: ['CMD-SHELL', 'wget -q -O /dev/null http://127.0.0.1/ || exit 1']
interval: 10s
timeout: 5s
retries: 6
start_period: 10s
restart: unless-stopped
networks:
- thebet365
```
### 任务 A3调整 `docker-compose.prod.yml` 的 `player` 服务
`player.image``${IMAGE_TAG}` 改为独立变量(避免与 api/admin 的 `IMAGE_TAG` 绑死):
```yaml
player:
image: thebet365-player:${PLAYER_IMAGE_TAG:-main}
# build / ports / healthcheck 等其余保持不变
```
> `player2~4` **不要**写 `build:`,生产只 load 预构建镜像。
---
## 四、`.env.docker` 配置模板
> **任务 A2**:追加到 `.env.docker.example`;服务器 `.env.docker` 按真实域名填写。
```env
# ── 共用后端 ──
IMAGE_TAG=latest
ADMIN_PORT=8081
BIND_ADDR=127.0.0.1
# 管理端邀请链接默认指向的主玩家站(勿带末尾 /
VITE_PLAYER_URL=https://www.example.com
# 四个玩家站域名都需列入(逗号分隔,无空格或统一 trim
CORS_ORIGINS=https://www.example.com,https://theme2.example.com,https://theme3.example.com,https://theme4.example.com,https://admin.example.com
# ── 四套 player 镜像 tag 与宿主机端口 ──
PLAYER_IMAGE_TAG=main
PLAYER_PORT=8082
PLAYER2_IMAGE_TAG=theme-2
PLAYER2_PORT=8083
PLAYER3_IMAGE_TAG=theme-3
PLAYER3_PORT=8084
PLAYER4_IMAGE_TAG=theme-4
PLAYER4_PORT=8085
```
修改 `CORS_ORIGINS` 后必须重启 api
```bash
docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker restart api
```
---
## 五、分支合并代码main → theme-*
> **发版前**在每个 `theme-*` 分支执行。目标:功能与 main 一致,**皮肤不变**。
### 5.1 禁止事项
| 禁止 | 原因 |
|------|------|
| `git merge main` 后直接发 player | 易把 main 暗金样式大量带入 |
| `git checkout main -- apps/player/` | 整目录覆盖会冲掉主题 CSS/组件 |
| `git checkout main -- apps/player/src/i18n/` | 会冲掉主题分支已有措辞 |
### 5.2 推荐整目录同步API / Admin / shared / 迁移)
在目标主题分支上(示例 `theme-2`
```bash
git checkout theme-2
git fetch origin
# 同步后端与共享包(可按需增减路径)
git checkout origin/main -- apps/api
git checkout origin/main -- apps/admin
git checkout origin/main -- packages/shared
git checkout origin/main -- pnpm-lock.yaml
git checkout origin/main -- pnpm-workspace.yaml
# 若有新迁移,务必带上
git checkout origin/main -- apps/api/prisma/migrations
git checkout origin/main -- apps/api/prisma/schema.prisma
git status # 确认没有误改 apps/player 大段样式文件
git commit -m "sync: api/admin/shared/migrations from main"
```
### 5.3 Player只做逻辑与文案增量
**方式 1 — 按文件 cherry-pick有明确 commit 时)**
```bash
git log origin/main --oneline -- apps/player/src/composables apps/player/src/stores
git cherry-pick <commit-hash> # 冲突时保留 theme 分支的 styles / 主题组件
```
**方式 2 — 按目录选择性 checkout仅非 UI 目录)**
```bash
# 示例:只同步 stores、composables、api 封装(执行前确认路径在 main 有变更)
git checkout origin/main -- apps/player/src/stores
git checkout origin/main -- apps/player/src/composables
git checkout origin/main -- apps/player/src/api
```
**方式 3 — i18n 只合并新增 key**
- 对比 `apps/player/src/i18n/*.ts`,手工把 main **新增的 key** 补进三语文件
- 不要用 main 文件整文件覆盖
### 5.4 合并后本地验证(每个 theme 分支)
```bash
pnpm install
pnpm db:generate # 若 schema 有变
pnpm --filter @thebet365/shared build
pnpm --filter @thebet365/player build
pnpm dev:api # 另开终端
pnpm dev:player # http://localhost:5173 目视确认仍是本主题皮肤
```
### 5.5 main 分支
- 日常功能开发在 `main` 完成后再同步到各 theme 分支
- `main` 自身 player 镜像 tag 建议使用 `main``latest`(与 `.env.docker``PLAYER_IMAGE_TAG` 一致即可)
---
## 六、构建与上传镜像
### 6.1 四个 player 镜像Windows CMD
```bat
cd C:\path\to\thebet365
git checkout main
docs\docker\build-and-export-player.bat --tag main
git checkout theme-2
docs\docker\build-and-export-player.bat --tag theme-2
git checkout theme-3
docs\docker\build-and-export-player.bat --tag theme-3
git checkout theme-4
docs\docker\build-and-export-player.bat --tag theme-4
```
产物(项目根目录,已在 `.gitignore`
| 文件 | 加载后镜像名 |
|------|----------------|
| `thebet365-player-main.tar` | `thebet365-player:main` |
| `thebet365-player-theme-2.tar` | `thebet365-player:theme-2` |
| `thebet365-player-theme-3.tar` | `thebet365-player:theme-3` |
| `thebet365-player-theme-4.tar` | `thebet365-player:theme-4` |
### 6.2 api + admin 一包
```bat
git checkout main
docs\docker\build-and-export-images.bat --tag latest
```
或 Linux`./docs/docker/build-and-export-images.sh --tag latest`
### 6.3 上传至服务器
目录示例:`/www/wwwroot/thebet365`
| 必传 | 说明 |
|------|------|
| 四个 player tar | 四套皮肤 |
| `thebet365-images-latest.tar`(或带版本 tag | api + admin |
| `docker-compose.prod.yml` | 若仓库有更新 |
| `docker-compose.themes.yml` | **首次多主题必传** |
| `scripts/` | 若部署脚本有更新 |
**勿覆盖**`.env.docker`、Docker 数据卷、`backups/`
---
## 七、服务器部署命令
### 7.1 首次启用四套主题
```bash
cd /www/wwwroot/thebet365
chmod +x scripts/*.sh
# 导入全部镜像
docker load -i thebet365-images-latest.tar
docker load -i thebet365-player-main.tar
docker load -i thebet365-player-theme-2.tar
docker load -i thebet365-player-theme-3.tar
docker load -i thebet365-player-theme-4.tar
# 编辑 .env.docker见第四节模板后启动
docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d
```
若当前环境已由 `deploy-first.sh` 跑通,只需 **load 新 player 镜像 + 合并 compose + up -d player2 player3 player4**,并调整 `.env.docker`
### 7.2 更新共用 api/admin
仍用现有脚本(**不会**自动更新 player2~4
```bash
./scripts/deploy-update.sh --images thebet365-images-latest.tar --tag latest
```
之后确认多主题 compose 仍生效:
```bash
docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d
```
### 7.3 只更新某一主题(例如 theme-4
```bash
docker load -i thebet365-player-theme-4.tar
docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d player4
```
其他主题容器不受影响。
### 7.4 回滚某一 player
```bash
# 加载旧 tag 的 tar 后
docker compose -f docker-compose.prod.yml -f docker-compose.themes.yml --env-file .env.docker up -d player3
```
api 回滚仍用 `./scripts/rollback.sh --to <tag>`**不**回滚数据库)。
---
## 八、宝塔 / Nginx 反代
每个玩家站 **只反代到对应端口**,容器内已处理 `/api``/uploads`,宝塔无需再写 API 规则。
| 宝塔网站 | `proxy_pass` |
|----------|----------------|
| 主站main | `http://127.0.0.1:8082` |
| theme-2 站 | `http://127.0.0.1:8083` |
| theme-3 站 | `http://127.0.0.1:8084` |
| theme-4 站 | `http://127.0.0.1:8085` |
| 管理后台 | `http://127.0.0.1:8081` |
示例:
```nginx
location / {
proxy_pass http://127.0.0.1:8082;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
```
四套站点分别申请 SSL`CORS_ORIGINS` 使用 **https** 域名。
---
## 九、验收清单
部署完成后逐项检查:
- [ ] `docker compose ... ps` — api、admin、player、player2、player3、player4 均为 **healthy**
- [ ] 四个玩家域名首页 UI 皮肤互不相同
- [ ] 各站登录同一账号,余额一致
- [ ] 各站下注、充值、站内信、公告正常
- [ ] 管理后台 `:8081` 正常;员工菜单与 Inbox 开关已配置(见 [Docker部署指南.md](./Docker部署指南.md) 第八节步骤 5
- [ ] `npx prisma migrate status`(在 api 容器内)无 pending 迁移
- [ ] 浏览器 Network 无 CORS 报错(若有,检查 `CORS_ORIGINS` 并 restart api
- [ ] theme-4 独有组件(如悬浮客服)仅在 theme-4 站出现
- [ ] **阶段 F 完成后**:邀请面板切换四套主题,复制链接分别打开对应域名 `/register?code=...`
---
## 十、常见问题
| 现象 | 处理 |
|------|------|
| 某站 502 | `docker compose ps` 看对应 player 是否 healthy`docker logs thebet365-player3` |
| 接口 401/403 仅某一域名 | 检查 `CORS_ORIGINS` 是否包含该 https 域名 |
| 四套变成同一皮肤 | 检查是否四个 tag 打错或 `.env.docker``PLAYER*_IMAGE_TAG` 写错 |
| `deploy-update` 后 player2 消失 | 脚本未管理 themes compose重新 `up -d` 并带 `-f docker-compose.themes.yml` |
| 邀请链接域名不对 | **未做阶段 F**:改 `VITE_PLAYER_URL` 重建 admin仅一个默认站**已做阶段 F**:到「全局设置 → 玩家主题站点」核对 URL邀请面板选对应主题 |
| 构建 ENOENT `public/球员` | 清理 `packages/shared/public` 下除 `flags``players` 外的中文目录后重试 |
---
## 十一、与本地开发的区别
| 场景 | 做法 |
|------|------|
| 日常改某一主题 UI | 切到对应分支 → `pnpm dev:player`5173 |
| 本地同时对比 4 套 | 可选:多开终端 `--port 5173/5174/5175/5176`(非必须) |
| 生产 4 套并存 | 4 个 player 容器 + 4 个端口 + 4 个域名 |
---
## 十二、邀请链接按主题选择(阶段 F 详细设计)
> **现状**`apps/admin/src/utils/invite-link.ts` 用构建时注入的 `VITE_PLAYER_URL` 拼链接;四套主题并存时后台无法选择注册落地页。
> **目标**:管理员(及代理)生成/复制邀请链接时,**下拉选择**要落地的玩家主题站;配置存数据库,**改域名不必重建 admin 镜像**。
### 12.1 行为说明
| 角色 | 能力 |
|------|------|
| 平台管理员(`settings.manage` | 在「全局设置」维护主题列表:显示名、公网 URL、是否启用、哪一项为默认 |
| 管理员 / 代理 | 在「邀请」弹窗选主题 → 复制链接 `{所选站}/register?code=xxx` |
| 玩家 | 无感知;任意主题站注册,同一邀请码、同一后端 |
邀请码本身与主题无关(仍走现有 `InvitesService`**仅注册链接里的域名**随所选主题变化。
### 12.2 数据模型(`SystemConfig`
配置键:`player.theme_sites`
JSON 字符串,结构示例:
```json
{
"themes": [
{ "id": "main", "label": "暗金主站", "baseUrl": "https://www.example.com", "enabled": true, "isDefault": true },
{ "id": "theme-2", "label": "Pinnacle 蓝白", "baseUrl": "https://theme2.example.com", "enabled": true, "isDefault": false },
{ "id": "theme-3", "label": "统一移动端", "baseUrl": "https://theme3.example.com", "enabled": true, "isDefault": false },
{ "id": "theme-4", "label": "海军蓝极简", "baseUrl": "https://theme4.example.com", "enabled": true, "isDefault": false }
]
}
```
规则:
- `id` 与 Git 分支 / Docker 镜像 tag 对齐(`main``theme-2``theme-3``theme-4`
- `baseUrl` **勿带末尾 `/`**;保存时 API 侧 trim + 校验 `https?://`
- 有且仅有一个 `isDefault: true`;未配置时 API 回退 `VITE_PLAYER_URL`(兼容旧环境)
- `enabled: false` 的主题不出现在邀请下拉里
### 12.3 API 任务(`apps/api`
**F1 — `SystemConfigService` 新增:**
```typescript
// apps/api/src/shared/config/system-config.service.ts
getPlayerThemeSites(): Promise<PlayerThemeSitesSettings>
updatePlayerThemeSites(data): Promise<PlayerThemeSitesSettings>
listEnabledPlayerThemes(): Promise<PlayerThemePublicOption[]> // 仅 id/label/baseUrl/isDefault
```
**F1 — Admin 控制器:**
| 方法 | 路径 | 权限 | 说明 |
|------|------|------|------|
| GET | `/admin/settings/player-themes` | `settings.manage` | 完整配置(含 disabled |
| PUT | `/admin/settings/player-themes` | `settings.manage` | 保存;写审计 `UPDATE_PLAYER_THEME_SITES` |
| GET | `/admin/player-themes/options` | 登录员工/代理即可 | 仅 `enabled` 主题,供邀请 UI |
代理门户若走 `/manage/*`,在 `auth.controller` 或 manage 控制器增加同等 **GET options**(复用 service
**校验:**
- 至少保留 1 个 `enabled` 主题
- URL 格式合法;禁止重复 `baseUrl`
- 更新后无需重启 api读 DB
### 12.4 管理端任务(`apps/admin`
**F2 — `GlobalSettingsView.vue` 增加卡片「玩家主题站点」:**
- 表格编辑label、baseUrl、enabled、设为默认
- 保存调用 `PUT /admin/settings/player-themes`
- 与第四节四个域名保持一致(部署后首次必填)
**F3 — 邀请 UI**
涉及文件:
- `apps/admin/src/utils/invite-link.ts` — 改为 `buildPlayerRegisterUrl(code, baseUrl?)`
- `apps/admin/src/components/InviteCodePanel.vue` — 加载 options`el-select` 选主题,`registerUrl` 随选择变化
- `apps/admin/src/components/InviteHistoryPanel.vue` — 复制链接前同样选主题(或记住上次选择)
交互建议:
- 默认选中 API 返回的 `isDefault` 主题
- `localStorage``admin_invite_theme_id` 记住上次选择(可选)
- 无配置时回退 `VITE_PLAYER_URL`,与现网行为一致
**F4 — i18n三语同步**
`admin-messages.ts` / `admin-pages*.ts` 增加 key例如
- `invite.theme_site` — 注册落地主题
- `invite.theme_site_hint` — 选择玩家看到的注册页面风格
- `settings.player_themes` — 玩家主题站点
- `settings.player_themes_hint` — 与四套 Docker 玩家域名对应
### 12.5 与 Docker 四套主题的对应关系
部署完四套 player 后,在 **全局设置** 填:
| id | 对应容器 | 示例 baseUrl |
|----|----------|--------------|
| `main` | `thebet365-player` :8082 | `https://www.example.com` |
| `theme-2` | `thebet365-player2` :8083 | `https://theme2.example.com` |
| `theme-3` | `thebet365-player3` :8084 | `https://theme3.example.com` |
| `theme-4` | `thebet365-player4` :8085 | `https://theme4.example.com` |
`VITE_PLAYER_URL` 仍可保留为 **构建默认值****未配置 DB 时的回退**;多主题上线后以 DB 配置为准。
### 12.6 阶段 F 验收
- [ ] 全局设置保存 4 个 URL 后刷新仍生效
- [ ] 邀请面板切换主题,链接域名随之变化,邀请码不变
- [ ] 四套链接均可打开注册页并带 `code` 参数
- [ ] 代理账号邀请弹窗可选主题(不能进全局设置改 URL
- [ ] 禁用某主题后下拉里消失
- [ ] 未配置 DB 时行为与现网一致(`VITE_PLAYER_URL`
### 12.7 实施顺序建议
```text
F1 API 配置读写 → F2 全局设置页 → F3 邀请面板 → F4 代理端 → 部署四套主题后填 URL → 12.6 验收
```
可与 **阶段 A~DDocker 多 player** 并行开发;功能不依赖 player2~4 已上线,但验收需要四个域名可访问。
---
## 十三、文档维护
| 变更类型 | 更新本文 |
|----------|----------|
| 新增 theme-5 | 复制 player4 模式,追加端口 8086 |
| 修改 deploy 脚本支持多 player | 更新第七节命令 |
| 分支合并策略变化 | 更新第五节 |
---
**下次实施入口**
- **基础设施**:阶段 A → B → C → D → 第九节验收
- **邀请多主题**:阶段 F第十二节可与 A~D 并行,四套域名就绪后做 12.6 验收