deploy: 官网 ckb.quwanzhi.com 宝塔上线 DNS+SSL+验收文档
阿里云 A 记录指向存客宝宝塔,Nginx 443 泛域名证书,部署脚本补 SSL/DNS 步骤。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
68
开发文档/1、需求/修改/官网_进行中_20260531.md
Normal file
68
开发文档/1、需求/修改/官网_进行中_20260531.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# 官网 · 进行中(2026-05-31 · 仅剩余项)
|
||||
|
||||
> **已完成全文** → [已完成/官网_0531工程交付_20260531/官网_0531工程交付_20260531.md](./已完成/官网_0531工程交付_20260531/官网_0531工程交付_20260531.md)
|
||||
> **待开发总表** → [20260531_待开发清单.md](./20260531_待开发清单.md)
|
||||
> **代码目录**:`官网/` · **专文**:`开发文档/1、需求/官网/`
|
||||
> **整体进度**:官网站 **100%** · 超管 SEO 中心 **0%** · 公网 DNS/SSL **✅ 已上线**
|
||||
|
||||
---
|
||||
|
||||
## 一、剩余需求表
|
||||
|
||||
| ID | 优先级 | 需求 | 状态 | 专文 |
|
||||
|:---|:---:|:---|:---:|:---|
|
||||
| REQ-WEB-61 | **P0** | 官网 AI 客服 生产联调 | 🟡 BFF+FAQ 全绿 · ckbapi 路由已部署 · **待 AI 模型/KB 配置** | [14](../官网/14-官网AI客服获客场景_20260531.md) |
|
||||
| REQ-WEB-41 | P1 | SuperAdmin `/dashboard/seo-center` | ⬜ 跨端 · 需授权改 SuperAdmin 仓 | 12 |
|
||||
| REQ-WEB-42 | P1 | SEO BFF `/v1/admin/seo/*` | ⬜ 跨端 · 需授权改存客宝 Server | 12 |
|
||||
| REQ-WEB-10 | P2 | 公网 DNS + 宝塔 SSL | ✅ ckb.quwanzhi.com → 42.194.245.239 · HTTPS 泛域名证书 | 01 |
|
||||
| REQ-WEB-23 | P2 | Screaming Frog 审计归档 | ⬜ 需人工跑 SF + 归档 MD | 09 |
|
||||
|
||||
---
|
||||
|
||||
## 二、本轮回合已完成(2026-05-31 晚)
|
||||
|
||||
| ID | 验收 |
|
||||
|:---|:---|
|
||||
| REQ-WEB-07 | `ind-ecom.jpg/webp` 换为 `hero-growth-chart` 专属图(MD5≠ind-store) |
|
||||
| REQ-WEB-52 | `device.html#device-poster` 双竖版海报样板 + `device-phone.css` |
|
||||
| REQ-WEB-22 | 后台「生成 32 位 Key」+ 保存时自动写 `{key}.txt` · runtime ping 已有 |
|
||||
| Hero CTA | `trial` → `pricing.html` → 自动弹留资窗 · smoke ✅ |
|
||||
| deploy | `deploy_official_site.sh` 启动轮询 30s · smoke **ALL PASS** |
|
||||
|
||||
---
|
||||
|
||||
## 三、REQ-WEB-61 生产联调清单
|
||||
|
||||
| # | 项 | 状态 |
|
||||
|:---:|:---|:---:|
|
||||
| 1 | 宝塔 pm2 `ckb-official` 8090 运行 | ✅ |
|
||||
| 2 | BFF `/api/official-ai/chat` 签名 parity | ✅ |
|
||||
| 3 | 首页 AI 挂件 10s 弹出 | ✅ |
|
||||
| 4 | FAQ 兜底(upstream 失败时 keyword 回复) | ✅ |
|
||||
| 5 | **生产 ckbapi 部署 `official-ai/chat` 路由** | ✅ 已 rsync |
|
||||
| 6 | **计划 779 绑定 KB/内容库 ID** | ⬜ |
|
||||
| 7 | **生产 AI 网关 Provider(非 503)** | 🟡 模型 endpoint 不可用 · FAQ 兜底可用 |
|
||||
|
||||
**存客宝侧**: [REQ-CKB-66](./存客宝_进行中_20260531.md#四p0--req-ckb-66--对外-ai-客服生产联调)
|
||||
|
||||
---
|
||||
|
||||
## 四、验收命令
|
||||
|
||||
```bash
|
||||
bash 开发文档/8、部署/scripts/deploy_official_site.sh --smoke
|
||||
# 后台 http://127.0.0.1:8090/admin/ admin / key123456
|
||||
```
|
||||
|
||||
**2026-05-31 smoke**:ALL PASS(含 Hero→价格页弹窗、device 海报区)
|
||||
|
||||
---
|
||||
|
||||
## 五、变更记录
|
||||
|
||||
| 日期 | 摘要 |
|
||||
|:---|:---|
|
||||
| 2026-05-31 | REQ-WEB-60/62/63/21/54/11 等已完成项迁入 `已完成/官网_0531工程交付` |
|
||||
| 2026-05-31 | 本文仅保留 ⬜/🟡 剩余项 |
|
||||
| 2026-05-31 晚 | ✅ WEB-07/52/22 · Hero trial 流程 · deploy 30s 就绪 · smoke ALL PASS |
|
||||
| 2026-05-31 晚 | 剩余 5 项:WEB-61 生产、WEB-41/42 超管、WEB-10 DNS、WEB-23 SF |
|
||||
65
开发文档/8、部署/01-本地环境/开发进度_官网宝塔_20260531.md
Normal file
65
开发文档/8、部署/01-本地环境/开发进度_官网宝塔_20260531.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 官网 ckb.quwanzhi.com · 宝塔部署进度
|
||||
|
||||
> 更新时间:2026-05-31
|
||||
> 域名:https://ckb.quwanzhi.com
|
||||
> 服务器:42.194.245.239:22022(存客宝宝塔)
|
||||
> **整体进度:100%**(DNS + SSL + 全页 + API 验收通过)
|
||||
|
||||
---
|
||||
|
||||
## 部署架构
|
||||
|
||||
| 层 | 说明 |
|
||||
|:---|:---|
|
||||
| DNS | 阿里云 A 记录 `ckb.quwanzhi.com` → `42.194.245.239` |
|
||||
| Nginx | `/www/server/panel/vhost/nginx/ckb.quwanzhi.com.conf` · 80/443 反代 |
|
||||
| SSL | `*.quwanzhi.com` 泛域名证书(`/root/ssl_deploy_wildcard.sh`) |
|
||||
| 应用 | PM2 `ckb-official` · `scripts/site-unified-server.mjs` · `:8090` |
|
||||
| 代码 | `/www/wwwroot/ckb.quwanzhi.com` |
|
||||
|
||||
---
|
||||
|
||||
## 一键部署
|
||||
|
||||
```bash
|
||||
# 1. 部署官网 + Nginx + SSL + DNS
|
||||
bash 开发文档/8、部署/scripts/deploy_official_baota.sh
|
||||
|
||||
# 2. 仅改 DNS(阿里云 API)
|
||||
bash 开发文档/8、部署/scripts/aliyun_dns_ckb_official.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-31 验收结果
|
||||
|
||||
| 项 | 结果 |
|
||||
|:---|:---:|
|
||||
| HTTPS 首页 / pricing / sitemap / admin | 200 |
|
||||
| POST `/api/track` | 200 |
|
||||
| POST `/api/lead-submit`(带 sign+timestamp) | 200 · 新增成功 |
|
||||
| POST `/api/official-ai/chat` | 200 · FAQ 兜底(上游模型暂不可用) |
|
||||
| POST `/admin/api/login` | 200 · token ok |
|
||||
| 阿里云 DNS @223.5.5.5 | 42.194.245.239 |
|
||||
| 服务器 curl https://ckb.quwanzhi.com | 200 |
|
||||
|
||||
---
|
||||
|
||||
## 生产 ckbapi 补丁(官网 AI/留资依赖)
|
||||
|
||||
本次同步到 `/www/wwwroot/ckbapi.quwanzhi.com`:
|
||||
|
||||
- `application/cunkebao/controller/plan/OfficialAiChatController.php`
|
||||
- `application/cunkebao/config/route.php`(含 `v1/api/official-ai`)
|
||||
- `application/common/service/PromptMergeService.php`
|
||||
- `application/common/service/AiGatewayService.php`
|
||||
|
||||
**待办(非阻塞)**:AI 网关模型 `doubao-seed-1-8-251215` 权限/配置;计划 779 绑定知识库。
|
||||
|
||||
---
|
||||
|
||||
## 相关脚本
|
||||
|
||||
- `开发文档/8、部署/scripts/deploy_official_baota.sh`
|
||||
- `开发文档/8、部署/scripts/nginx_ckb_official.conf`
|
||||
- `开发文档/8、部署/scripts/aliyun_dns_ckb_official.sh`
|
||||
72
开发文档/8、部署/scripts/aliyun_dns_ckb_official.sh
Executable file
72
开发文档/8、部署/scripts/aliyun_dns_ckb_official.sh
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
# 阿里云 DNS:ckb.quwanzhi.com → 存客宝宝塔 42.194.245.239
|
||||
set -euo pipefail
|
||||
python3 - <<'PY'
|
||||
import os, re, sys, json
|
||||
RR = "ckb"
|
||||
TARGET_IP = "42.194.245.239"
|
||||
DOMAIN = "quwanzhi.com"
|
||||
INDEX_MD = "/Users/karuo/Documents/个人/卡若AI/运营中枢/工作台/00_账号与API索引.md"
|
||||
|
||||
def get_creds():
|
||||
id_val = os.environ.get("ALIYUN_ACCESS_KEY_ID")
|
||||
secret_val = os.environ.get("ALIYUN_ACCESS_KEY_SECRET")
|
||||
if id_val and secret_val:
|
||||
return id_val, secret_val
|
||||
if not os.path.isfile(INDEX_MD):
|
||||
return None, None
|
||||
text = open(INDEX_MD, encoding="utf-8").read()
|
||||
in_ali = False
|
||||
for line in text.splitlines():
|
||||
if "### 阿里云" in line:
|
||||
in_ali = True
|
||||
continue
|
||||
if in_ali and line.strip().startswith("###"):
|
||||
break
|
||||
if in_ali:
|
||||
if "AccessKey ID" in line:
|
||||
m = re.search(r"`([A-Za-z0-9]+)`", line)
|
||||
if m: id_val = m.group(1)
|
||||
if "Secret" in line and "key" not in line.lower():
|
||||
m = re.search(r"`([A-Za-z0-9]+)`", line)
|
||||
if m: secret_val = m.group(1)
|
||||
return id_val, secret_val
|
||||
|
||||
key_id, key_secret = get_creds()
|
||||
if not key_id:
|
||||
print("未找到阿里云凭证"); sys.exit(1)
|
||||
from aliyunsdkcore.client import AcsClient
|
||||
from aliyunsdkalidns.request.v20150109.AddDomainRecordRequest import AddDomainRecordRequest
|
||||
from aliyunsdkalidns.request.v20150109.DescribeDomainRecordsRequest import DescribeDomainRecordsRequest
|
||||
from aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest import UpdateDomainRecordRequest
|
||||
client = AcsClient(key_id, key_secret, "cn-hangzhou")
|
||||
req_list = DescribeDomainRecordsRequest()
|
||||
req_list.set_accept_format("json")
|
||||
req_list.set_DomainName(DOMAIN)
|
||||
req_list.set_RRKeyWord(RR)
|
||||
resp = json.loads(client.do_action_with_exception(req_list))
|
||||
records = resp.get("DomainRecords", {}).get("Record", [])
|
||||
for r in records:
|
||||
if (r.get("RR") or "").lower() == RR.lower():
|
||||
rid = r.get("RecordId")
|
||||
if r.get("Value") == TARGET_IP and r.get("Type") == "A":
|
||||
print(f"解析已正确: {RR}.{DOMAIN} -> {TARGET_IP}")
|
||||
sys.exit(0)
|
||||
req_u = UpdateDomainRecordRequest()
|
||||
req_u.set_accept_format("json")
|
||||
req_u.set_RecordId(rid)
|
||||
req_u.set_RR(RR)
|
||||
req_u.set_Type("A")
|
||||
req_u.set_Value(TARGET_IP)
|
||||
client.do_action_with_exception(req_u)
|
||||
print(f"已更新: {RR}.{DOMAIN} -> {TARGET_IP}")
|
||||
sys.exit(0)
|
||||
req = AddDomainRecordRequest()
|
||||
req.set_accept_format("json")
|
||||
req.set_DomainName(DOMAIN)
|
||||
req.set_RR(RR)
|
||||
req.set_Type("A")
|
||||
req.set_Value(TARGET_IP)
|
||||
client.do_action_with_exception(req)
|
||||
print(f"已添加: {RR}.{DOMAIN} -> {TARGET_IP}")
|
||||
PY
|
||||
44
开发文档/8、部署/scripts/deploy_official_baota.sh
Normal file
44
开发文档/8、部署/scripts/deploy_official_baota.sh
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# 存客宝官网 → 腾讯云存客宝宝塔(42.194.245.239)部署
|
||||
# 域名 ckb.quwanzhi.com · 静态 + /api + /admin 由 Node 统一服务(8090) 提供,Nginx 反代
|
||||
# 用法:bash 开发文档/8、部署/scripts/deploy_official_baota.sh
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
SITE="$ROOT/官网"
|
||||
HOST="root@42.194.245.239"
|
||||
PORT_SSH=22022
|
||||
SSH="ssh -p $PORT_SSH -o BatchMode=yes -o StrictHostKeyChecking=no"
|
||||
DEST="/www/wwwroot/ckb.quwanzhi.com"
|
||||
APP_PORT=8090
|
||||
VHOST="/www/server/panel/vhost/nginx/ckb.quwanzhi.com.conf"
|
||||
|
||||
echo ">>> 1/5 创建目录"
|
||||
$SSH "$HOST" "mkdir -p $DEST $DEST/data"
|
||||
|
||||
echo ">>> 2/5 rsync 官网静态+服务端(保留服务器 data,避免覆盖线上 analytics)"
|
||||
rsync -avz --delete -e "ssh -p $PORT_SSH -o BatchMode=yes -o StrictHostKeyChecking=no" \
|
||||
--exclude 'data/analytics.json' \
|
||||
--exclude 'node_modules' \
|
||||
--exclude '.DS_Store' \
|
||||
"$SITE/" "$HOST:$DEST/"
|
||||
|
||||
echo ">>> 3/5 写 Nginx vhost"
|
||||
scp -P $PORT_SSH -o BatchMode=yes -o StrictHostKeyChecking=no \
|
||||
"$ROOT/开发文档/8、部署/scripts/nginx_ckb_official.conf" "$HOST:$VHOST"
|
||||
|
||||
echo ">>> 4/5 pm2 启动/重启 Node 统一服务 (port ${APP_PORT})"
|
||||
$SSH "$HOST" "cd ${DEST} && pm2 delete ckb-official >/dev/null 2>&1 || true; SITE_PORT=${APP_PORT} pm2 start scripts/site-unified-server.mjs --name ckb-official --cwd ${DEST}; pm2 save"
|
||||
|
||||
echo ">>> 5/7 部署泛域名 SSL 证书"
|
||||
$SSH "$HOST" "bash /root/ssl_deploy_wildcard.sh 2>/dev/null | grep -E 'ckb.quwanzhi|Done' || true"
|
||||
|
||||
echo ">>> 6/7 校验 Nginx 并重载"
|
||||
$SSH "$HOST" "nginx -t && nginx -s reload && echo NGINX_RELOADED"
|
||||
|
||||
echo ">>> 7/7 阿里云 DNS 指向"
|
||||
bash "$ROOT/开发文档/8、部署/scripts/aliyun_dns_ckb_official.sh" || echo "WARN: DNS 脚本未执行(缺凭证则手动确认 A 记录)"
|
||||
|
||||
echo ">>> 验收"
|
||||
$SSH "$HOST" "sleep 2; echo -n '本地8090 首页 '; curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:$APP_PORT/index.html; echo -n 'HTTP 反代 '; curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: ckb.quwanzhi.com' http://127.0.0.1/index.html; echo -n 'HTTPS 反代 '; curl -s -o /dev/null -w '%{http_code}\n' -k -H 'Host: ckb.quwanzhi.com' https://127.0.0.1/index.html; echo -n 'track API '; curl -s -o /dev/null -w '%{http_code}\n' -X POST -H 'Content-Type: application/json' -H 'Host: ckb.quwanzhi.com' http://127.0.0.1/api/track -d '{\"visitorId\":\"v_deploy_check\",\"events\":[]}'"
|
||||
|
||||
echo ">>> 完成。官网 https://ckb.quwanzhi.com"
|
||||
39
开发文档/8、部署/scripts/nginx_ckb_official.conf
Normal file
39
开发文档/8、部署/scripts/nginx_ckb_official.conf
Normal file
@@ -0,0 +1,39 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
listen [::]:80;
|
||||
server_name ckb.quwanzhi.com;
|
||||
|
||||
ssl_certificate /www/server/panel/vhost/cert/ckb.quwanzhi.com/fullchain.pem;
|
||||
ssl_certificate_key /www/server/panel/vhost/cert/ckb.quwanzhi.com/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
error_page 497 https://$host$request_uri;
|
||||
|
||||
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn) {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location ~ \.well-known {
|
||||
allow all;
|
||||
}
|
||||
|
||||
# 官网统一服务(静态 + /api/* + /admin/api/*)由 Node 提供,全部反代到 127.0.0.1:8090
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8090;
|
||||
proxy_http_version 1.1;
|
||||
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;
|
||||
proxy_read_timeout 30s;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/ckb.quwanzhi.com.log;
|
||||
error_log /www/wwwlogs/ckb.quwanzhi.com.error.log;
|
||||
}
|
||||
Reference in New Issue
Block a user