- 单用户资料接口补上距离:此前只有推荐/附近列表会算距离,资料页和 聊天头部因此无内容可显示。沿用同一套 haversine 与隐私开关。 - 语音/图片消息可限定会员发送,两个开关在管理端「运营配置」中修改 (迁移 032)。校验放在 persistMessageContext,HTTP 与 WebSocket 两条发送路径都覆盖;文本消息永不受限。 - 短信服务关闭时注册不再要求验证码:关掉之后没人能拿到验证码,继续 要求就等于关闭注册通道。重置密码不做同样放宽,那里缺验证码等于 凭手机号夺号。app/config 增加 smsVerification 供客户端决定表单形态。 - 修复 AI 托管账号之间不回复:原规则按「发送方是否托管账号」拦截, 把真人操作测试号的正常对话也挡了。改为标记 worker 自己写入的回复, 只对 AI 生成的消息跳过入队。 - ai.default_model_id 同时接受模型 ID 与名称,填名称时不再被 MySQL 静默转成 0 而使配置失效。 - 聊天媒体留存管理与清理任务(迁移 033,两台线上均已应用)。 新增集成测试均针对真实 MySQL:会员限制、免短信注册、AI 入队规则、 默认模型解析、资料距离。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
429 lines
36 KiB
Markdown
429 lines
36 KiB
Markdown
# im.bchongw.com 正式环境部署记录
|
||
|
||
初次部署日期:2026-08-30
|
||
宝塔项目接管及 H5 发布日期:2026-08-31
|
||
运行方式:宝塔 Go 项目(域名、HTTPS、管理端/H5 网关)+ 独立 MySQL 8.4 LTS(非 Docker)
|
||
|
||
此前 Go 服务由独立 systemd 管理,没有出现在宝塔 Go 项目列表。现已纠正:后端的启动、停止、重启、日志和开机启动均纳入宝塔 Go 项目管理;原 systemd 服务已停止并禁用,保留用于回滚。
|
||
|
||
2026-08-31 已进一步将域名与 HTTPS 从原 HTML 网关迁入 Go 项目:`xingyu_im` 直接绑定 `im.bchongw.com:80`,开启外网映射和 HTTPS(443),HTTP 强制跳转 HTTPS。原 HTML 网关的项目记录已合并,网页文件、发布版本、证书及业务数据全部保留,没有重复绑定同一域名。
|
||
|
||
## 在宝塔哪里操作
|
||
|
||
| 宝塔入口 | 项目 | 用途 |
|
||
| --- | --- | --- |
|
||
| 网站 → Go 项目 | `xingyu_im` | 后端启停/重启、运行日志、环境文件、域名管理、外网映射、SSL 和管理端/H5/API/WSS 网关 |
|
||
| 数据库 → MySQL | `im`(远程数据库类型,实际连接本机 `127.0.0.1:3307`) | 查看与管理现有 IM 数据库 |
|
||
|
||
关闭已打开的设置窗口并刷新宝塔项目列表,进入 `xingyu_im → 域名管理` 即可看到 `im.bchongw.com`、端口 `80`;`SSL` 中可看到有效证书和强制 HTTPS 状态。这里的端口 80 是域名绑定入口,不表示关闭 HTTPS;SSL 监听端口为 443。
|
||
|
||
## 对外地址
|
||
|
||
- API:`https://im.bchongw.com`
|
||
- 健康检查:`https://im.bchongw.com/healthz`
|
||
- WebSocket:`wss://im.bchongw.com/ws`
|
||
- 管理端网页:`https://im.bchongw.com/admin/`
|
||
- uni-app H5:`https://im.bchongw.com/app/`
|
||
- 管理 API:`https://im.bchongw.com/admin/v1`
|
||
|
||
HTTP 会永久重定向到 HTTPS。后端和独立数据库只监听本机回环地址,不直接暴露到公网。
|
||
|
||
## 服务与目录
|
||
|
||
| 项目 | 值 |
|
||
| --- | --- |
|
||
| 宝塔 Go 项目 | `xingyu_im` |
|
||
| Go 监听地址 | `127.0.0.1:18888` |
|
||
| 当前可执行文件 | `/www/server/xingyu-im/bt/xingyu-api` |
|
||
| 启动命令 | `/www/server/xingyu-im/bt/start.sh` |
|
||
| 后端生效环境文件 | `/etc/xingyu-im-bt.env`(`root:www 0640`) |
|
||
| Go 运行用户 | `www` |
|
||
| Go 日志 | `/www/wwwlogs/go/xingyu_im.log` |
|
||
| 运维/接管脚本 | `/www/server/xingyu-im/ops`(仅 root 可访问) |
|
||
| 旧 systemd 服务 | `xingyu-im.service`,已停止并禁用,不能与宝塔 Go 项目同时启动 |
|
||
| 旧后端版本/环境备份 | `/www/server/xingyu-im/releases/20260830-1345`、`/etc/xingyu-im.env` |
|
||
| 上传目录 | `/www/wwwroot/xingyu-data/uploads` |
|
||
| 宝塔站点目录 | `/www/wwwroot/im.bchongw.com` |
|
||
| Go 项目绑定域名 | `im.bchongw.com:80`,外网映射已开启 |
|
||
| 宝塔 Nginx 主配置 | `/www/server/panel/vhost/nginx/go_xingyu_im.conf` |
|
||
| 管理端/H5/WS 路由扩展配置 | `/www/server/panel/vhost/nginx/extension/xingyu_im/xingyu_routes.conf` |
|
||
| Go 项目证书目录 | `/www/server/panel/vhost/cert/xingyu_im`(证书文件链接到 Let's Encrypt 自动续签目录) |
|
||
| 网站访问日志 | `/www/wwwlogs/xingyu_im.log` |
|
||
| 管理端发布根目录 | `/www/wwwroot/xingyu-admin/releases` |
|
||
| 管理端当前版本 | `/www/wwwroot/xingyu-admin/releases/20260831-095050` |
|
||
| 管理端入口软链接 | `/www/wwwroot/im.bchongw.com/admin` |
|
||
| H5 当前版本 | `/www/wwwroot/xingyu-h5/releases/20260831-091056` |
|
||
| H5 入口软链接 | `/www/wwwroot/im.bchongw.com/app` |
|
||
| MySQL 服务 | `xingyu-mysql8.service` |
|
||
| MySQL 版本 | `8.4.11 LTS` |
|
||
| MySQL 监听地址 | `127.0.0.1:3307` |
|
||
| MySQL 配置 | `/etc/xingyu-mysql8.cnf` |
|
||
| MySQL 数据目录 | `/www/server/xingyu-mysql8-data` |
|
||
|
||
服务器原有宝塔 MySQL 5.6 保持不变;项目使用独立 MySQL 8.4 实例,避免影响现有网站。该实例通过宝塔自带的“添加远程数据库”功能接入,数据库条目 ID 为 `3`,没有重新建库或迁移业务数据。MySQL 8 实例本身仍由 `xingyu-mysql8.service` 托管;不要通过宝塔软件商店替换原有 MySQL 5.6。
|
||
|
||
## 常用运维命令
|
||
|
||
```bash
|
||
cd /www/server/panel
|
||
./pyenv/bin/python /www/server/xingyu-im/ops/baota_panel_takeover.py status
|
||
./pyenv/bin/python /www/server/xingyu-im/ops/baota_bind_go_domain.py verify
|
||
systemctl status xingyu-mysql8 --no-pager
|
||
tail -n 200 /www/wwwlogs/go/xingyu_im.log
|
||
curl -fsS http://127.0.0.1:18888/healthz
|
||
curl -fsS https://im.bchongw.com/healthz
|
||
/www/server/nginx/sbin/nginx -t
|
||
```
|
||
|
||
后端重启:在宝塔“网站 → Go 项目 → xingyu_im”中点“重启”。不要再执行 `systemctl restart xingyu-im`。启动脚本会等待旧 Go 进程释放 18888 端口,已修复宝塔立即重启与 go-zero 优雅退出产生的端口冲突。
|
||
|
||
只重新加载 Nginx:
|
||
|
||
```bash
|
||
/etc/init.d/nginx reload
|
||
```
|
||
|
||
验收脚本(会实际重启一次后端,维护窗口使用):
|
||
|
||
```bash
|
||
cd /www/server/panel
|
||
./pyenv/bin/python /www/server/xingyu-im/ops/baota_panel_takeover.py verify
|
||
```
|
||
|
||
## 管理员凭据
|
||
|
||
初始管理员用户名和密码保存在服务器 root 专用文件:
|
||
|
||
```text
|
||
/root/.xingyu-initial-credentials
|
||
```
|
||
|
||
文件权限为 `0600`。首次登录后应在管理端修改密码;引导密码已从 `/etc/xingyu-im.env` 清空,不会在服务重启时重复创建管理员。
|
||
|
||
## HTTPS 与续签
|
||
|
||
- 证书:Let's Encrypt
|
||
- 当前到期时间:2026-11-28
|
||
- 自动续签:`certbot-renew.timer`
|
||
- Nginx 重载钩子:`/etc/letsencrypt/renewal-hooks/deploy/reload-baota-nginx`
|
||
- Go 项目证书文件:`/www/server/panel/vhost/cert/xingyu_im/fullchain.pem`、`privkey.pem`,软链接到 `/etc/letsencrypt/live/im.bchongw.com/` 下的同名文件,续签后无需手动复制。
|
||
- ACME 验证目录:`/www/wwwroot/im.bchongw.com`;Go 路由扩展保留 `/.well-known/acme-challenge/` 的静态验证入口。
|
||
- 2026-08-31 域名迁入 Go 项目后,再次执行证书续签 dry-run 成功。
|
||
|
||
当前续签由 Certbot 负责。不要同时另建一套宝塔自动申请任务;如果以后改用宝塔托管申请,应先安排切换续签机制和证书路径。
|
||
|
||
检查续签任务:
|
||
|
||
```bash
|
||
systemctl status certbot-renew.timer --no-pager
|
||
certbot renew --dry-run --no-random-sleep-on-renew
|
||
```
|
||
|
||
## 前端生产配置
|
||
|
||
uni-app:
|
||
|
||
```dotenv
|
||
VITE_API_ORIGIN=https://im.bchongw.com
|
||
VITE_WS_ORIGIN=wss://im.bchongw.com
|
||
VITE_H5_BASE=/app/
|
||
```
|
||
|
||
以上配置保存在项目 `mobile/.env.production`;开发模式仍默认使用本机接口和根路径。运行 `pnpm type-check` 与 `pnpm build:h5` 后,产物位于 `mobile/dist/build/h5`。
|
||
|
||
管理端:
|
||
|
||
```dotenv
|
||
VITE_BASE=/admin/
|
||
VITE_GLOB_API_URL=/admin/v1
|
||
```
|
||
|
||
管理端和 API 使用同一域名,采用相对接口地址,避免跨域配置和域名切换造成的构建耦合。
|
||
|
||
当前后端 CORS 仅允许 `https://im.bchongw.com`。H5 或管理端部署到其他正式域名后,需要把对应 HTTPS Origin 追加到 `/etc/xingyu-im-bt.env` 的 `IM_ALLOWED_ORIGINS`,再到宝塔 Go 项目中重启。此文件使用 `export KEY=value` 格式,包含密钥,不能放到网站根目录或公开下载。
|
||
|
||
管理端、H5、WebSocket 及 ACME 路由保存在上述 `xingyu_routes.conf` 扩展中,由宝塔 Go 项目主配置自动包含。维护这些路由时编辑扩展文件,执行 `nginx -t` 成功后再重载。H5 发布脚本 `baota_publish_h5.py` 已兼容此布局;不要重新创建同域名的 HTML 项目。
|
||
|
||
### 2026-08-31 管理端登录后 404 修复
|
||
|
||
根因不是缺少伪静态:管理端使用 hash 路由,`#/analytics` 不会发送给 Nginx。原代码的业务路由使用 `dashboard:view` 等权限码作为 `meta.authority`,但路由守卫传入的是 `super` 等角色名,导致已授权页面被错误过滤。
|
||
|
||
本次修改:
|
||
|
||
- 路由初始化从 `/admin/v1/auth/codes` 获取最新权限码,按权限码生成本地业务路由;不再混用角色名,也不受旧浏览器“后端菜单模式”偏好影响。
|
||
- 刷新页面重新加载权限,替换过期的权限缓存;保留登录后回到原深链接的行为。
|
||
- 账号安全页面同样要求登录,仅登录和第三方回调页面公开。
|
||
- 新增 7 项路由回归测试;加上原有权限/路由测试,共 18 项通过。类型检查和生产构建通过。
|
||
- 新包 SHA-256:`d6fa3ed37a710222dabee9c7e72812f8fe1c4821ff31a1014f484ca4c0b8791b`。
|
||
- 新版本通过原子切换 `admin` 软链接上线,旧版 `/www/wwwroot/xingyu-admin/releases/20260830-142433` 保留用于回滚;新目录兼容保留旧版散列资源,避免尚未刷新的标签页加载旧资源时 404。
|
||
- 已验证线上登录页面可渲染、新入口/仪表盘 JS 返回 200、入口 HTML 不缓存、API 健康检查和 H5 正常。新版本的生产管理员实际登录及登录后界面验收尚待用户授权;未通过其他方式绕过登录限制。
|
||
|
||
管理端发布脚本:`/www/server/xingyu-im/ops/baota-publish-admin.sh`。上传构建包至 `/tmp` 后,使用 root 执行:
|
||
|
||
```bash
|
||
bash /www/server/xingyu-im/ops/baota-publish-admin.sh /tmp/admin-build.zip <构建包SHA256>
|
||
```
|
||
|
||
脚本校验构建包、保留旧版本并原子切换网页入口;验证失败自动切回旧版本,不重启 Go、不修改数据库或 Nginx 配置。升级后已打开的管理端页面需要刷新(必要时使用 `Ctrl+F5`)加载新路由代码。
|
||
|
||
## 验收结果
|
||
|
||
- 后端单元测试通过并使用 Linux/amd64 静态二进制发布。
|
||
- 发布文件 SHA-256:`23ab263e16593b6f588e42bf480e08f364f8f46a12cf8c143077b767860b8b30`。
|
||
- 数据库迁移 `001` 至 `026` 全部执行成功,共 66 张业务表。
|
||
- 本机和公网健康检查均返回 HTTP 200。
|
||
- HTTPS 证书链和域名校验通过。
|
||
- 未认证 WSS 握手返回 HTTP 401,证明 WSS 反向代理已进入后端鉴权层。
|
||
- 管理员登录、JWT 会话、RBAC 仪表盘接口通过。
|
||
- 会员套餐公开接口返回 3 个初始套餐。
|
||
- 自动续签 dry-run 成功。
|
||
- Go 项目已设置宝塔开机启动/守护,MySQL 8 服务已设置 systemd 开机启动;本次未执行整机重启测试。
|
||
- 新增 `/swap-xingyu` 1 GB Swap 作为 OOM 保护,`vm.swappiness=10`。
|
||
- 首次管理端发布的 Vue/TypeScript 类型检查及生产构建通过,原生产包 SHA-256:`404b42391f201e4f500f16275941594ae1569459aa44617c8466b021571dcb3f`;当前包见上述登录 404 修复记录。
|
||
- 管理端首页、SPA 路由回退、运行时接口配置和管理员登录 API 均通过线上验收。
|
||
- 真实浏览器访问自动进入 `https://im.bchongw.com/admin/#/auth/login`,页面控制台无错误、无警告。
|
||
- 上一版管理端保留在 `/www/wwwroot/xingyu-admin/releases/20260830-1410`,可通过切换入口软链接快速回滚。
|
||
- 2026-08-31 已通过宝塔原生 Go 项目接口执行重启,PID 发生变化,随后本机及公网健康检查恢复正常。
|
||
- 宝塔 Go 列表接口返回 `xingyu_im`、`run=true`、`listen=[18888]`、`listen_ok=true`。
|
||
- 域名迁入后,宝塔 Go 项目域名接口返回 `im.bchongw.com:80`,外网映射开启;Go 项目 SSL 接口返回证书已启用、强制 HTTPS 已启用、证书到期日 2026-11-28。
|
||
- 域名迁入后,HTTP 健康检查返回 301,HTTPS 健康检查、`/admin/`、`/app/` 均返回 200,未认证 WSS 请求返回 401;证书模拟续签再次通过。本次只平滑重载 Nginx,未重启后端或迁移数据库。
|
||
- 宝塔数据库连接验证通过,IM 业务表数量保持 66 张;原有网站和数据库未替换。
|
||
- H5 类型检查与生产构建通过,发布包 SHA-256:`04f02657050cf0fa4e6d97d3736ec995255f6aef14672048a76266297ff759b0`。
|
||
- H5 启动页 → 登录页真实浏览器跳转通过,生产页面使用 `/app/` 资源基址;favicon 返回 HTTP 200,H5/管理端控制台无错误、无警告。
|
||
- 宝塔面板 URL 使用自签名证书,自动浏览器被证书校验阻止;面板项目列表、数据库连接及启停采用该服务器实际安装的宝塔模块接口验证,未绕过浏览器证书校验。
|
||
|
||
## 本次接管回滚备份
|
||
|
||
- 后端、原站点记录及面板数据库快照:`/www/backup/xingyu-panel-takeover-20260831-085613`
|
||
- H5 发布前 Nginx 配置:`/www/backup/xingyu-h5-publish-20260831-091056`
|
||
- 域名迁入 Go 项目前的项目/域名记录、面板站点数据库快照和原 HTML Nginx 配置:`/www/backup/xingyu-go-domain-20260831-092720`
|
||
- 原后端二进制和原环境文件仍保留;不要在宝塔 Go 项目运行时启动旧 systemd 服务,以免抢占同一端口。
|
||
- 面板数据库快照仅用于灾难恢复,不能直接覆盖当前面板数据库,否则会覆盖其他站点后续变更。正常回滚应仅还原本项目的记录和配置。
|
||
|
||
## 备份范围
|
||
|
||
至少备份以下内容:
|
||
|
||
```text
|
||
/www/server/xingyu-mysql8-data
|
||
/www/wwwroot/xingyu-data/uploads
|
||
/etc/xingyu-im.env
|
||
/etc/xingyu-im-bt.env
|
||
/etc/xingyu-mysql8.cnf
|
||
/www/server/xingyu-im/releases
|
||
/www/server/xingyu-im/bt
|
||
/www/server/xingyu-im/ops
|
||
/www/wwwroot/xingyu-admin/releases
|
||
/www/wwwroot/xingyu-h5/releases
|
||
/www/server/panel/vhost/nginx/go_xingyu_im.conf
|
||
/www/server/panel/vhost/nginx/extension/xingyu_im
|
||
/www/server/panel/vhost/cert/xingyu_im
|
||
/www/server/panel/data/db/site.db
|
||
/www/server/panel/data/db/database.db
|
||
/etc/letsencrypt
|
||
/root/.xingyu-initial-credentials
|
||
```
|
||
|
||
所有包含密钥或密码的备份必须加密并限制访问。
|
||
|
||
## 2026-08-31 测试用户同步上线
|
||
|
||
本次仅发布测试用户相关功能到现有宝塔 Go 项目和同域名管理端/H5,没有迁移托管环境,也没有改变支付、短信、对象存储或第三方登录的配置值。
|
||
|
||
### 数据与显示规则
|
||
|
||
- 已在生产 `im` 库导入批次 `cn-adults-20260831-v1`,共 **100 人:男 50、女 50**;本次 ID 为 1–100,公开编号为 `TESTCN000001` 至 `TESTCN000100`。
|
||
- 每条资料均为 `is_test=1`,有独立的 `test_batch` 字段,昵称带 `测试·` 前缀,个人简介注明虚构测试资料。管理端支持按“测试用户 / 正式注册用户”和批次筛选,客户端的推荐、附近、用户列表和个人主页显示测试标签。
|
||
- 头像为 **10 张 AI 生成的虚构中国成年人肖像(5 男、5 女),每张复用 10 次**,并非 100 张不同头像,也非真实用户照片。生成来源说明保存在发布目录 `avatar-provenance.json`。
|
||
- 仅创建用户、资料及隐私设置,不创建手机号、有效登录密码、登录会话、实名认证、付费会员、订单、动态或聊天记录。隐私设置关闭虚构在线状态、最后活跃时间和距离展示。
|
||
- 导入前正式注册用户为 0;导入后仍为 0。管理端的正式用户、新增、活跃和资料完善率统计排除测试用户,另行显示测试用户数量。
|
||
- 重复运行已验证:`created=0, skipped=100`,不会重复新增或覆盖已存在的资料。
|
||
|
||
### 发布与备份位置
|
||
|
||
| 内容 | 位置 |
|
||
| --- | --- |
|
||
| 发布前数据库、后端、环境文件和发布状态备份 | `/www/backup/xingyu-test-users-20260831-113046` |
|
||
| 发布结果记录 | `/www/backup/xingyu-test-users-20260831-113046/result.json` |
|
||
| 新后端、导入工具、头像、迁移和前端压缩包 | `/www/server/xingyu-im/releases/test-users-20260831-113046` |
|
||
| 新管理端目录 | `/www/wwwroot/xingyu-admin/releases/test-users-20260831-113046` |
|
||
| 新 H5 目录 | `/www/wwwroot/xingyu-h5/releases/test-users-20260831-113046` |
|
||
| 上一管理端目录(保留) | `/www/wwwroot/xingyu-admin/releases/20260831-095050` |
|
||
| 上一 H5 目录(保留) | `/www/wwwroot/xingyu-h5/releases/20260831-091056` |
|
||
| 发布脚本 | `/www/server/xingyu-im/ops/baota_publish_test_users.py` |
|
||
|
||
发布包 SHA-256:`9a783aef2f6b37d025a0e33454081d43136f06a863c2c80cb9c87e973627933a`。
|
||
|
||
后端 SHA-256:`92b306000ab787e2eb20e69daf25cc3374d082a88f7301e24811a2b7d0022d9d`。
|
||
|
||
管理端 ZIP SHA-256:`eafa92003b31ce78ca24b28576c4dfc5e45a99754de5d004b3c0727575b71e30`。
|
||
|
||
H5 ZIP SHA-256:`e10e213e293776c67f8e248eaf2d56735bd122ce6d279a6a156efc2cccce0b57`。
|
||
|
||
### 迁移和运行目录注意事项
|
||
|
||
生产原有迁移 001–026 校验一致,本次仅新增执行 **028_test_users.sql**。工作区中另一批原生 App 第三方登录功能未合并到本次后端发布,**027_app_oauth_login.sql 仍未执行**。不要因版本号存在间隔而直接补执行它,后续发布该功能应单独评估、部署和验证。
|
||
|
||
发布目录中的 `backend-source.zip` 是本次实际构建的后端源码快照,已隔离未发布的原生 OAuth 改动;本地对应源码目录为 `.tools/test-users-release-20260831/backend`。当前开发工作区并不等同于这份生产快照,不能以最新的工作区内容代替本次发布产物复现。管理端和 H5 以本次归档的 ZIP 和上述哈希为准;本地 `dist` 可能被后续构建替换。
|
||
|
||
H5 的 OAuth 请求已兼容线上严格 JSON 解码:不发送空 `appProof` 或 H5 不需要的 `platform` 字段;有值的原生 App 字段仍保留在开发源码中。
|
||
|
||
发现线上存储配置为 `storage.local.directory=./uploads`,宝塔实际工作目录为 `/www/server/xingyu-im/bt`,该相对目录原先不存在。本次创建软链接:
|
||
|
||
```text
|
||
/www/server/xingyu-im/bt/uploads -> /www/wwwroot/xingyu-data/uploads
|
||
```
|
||
|
||
头像保存到既有持久化目录,并经 `https://im.bchongw.com/uploads/<文件名>.png` 访问。没有改动原有存储配置值,也没有覆盖其他头像文件。
|
||
|
||
### 本次验收
|
||
|
||
- 后端源码快照 `go test ./...`、管理端类型检查/生产构建、H5 类型检查/生产构建通过;测试标签与 OAuth 请求兼容回归用例通过。
|
||
- 数据库独立复核:100 条测试资料、100 个测试昵称标签、男女各 50;正式注册用户数量保持 0。
|
||
- 所有 10 张头像均经 HTTPS 返回 200 和 PNG 内容;生产入口 HTML 与发布包一致,管理端入口 JS、用户管理/仪表盘模块及 H5 测试标签模块的响应内容 SHA-256 与发布包一致。
|
||
- `/healthz` 返回 200;管理接口、推荐接口和 WebSocket 在未登录时均返回 401,未为测试或验收创建管理员会话。
|
||
- 订单、动态、聊天消息、订阅、用户会话数量均保持 0,管理员数量保持 1。
|
||
- Go 服务通过宝塔原生项目管理接口重启,未启用旧 systemd 服务;前端以软链接原子切换,保留旧散列资源,未改动 Nginx 配置。
|
||
- 初次发布时,验收脚本仅读取首条 `Cache-Control`,误判管理端缺少 `no-store` 并自动回退应用。实际响应同时含有 `no-cache` 与 `no-store, no-cache, must-revalidate` 两条头。本次修正为读取全部同名响应头,校验已导入批次和备份后恢复相同发布包,最终验收通过,没有重复导入或恢复整库。
|
||
- 发布前数据库 gzip 备份完整性复核通过。备份仅限 root 访问;不得直接恢复整库覆盖发布后的真实注册或业务数据。
|
||
- 本次未进行生产管理员登录后的真实浏览器验收,未绕过此前的登录授权限制。
|
||
|
||
访问 [管理端用户管理](https://im.bchongw.com/admin/#/users),将用户类型筛选为“测试用户”;访问 [H5](https://im.bchongw.com/app/) 后刷新加载新版。已安装的原生 App 不会因网页发布而自动升级,新版专用标签组件需要重新构建/安装 App;测试资料和昵称前缀已经由服务端提供。
|
||
|
||
## 2026-08-31 测试头像迁移至腾讯云 COS
|
||
|
||
根据用户后续指示,将上文 100 个测试用户共用的 10 张头像上传至管理端已配置的腾讯云 COS,并替换生产数据库链接。
|
||
|
||
- 存储桶:`gz-1349751149`,区域 `ap-guangzhou`。
|
||
- 对象前缀:`media/test-users/cn-adults-20260831-v1/`;对象名包含原文件 SHA-256 的前 20 位及原文件名,防止缓存混淆和名称冲突。
|
||
- 新地址格式:`https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/media/test-users/cn-adults-20260831-v1/<sha20>-<原文件名>.png`,无临时签名和过期查询参数。
|
||
- 备份目录:`/www/backup/xingyu-cos-avatars-20260831-115707`。`before.json` 保存逐用户的新旧链接和文件摘要,`uploaded.json` 保存对象上传结果,`result.json` 保存迁移统计;目录权限 0700,文件权限 0600。
|
||
- 已新增上传 10 个对象,匿名 GET 逐张验证与本地 PNG 内容一致后,在单个 MySQL 事务中更新 100 条 `user_profiles.avatar_url`;再次核对 COS 链接 100 条、原本地头像链接 0 条,男女数量仍各 50。
|
||
- 外部网络独立检查全部 10 个 COS URL,均返回 HTTP 200 和 `image/png`。原本地文件全部保留,不删除也不覆盖其他对象。
|
||
- 线上在迁移前已选用 `tencent_cos`;本次未修改任何系统配置值,也没有修改任何对象 ACL 或存储桶权限。凭证仅在服务器进程内读取解密,没有打印或复制到本地。
|
||
- Go 主服务 PID 保持不变,无需重新部署前端或重启后端。客户端/管理端重新加载用户列表即可获取新地址。
|
||
|
||
迁移工具源码:`backend/cmd/migrate-test-avatars-cos`;服务器工具:`/www/server/xingyu-im/ops/migrate-test-avatars-cos`。本次二进制 SHA-256 为 `68d55ce62b2e515f5e0dee27ff048353e13477f434f0f875a43cf400250e52fc`。离线回归测试覆盖配置密文兼容、路径和 HTTPS 校验、重复上传不覆盖、已有对象冲突拒绝、匿名访问和内容一致性。
|
||
|
||
如需撤销本次头像链接修改,仅针对 `before.json` 中的用户逐行核对当前链接仍等于记录的 `newUrl`,再在事务内恢复为 `oldUrl`;不能覆盖后来由用户或管理员修改的头像,不能恢复整库覆盖后续业务数据。先确认本地旧地址可访问,COS 对象也应保留到引用核对结束。
|
||
|
||
## 2026-08-31 应用功能发布(12:11)
|
||
|
||
用户授权“部署线上”后,已将本次后端、管理端及 H5 发布到现有宝塔项目。此次发布替代上文测试用户版本;没有改动 Nginx、服务器环境变量或已有支付、短信、存储及第三方登录配置值。
|
||
|
||
- 管理端“用户管理”增加“新增用户”,后端新增 `users:create` 权限,并授予现有超级管理员角色。
|
||
- 密码取消长度和字符复杂度限制,移除前端强度提示;仍保留必填、旧密码身份验证和两次输入一致性检查。原 bcrypt 密码兼容,超过 bcrypt 字节上限的新密码采用 Argon2id 保存,不截断输入。
|
||
- 上线 App 第三方登录接口及管理端 App 渠道开关;现有渠道启用状态保持不变,新 App 开关默认关闭,需要有效的平台参数及对应客户端配置才能使用。
|
||
- H5 使用正式 HTTPS/WSS 地址。原生 App 的服务器地址修正、登录入口和表单变化仍需重新构建并安装 App,不会随本次网页发布自动更新。
|
||
|
||
### 发布产物与备份
|
||
|
||
- 服务器发布目录:`/www/server/xingyu-im/releases/application-20260831-121140`。
|
||
- 管理端当前目录:`/www/wwwroot/xingyu-admin/releases/application-20260831-121140`。
|
||
- H5 当前目录:`/www/wwwroot/xingyu-h5/releases/application-20260831-121140`。
|
||
- 发布包 SHA-256:`865952392f733cefcdd9ad257fd701a55be57c434a55f381a7045a5b035d0c17`。
|
||
- 新后端 SHA-256:`54e699a73fd6d3cec7baae3b1224a03cca6f2ddfdcb91c23f05e1fa258514b56`。
|
||
- 备份目录:`/www/backup/xingyu-application-20260831-121140`,权限 0700。包括发布前完整 `im.sql.gz`、原二进制、兼容回滚二进制、环境文件及发布前后状态记录;数据库和环境文件权限 0600。
|
||
- 本次应用迁移 `027_app_oauth_login.sql` 和 `029_admin_create_users.sql`,保留已上线的 028;数据库现有 001–029 共 29 条迁移记录,历史校验值一致。
|
||
- 本地发布包和源码快照:`.deploy/application-20260831-120612`。服务器发布目录中的 `backend-source.zip` 归档了实际构建源码、兼容回滚源码及测试夹具,不在公开网站目录内。
|
||
|
||
前端保留旧散列资源,入口软链接原子切换;后端通过宝塔 Go 项目接口重启。若需回滚,使用备份中的 `xingyu-api-compatible-rollback`(SHA-256:`c041e6549b06e32314e131cabcdc5bd2035ae08f494feb5cb3f5b8b332d1035b`),并将前端软链接切回各自的 `test-users-20260831-113046` 目录。此回滚程序基于上一线上源码,只补充 Argon2id 密码验证,以免新长密码在回滚后无法登录;不要直接使用不支持新哈希的原二进制。增量迁移保留,不得恢复整库覆盖发布后的数据。
|
||
|
||
### 本次验证
|
||
|
||
- 新后端及兼容回滚源码快照的 `go test ./...` 均通过,管理端及移动端类型检查通过,管理端与 H5 生产构建通过。
|
||
- 公网 HTTPS 证书校验通过;管理端、H5、健康检查和 App/H5 登录渠道接口均返回 200。两个入口 HTML 和 5 个入口资源的内容与发布包一致,入口 HTML 包含 `no-store`。
|
||
- 管理接口及 WebSocket 未登录请求均返回 401;未为验收创建账户、修改密码或创建管理员会话。
|
||
- `/proc` 中唯一运行的后端进程 PID 为 733469,运行映像摘要与新后端一致,确认不是仅替换了磁盘文件。
|
||
- 发布前后现有配置值及测试用户资料指纹一致;100 个测试用户的 COS 头像保持不变。复核时用户总数 100、管理员 1、用户会话 2、订单 0、动态 0,未导入额外测试数据。
|
||
- 数据库备份 gzip 完整性验证通过,回滚材料已保留;未实际执行生产回滚,也未进行登录后的业务写入验收。
|
||
|
||
访问 [管理端](https://im.bchongw.com/admin/) 或 [H5](https://im.bchongw.com/app/) 后强制刷新加载新版。如已有会话未刷新到新增权限,可退出后重新登录。
|
||
|
||
## 2026-08-31 IM 未读数与时间格式修复(12:47)
|
||
|
||
针对 App 给对方发消息后自己的列表出现未读红点、时间显示 `NaN:NaN` 的问题,已发布后端小范围修复。
|
||
|
||
- 原先使用 `last_seq - read_seq`,把自己发出的消息也计入未读。现按会话成员实际收到的消息统计:发送者不是本人、序号超过已读/清空/加入位置,且消息未撤回或被管理端下架。发送消息不会自动清除之前尚未阅读的对方消息。
|
||
- `lastMessageAt` 由直接返回 `sql.NullTime` 对象改成 RFC3339 时间字符串;没有消息时返回 `null`。
|
||
- HTTP 读取消息、更新已读状态会通过 WebSocket 通知当前用户的其他连接;已读位置不会超过实际消息序号,失败不会假装成功。
|
||
- 发布前只读检查发现 2 个只有自己发信、却被旧逻辑标为未读的会话。没有为修复清空聊天、修改 read_seq 或创建测试会话,旧记录由新计数逻辑自动正确展示。
|
||
|
||
本次基于 12:11 实际生产源码,只修改 `backend/internal/app/im.go` 并加入其回归测试;发布前逐文件核对归档差异恰为这两项。保留 App OAuth、管理员新增用户和密码处理等已上线功能,001–029 迁移未改动或重跑,管理端和 H5 发布目录未切换。
|
||
|
||
- 后端发布目录:`/www/server/xingyu-im/releases/im-unread-20260831-124713`。
|
||
- 后端 SHA-256:`812ceedad7a7714ad9d04558946370d5665b0a2a9231b0e1282cb65def9f03ab`。
|
||
- 发布包 SHA-256:`230a4755988c2dc4c90a10f00955445e655e11dd6719ece5985707d45f010017`。
|
||
- 回滚备份:`/www/backup/xingyu-im-unread-20260831-124713/xingyu-api-original`,其摘要为上一版 `54e699a73fd6d3cec7baae3b1224a03cca6f2ddfdcb91c23f05e1fa258514b56`;目录 0700,另有 `before.json`、`result.json`。
|
||
- 经宝塔原生 Go 项目重启后,唯一服务进程 PID 为 733915,运行映像摘要与发布文件一致;`/healthz` 正常,未登录的会话接口、管理接口、WebSocket 均返回 401。
|
||
- 发布脚本:`deploy/baota_publish_im_unread.py`,包含生产版本检查、源码差异白名单、迁移一致性检查、二进制备份及失败自动回滚。回滚只替换应用二进制,不恢复数据库。
|
||
|
||
本地验证通过:后端完整测试;隔离 MySQL 中 8 个 HTTP/WebSocket 收发、重复发送、已读、撤回、下架等场景;客户端 6 个回归用例(含实际聊天页隐藏后不再标已读、HTTP/WS 回显去重、陈旧请求不恢复红点、旧时间格式兼容);加上图标、原生组件和测试标签共 19 个客户端用例;Vue 类型检查及 App/H5 生产构建。
|
||
|
||
客户端代码还修复了重复回显、隐藏聊天页误标已读、返回列表及多连接未读同步。这部分在本地 `mobile`,App 资源位于 `mobile/dist/build/app`,**没有生成或安装签名 APK,也没有把这批客户端改动发布到线上 H5**。已安装 App 重新进入消息页即可取得后端修正后的未读数和时间;要包含全部客户端修复,需重新同步运行或打包安装。未进行生产账号登录后的真机验收。
|
||
|
||
## 2026-08-31 头像缩略图上线(18:00)
|
||
|
||
用户授权“部署上线”后,已发布头像处理后端和新版 H5。后端以 12:47 的实际生产源码为基础,只有头像处理、对应测试、文档及依赖共 9 个文件变化;聊天未读修复、密码规则、管理员新增用户和 App OAuth 等现有功能保持不变。没有执行数据库迁移,也没有修改 Nginx、存储配置、原有头像或聊天记录。
|
||
|
||
- 新版 H5 头像上传发送 `purpose=avatar`,服务端生成最长边 640px 展示图、256px 缩略图,并保留实际上传的原文件。小头像使用缩略图,推荐卡片使用展示图;加载缩略图失败时回退一次到展示图。
|
||
- 普通图片、封面、语音和证据上传保留原逻辑。历史头像及第三方头像没有批量下载或替换,不会因本次发布自动变小。
|
||
- H5 从本次冻结的 `mobile` 源码构建,包含此前已在本地完成的聊天同步、图标和原生组件兼容修复;这更新了上文“尚未发布客户端改动到 H5”的状态。管理端静态目录没有切换。
|
||
- 当前采用 `tencent_cos`,生成文件使用原有存储配置,不启用云端图片处理或调整对象 ACL。
|
||
|
||
### 产物及回滚
|
||
|
||
- 后端发布目录:`/www/server/xingyu-im/releases/avatars-20260831-180014`。
|
||
- 后端 SHA-256:`b7eeb926d063855e4271815872ba8c90e226554a3824d48e0995479a671e546e`。
|
||
- 发布包 SHA-256:`28901eeaa88355886cf74899b4e3390cb0baeb5275c1126024f884b34731b404`。
|
||
- 后端源码归档 SHA-256:`bc6c1bafc57d3b7e772e7823d89485d6dbce6cc11ff33fc74a01878665a73f10`。
|
||
- H5 目录:`/www/wwwroot/xingyu-h5/releases/avatars-20260831-180014`;H5 ZIP SHA-256:`00facb91404f06147e9d1f85d872fcc8019878e3a09e45dee8c156db74665214`。
|
||
- 备份目录:`/www/backup/xingyu-avatars-20260831-180014`,权限 0700;包括旧二进制、权限 0600 的完整数据库 gzip 备份,以及发布前后状态 JSON。
|
||
- 回滚目标:旧二进制摘要 `812ceedad7a7714ad9d04558946370d5665b0a2a9231b0e1282cb65def9f03ab`,旧 H5 目录 `/www/wwwroot/xingyu-h5/releases/application-20260831-121140`。旧前端资源已兼容保留,切换通过软链接完成。若回滚仅替换程序和前端入口,不恢复数据库覆盖发布后的业务数据。
|
||
- 发布脚本:`deploy/baota_publish_avatars.py`。发布目录保存 `backend-source.zip`、`mobile-source.zip`、构建产物、校验清单和脚本;本地对应 `.deploy/avatars-20260831-175508`。
|
||
|
||
### 验证结果
|
||
|
||
- 隔离后端源码完整测试通过;冻结的前端源码类型检查、49 项回归测试和 H5 构建通过。
|
||
- 服务器执行与发布源码一致的 Linux 测试二进制,11 个选定测试及其子用例全部通过,覆盖头像生成、方向校正、GIF/WebP、尺寸限制、实际 HTTP 上传/读取、失败清理和普通媒体兼容。这些测试仅使用临时目录、内存数据库/存储,不接触生产账号及 COS 对象。
|
||
- 通过宝塔 Go 项目重启;验证唯一运行进程 PID 9373,其 `/proc` 运行映像摘要与新后端一致。
|
||
- 公网 HTTPS 证书校验通过,H5 的全部 84 个文件内容摘要与本次发布包一致;健康检查、管理端访问正常,上传接口、会话接口及 WebSocket 的未登录请求均返回 401。
|
||
- 发布前后配置值与 100 个测试用户头像指纹一致。复核用户 100、资料 100、管理员 1、媒体记录 0、聊天消息 5、迁移记录 29;未为验收创建账户、修改头像或写入媒体记录。
|
||
- 完整数据库 gzip 备份校验通过;没有实际执行生产回滚,也没有进行生产用户登录后的 COS 上传或真机验收。
|
||
|
||
访问 [H5](https://im.bchongw.com/app/) 后强制刷新即可使用新上传流程。已安装的 App 不会随网页发布自动升级,需要重新打包安装;本次未生成或安装签名 APK。
|
||
|
||
## 2026-09-01 测试头像缩略图补齐(11:06)
|
||
|
||
排查 App“附近”列表头像加载慢时,确认 10 个测试头像的 `-thumb.jpg` 对象全部返回 404。客户端因此先等待缩略图失败,再回退下载约 1.8–2.0MB 的 PNG 原图,每张头像产生两次请求。
|
||
|
||
- 已在原 COS 前缀 `media/test-users/cn-adults-20260831-v1/` 下新增 10 个确定名称的 256px JPEG 缩略图,原 10 个 PNG 对象未覆盖。
|
||
- 外网独立 HEAD 复核 10/10 均为 HTTP 200、`image/jpeg`,单张 8,630–13,355 字节;10 张合计由原图 19,859,686 字节降至 110,178 字节,减少 99.45%。
|
||
- 生产数据库中 100 条测试用户头像链接前后指纹一致,更新行数为 0;未修改 COS 配置、用户资料或其他媒体。
|
||
- 备份与验证记录位于 `/www/backup/xingyu-cos-avatars-thumbnails-20260901-110619`,目录仅 root 可读。迁移二进制 SHA-256 为 `9516326bb0cd9b3e5090ee0a567de164bbfa8644545b5c7021918ea56ff92695`。
|
||
- 此操作只新增静态对象,无需重启后端。客户端重新进入“附近”页后即可直接请求缩略图。
|
||
|
||
## 2026-09-03 语音上传兼容修复(10:20)
|
||
|
||
已将手机录音上传兼容修复发布到 `im.bchongw.com`。服务端新增对无 ID3 标签、直接以 MPEG 音频帧开头的 MP3 录音识别,并兼容客户端显式传入 `purpose=voice`;原有图片、头像和普通媒体上传契约保持不变。
|
||
|
||
- 发布目录:`/www/server/xingyu-im/releases/voice-upload-20260903-102001`。
|
||
- 回滚备份:`/www/backup/xingyu-voice-upload-20260903-102001/xingyu-api-original`。
|
||
- 新后端 SHA-256:`ac1b0c9f5a48b2386fbecb604003fc97299951e580c97e02f8765e1e0228deee`。
|
||
- 上一后端 SHA-256:`b250dd522a74a8812d392e5ed3ae17b2981c799978abf402770dfff1c7442086`。
|
||
- 源码归档 SHA-256:`0dbc6fd23c2bd8e69cc0a15e21d3b1f5b60e7586c91dd20ef486a46071ad047b`。
|
||
- 本次没有数据库迁移、业务数据写入、Nginx 改动或前端目录切换。
|
||
|
||
发布前完整执行 `go test ./...`,包含裸 MPEG Layer III 录音上传回归用例。发布后宝塔 Go 项目 PID 为 `58246`,磁盘文件与 `/proc` 运行映像摘要均为新版本;本机和公网健康检查返回 200,未认证媒体上传请求返回 401。
|
||
|
||
## 2026-09-03 聊天媒体查询修复(11:50)
|
||
|
||
管理端“聊天媒体”页面已发布,但数据库漏执行 `033_chat_media_management.sql`,导致列表接口查询不存在的 `im_message_media` 表并返回“查询聊天媒体失败”。本次先完成整库 gzip 备份,再补执行该迁移。
|
||
|
||
- 数据库备份:`/www/backup/xingyu-chat-media-migration-20260903-115013/im.sql.gz`,备份目录权限 0700、文件权限 0600,gzip 完整性检查通过。
|
||
- 迁移:`033_chat_media_management.sql`,SHA-256 `677c8dfe790e5996326f29967e41dba1f6a2a8018112be7eb42dc9fab1c600df`;迁移记录与工作区文件校验值一致。
|
||
- 历史媒体消息 0 条,管理表 0 条;列表联表查询与统计查询均执行成功。
|
||
- 自动清理保持关闭,默认保留天数为 90 天;本次未删除、覆盖或上传任何聊天文件。
|
||
- 管理端发布目录仍为 `/www/wwwroot/xingyu-admin/releases/20260903-112753`。宝塔实际运行二进制 `/www/server/xingyu-im/bt/xingyu-api` SHA-256 为 `5a97957780900428cc106f2140d640d2d04963729eeeefb396fc8fffc32763a4`,已包含聊天媒体接口,与副站一致,无需重启。
|
||
- 复核 `https://im.bchongw.com/healthz`、管理端入口均返回 200;未登录访问聊天媒体接口返回 401,确认路由与鉴权正常。
|