提交图

27 次代码提交

作者 SHA1 备注 提交日期
徐勤民
34bfa71bd5 fix(update): 修复 WebSocket 101 误判 + 清理孤儿容器
- WebSocket 探测:curl 在 101 握手后无法继续 WS 协议会追加 000,
  返回值为 "101000",改为 grep '^101' 判断首三位而非精确匹配
- up -d 加 --remove-orphans:自动清理已从 compose 文件移除的容器
  (如之前删除的 ops-web),消除每次升级的 WARN 噪音

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 09:27:22 +08:00
徐勤民
777eb23b60 fix(update): restart→up -d 确保新镜像生效;新增 WebSocket 连通性自检
- 将 docker compose restart 改为 up -d --no-deps:
  restart 仅重启容器进程,不切换镜像;up -d 检测镜像变更后重建容器,
  是拉取新镜像后使其生效的正确方式
- 新增 Step 9 WebSocket 自检:
  · 探测容器 nginx → im-service 本地握手(HTTP 101 = 正常)
  · 同时探测外部域名 WebSocket 握手,失败时输出上层代理配置指引
    (覆盖云 SLB/CDN 开启 WebSocket、nginx 补充四行头的两种场景)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 19:06:07 +08:00
徐勤民
4ff09ae768 feat(update): 完整重写热更新脚本,覆盖所有已知部署问题
Step 1 - CONSOLE_DOMAIN:检测裸 IP,交互提示输入公网域名
Step 2 - SDK URL:修复 xuqinmin.com 残留 / 内网 IP / 空值三种情形
Step 3 - SDK JSON:同步 xuqm-private-sdk.json
Step 4 - 宿主机 nginx WebSocket 头:
  · nginx -T 获取完整配置
  · Python3 精确定位代理到容器 nginx 的 location 块
  · 缺少 proxy_http_version 1.1 / Upgrade / Connection 时自动注入
  · 修改前备份 .xuqm.bak,nginx -t 失败自动回滚,成功后 nginx -s reload
  · 未发现代理配置时输出标准模板供参考
Step 5 - 拉取镜像(可选)
Step 6 - 重启 tenant-service + nginx
Step 7 - 等待 tenant-service 健康(最长 120s)
Step 8 - 自动处理积压 PENDING 服务开通申请
Step 9 - 全量验证

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 18:58:28 +08:00
徐勤民
7d8f916ea5 fix(update): 检测并修复 CONSOLE_DOMAIN 及 SDK URL 为内网 IP 的情况
- CONSOLE_DOMAIN 为私有 IP 段时提示用户输入正确的公网域名
- SDK_IM_WS_URL / SDK_IM_API_URL / SDK_FILE_SERVICE_URL 包含
  裸 IP(10.x / 172.x / 192.168.x / 127.x)时同样触发修复
- 提取 _url_needs_fix 辅助函数消除重复判断逻辑

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 18:49:50 +08:00
徐勤民
28fd8c0793 feat(update): upgrade 后自动调用 approve-pending-requests 修复积压申请
update.sh 在 tenant-service 健康后调用
POST /api/private/admin/approve-pending-requests
自动开通所有 PENDING 状态的服务申请,无需用户手动操作。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 18:46:00 +08:00
徐勤民
a327a262dd feat(deploy): 移除 ops-web、修复 SDK URL 注入、新增一键升级
核心变更:
- 完全移除 ops-web 容器(私有化部署无需运营后台)
- nginx sub_filter 替换前端 JS bundle 中的公网 SDK URL
- deploy.sh 写入正确的 SDK_IM_WS_URL / SDK_IM_API_URL / SDK_FILE_SERVICE_URL
- 新增 scripts/update.sh:热更新脚本,修复配置 + 可选拉镜像 + 重启 + 验证
- 新增 upgrade.sh:一键升级入口,curl 下载后直接执行,流程同 install.sh
- install.sh 检测已有部署(.env 存在),自动路由到 update.sh 而非重跑向导
- 关键配置文件(.env / secrets.env / xuqm.env)在 tarball 解压前备份后恢复

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 18:25:12 +08:00
徐勤民
0c4802b20a feat(deploy): nginx 绑定模式可选,兼容有/无宿主机 nginx 两种场景
向导新增第 0d 步:询问宿主机 80 端口是否空闲。
  - 空闲(多层代理/内网)→ NGINX_BIND=80,容器直接监听宿主机 80
  - 已有 nginx(云服务器 HTTPS)→ NGINX_BIND=127.0.0.1:11223,宿主机加一条转发

