Files
kefu/im/deploy/im.bchongw.com_部署记录.md
Your NameandClaude Opus 5 acd8933dbb 后端:资料距离、语音图片会员限制、免短信注册、AI 托管回复修复
- 单用户资料接口补上距离:此前只有推荐/附近列表会算距离,资料页和
  聊天头部因此无内容可显示。沿用同一套 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>
2026-09-04 10:00:08 +08:00

36 KiB
Raw Permalink Blame History

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。

常用运维命令

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:

/etc/init.d/nginx reload

验收脚本(会实际重启一次后端,维护窗口使用):

cd /www/server/panel
./pyenv/bin/python /www/server/xingyu-im/ops/baota_panel_takeover.py verify

管理员凭据

初始管理员用户名和密码保存在服务器 root 专用文件:

/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 负责。不要同时另建一套宝塔自动申请任务;如果以后改用宝塔托管申请,应先安排切换续签机制和证书路径。

检查续签任务:

systemctl status certbot-renew.timer --no-pager
certbot renew --dry-run --no-random-sleep-on-renew

前端生产配置

uni-app:

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。

管理端:

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 /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 服务,以免抢占同一端口。
  • 面板数据库快照仅用于灾难恢复,不能直接覆盖当前面板数据库,否则会覆盖其他站点后续变更。正常回滚应仅还原本项目的记录和配置。

备份范围

至少备份以下内容:

/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,该相对目录原先不存在。本次创建软链接:

/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 访问;不得直接恢复整库覆盖发布后的真实注册或业务数据。
  • 本次未进行生产管理员登录后的真实浏览器验收,未绕过此前的登录授权限制。

访问 管理端用户管理,将用户类型筛选为“测试用户”;访问 H5 后刷新加载新版。已安装的原生 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 完整性验证通过,回滚材料已保留;未实际执行生产回滚,也未进行登录后的业务写入验收。

访问 管理端 或 H5 后强制刷新加载新版。如已有会话未刷新到新增权限,可退出后重新登录。

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 后强制刷新即可使用新上传流程。已安装的 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,确认路由与鉴权正常。