docker-compose.yml nginx ports 改用 ${NGINX_BIND:-80}:80 变量控制。
端口检查、Step 7 验证地址、部署完成输出均根据模式动态调整。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:20:02 +08:00
徐勤民
8b0c05e0e4 feat(nginx): 容器直接绑定 0.0.0.0:80,宿主机无需 nginx 配置
将内置 nginx 从 127.0.0.1:11223 改为直接绑定宿主机 0.0.0.0:80。
上层 nginx 直接 proxy_pass 到本机 IP:80 即可,省去宿主机 nginx 配置环节。
同步更新端口检查(80)、部署完成提示、runbook/configuration/README 文档。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:15:53 +08:00
徐勤民
f490b62f0b fix(deploy): 移除输出中硬编码的 IP 地址
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:12:33 +08:00
徐勤民
35f07bad95 fix(deploy): 修正端口检查、删除死代码、验证走内置nginx
1. 端口检查:80/443 → 11223(内置 nginx 实际使用的端口)
2. 删除 if false 死代码块(旧版 nginx 配置模板,137行无效代码)
3. Step 7 验证:改为 BASE_URL=http://127.0.0.1:11223,不依赖
   宿主机或外层 nginx 是否已配置,避免部署后验证误报失败
4. 最终输出:添加多层 nginx 代理场景的 WebSocket 头透传提示
5. verify.sh:移除不存在的 docs-site 容器检查(避免恒定 WARN)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 16:56:42 +08:00
徐勤民
a55121aa05 feat(nginx): 内置路由 nginx 作为统一入口,宿主机 nginx 只需一条 proxy_pass
将 nginx 容器从可选 profile 改为 base 必启服务,绑定 127.0.0.1:11223。
新增 config/nginx/conf.d/xuqm.conf 按 Docker 服务名路由所有内部请求。
部署完成提示从多条 location 精简为单条 proxy_pass http://127.0.0.1:11223。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 16:13:04 +08:00
徐勤民
964188ba8c fix(ports): 宿主机端口改为 11224-11231
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 15:43:05 +08:00
徐勤民
69da547866 fix(ports): 宿主机端口改为 10223-10230,绑定 127.0.0.1
原端口(8080-9001)在 Windows/Hyper-V 环境下可能被系统排除导致绑定失败。
统一改用 10223 起顺序编号,同时绑定 127.0.0.1 限制只有本机 nginx 可访问:
  10223 tenant-service   10224 file-service    10225 tenant-web
  10226 ops-web          10227 im-service      10228 push-service
  10229 update-service   10230 license-service

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 15:40:28 +08:00
徐勤民
2a250e79a0 refactor(deploy): 去除内置 nginx,各服务暴露宿主机端口,末尾输出 nginx 配置参考
私有化部署场景下用户通常有自己的 nginx,内置 nginx 容器会占用 80/443
与宿主机冲突,且域名/HTTPS 交互配置对用户是噪音。

- docker-compose.yml: nginx 容器改为 profile=nginx-bundled(默认不启动)
  各业务容器增加 ports 暴露宿主机端口(9001/8086/8082/8083/8084/8085/8080/8081)
- deploy.sh: 去除 域名/HTTPS/certbot 交互,改为询问一个外部访问地址(用于 SDK 配置)
  健康检查和 import API 直接打 127.0.0.1:9001,不再依赖 nginx 容器
  末尾输出端口表和可直接复制的 nginx location 配置参考

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 15:30:55 +08:00
徐勤民
60aeb61433 fix(deploy): 迁移/新建租户后同步写入 app_licenses,修复 license 404
importData API 只写 t_tenant/t_app/t_feature_service,不写 license-service
的 app_licenses 表,导致前端 /api/license/admin/apps/:appKey 返回 404。

在 deploy.sh 的迁移和新建两个分支中,import 成功后直接对同一 MySQL 执行
INSERT ... ON DUPLICATE KEY UPDATE,为所有非系统应用补写 app_licenses 记录。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 12:11:19 +08:00
徐勤民
3fe5ae0807 fix(migrate-tenant): 补全 app_licenses 迁移,修复租户迁移后 license 404
migrate-tenant.sh 迁移 t_app 时未同步写入 license-service 的 app_licenses
表,导致前端 /api/license/admin/apps/:appKey 返回 404。

新增 Step 4c:为所有迁移的 app 以 INSERT ... ON DUPLICATE KEY UPDATE
方式创建 app_licenses 记录(max_devices=1000,永不过期),操作幂等,
不影响已存在的 license 配置。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 12:02:26 +08:00
徐勤民
aa5bccae11 feat(deploy): 完成私有化部署全流程验收
- 更新部署进度文档,标记P5-02/P5-03为已完成状态
- 修复中文乱码问题,MySQL数据层使用UNHEX函数配合nginx字符集设置
- 配置im-service和update-service的内部服务URL,从127.0.0.1改为Docker服务名
- 实现全功能验收,nginx为所有服务添加路由映射并返回正确的状态码
- 创建私有化部署默认信息文档,记录完整的部署配置和访问地址
- 添加部署清理脚本clean.sh,支持一键清理容器、配置和数据目录
- 更新敏感配置模板,添加详细的密码和密钥配置说明
- 优化前端实时消息轮询机制,通过WebSocket心跳检测决定是否启用HTTP轮询回退
2026-05-19 19:23:28 +08:00
徐勤民
d2599a0c1e fix(nginx): WebSocket trailing slash, 413 on file upload, domain+HTTPS support
- nginx: /ws/im/ → /ws/im (trailing slash broke ?token= WebSocket connections)
- nginx: add /api/file/ location before /api/ with 500m limit (fixes 413)
- deploy.sh: default DEPLOY_HOST to localhost instead of 127.0.0.1
- deploy.sh: add interactive domain/HTTPS configuration step (0c)
  - optional custom domain with validation
  - optional HTTPS via Let's Encrypt certbot (standalone, before nginx starts)
  - generates SSL nginx config (two-server-block) and docker-compose.override.yml
  - SDK_IM_WS_URL and imWsUrl use _WS_SCHEME (ws/wss) based on protocol
- deploy.sh: add info() helper function

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 18:12:48 +08:00
徐勤民
be04c311b9 fix(verify): remove misleading 'optional services not started' message
WARN items include expected behaviors (login skipped in migrate mode,
JWT checks, etc.) — not just unstarted services. All services are
started by default. Changed footer to say '预期降级' instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 17:01:58 +08:00
徐勤民
54f4d2a06f fix(deploy): correct import API path + show actual error on failure
- /api/private/migrate/import → /api/private/deployment/migrate/import
- replace -sf with -s + HTTP status check to surface real error message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 16:07:47 +08:00
徐勤民
1dca34de5a fix(deploy): remove self-copy of nginx conf; show migration key input
- cp nginx conf to itself caused error; file is already in place
- migration key prompt changed from silent to visible (read -rp)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 15:42:35 +08:00
徐勤民
a6a81b0755 feat(deploy): generic deploy.sh with API-based tenant migration
- Rename deploy-szyx.sh → deploy.sh, remove all customer-specific branding
- Migrate mode: prompt for pmk_ key, call public platform export API,
  pipe to private import API — no MySQL credentials needed
- Remove bcrypt dependency (no longer used in script logic)
- Update install.sh and verify.sh references

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 15:14:23 +08:00
徐勤民
43a423b85c feat: 一键安装向导 + 交互式租户初始化
- 新增 install.sh:curl 一键下载依赖安装 + 自动解压部署包 + 启动部署向导
- deploy-szyx.sh:移除硬编码租户常量,改为交互式选择(新建/迁移)
  - 新建租户:收集邮箱/用户名/密码,bcrypt 写入 bootstrap.env
  - 迁移租户:提示输入生产 MySQL 配置,bcrypt 验证主账号后执行迁移
  - 已有数据时迁移前显示红色警告要求 yes 确认
- 移除 docs-site 独立容器(文档已内置于 tenant-web/docs/)
- nginx 和 docker-compose 同步清理 docs-site 残留配置

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:29:57 +08:00
徐勤民
f0649e9305 feat: 数字医信一键部署脚本 + 文档整理
scripts/deploy-szyx.sh (新增):
  七步幂等脚本,覆盖从预检到验收全流程:
  1. Docker / Compose / 磁盘 / 端口预检
  2. 写入数字医信专属配置(.env / secrets.env / xuqm.env /
     nginx / sdk-json),所有值固化为默认值,支持环境变量覆盖
  3. 登录 ACR (crpi-n44qjpuucgjt8e8c.cn-beijing.personal.cr.aliyuncs.com)
  4. 启动 MySQL + Redis 并轮询就绪
  5. 启动 base profile 业务容器并等待 actuator/health
  6. 迁移数字医信生产租户(szyx@bjca.org.cn),已迁移时自动跳过
  7. 验收:health / PRIVATE 模式 / 两个 appKey SDK config / 注册阻断 / 前端

docs/configuration.md:
  补充 Spring Boot SPRING_DATASOURCE_* 覆盖说明(application.yml
  硬编码生产 DB URL 的关键陷阱),nginx 服务端口对照表,
  docs-site 镜像可选说明。

docs/runbook.md:
  新增租户迁移章节,含前提、命令、自动步骤、验证示例。

README.md:
  快速参考:migrate-tenant.sh 用法、三条部署注意事项。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 08:01:19 +08:00
徐勤民
f6189a5283 feat: harden deployment scripts and add tenant migration
Issues found during P5-01 acceptance testing on WSL2:

configure.sh: sync MySQL/Redis host/port into config/xuqm.env (was
  only writing to .env, leaving xuqm.env with hardcoded 127.0.0.1).

install.sh: add docker login step before compose up; reads
  REGISTRY_USER/REGISTRY_PASSWORD from .env; --skip-registry-login
  flag for offline bundles or pre-authenticated environments.

healthcheck.sh: move docs-site from required to optional container
  list (image may not exist in all ACR namespaces); add localhost
  fallback URL for actuator/health when CONSOLE_DOMAIN is not set;
  add PRIVATE mode verification via /api/private/deployment/status.

scripts/migrate-tenant.sh (new): migrates a single tenant from the
  public platform MySQL to the private deployment. Exports t_tenant,
  t_app, t_feature_service with explicit column names to survive
  schema-order differences; supports --dry-run, --reset-password,
  managed/external destination MySQL, and restarts tenant-service
  after applying.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 00:27:10 +08:00
徐勤民
9eabe0d699 feat: implement complete private deployment scripts (P1-P4)
- upgrade.sh/rollback.sh: backup→pull→rolling restart→healthcheck→auto-rollback
- backup.sh/restore.sh: mysqldump+redis BGSAVE+config tar, SHA256 manifest, restore with checksum verification
- healthcheck.sh: Docker/container/MySQL/Redis/HTTP/disk checks, JSON output to .deploy-state/
- doctor.sh: sanitized diagnostics archive, vendor API TCP connectivity, cert expiry
- export-offline-bundle.sh: docker pull+save for all profile images, load-images.sh, SHA256
- configure.sh: interactive/non-interactive mode, MySQL/Redis mode selection, domain prompts
- enable-service.sh: domain validation, docker pull + compose up, healthcheck
- disable-service.sh: compose stop+rm, profile removal, render-config
- renew-cert.sh: acme.sh/certbot, --dry-run, backup old cert, nginx reload on success
- alert-webhook.sh: WeCom/DingTalk/Feishu webhook, message sanitization
- bench.sh: ab/wrk/curl benchmark, JSON report with docker stats
- rotate-secrets.sh: JWT and internal token rotation
- vendor credential templates: push.env and store-submit.env with full credential comments
- render-config.sh: auto-sync SDK URL env vars (SDK_FILE_SERVICE_URL, SDK_IM_API_URL, SDK_IM_WS_URL)
- All scripts pass bash -n syntax check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 20:49:25 +08:00
徐勤民
4ada03183a chore: scaffold private deployment repository 2026-05-18 19:49:31 +08:00