|
@@ -0,0 +1,534 @@
|
|
|
|
|
+# Homelegance Chatbot 生产部署文档
|
|
|
|
|
+
|
|
|
|
|
+**服务器**:AlmaLinux 8.10 | **Web 服务器**:Apache(与主站共用)
|
|
|
|
|
+**访问地址**:`https://www.homelegance.com/chat/`
|
|
|
|
|
+**部署路径**:`/redant/web/homelegance-chatbot`
|
|
|
|
|
+**数据库**:内网独立 PostgreSQL 服务器,Schema `chatbot`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 目录
|
|
|
|
|
+
|
|
|
|
|
+1. [环境要求](#1-环境要求)
|
|
|
|
|
+2. [Node.js 安装](#2-nodejs-安装)
|
|
|
|
|
+3. [代码部署](#3-代码部署)
|
|
|
|
|
+4. [数据库初始化](#4-数据库初始化)
|
|
|
|
|
+5. [环境变量配置](#5-环境变量配置)
|
|
|
|
|
+6. [构建与启动](#6-构建与启动)
|
|
|
|
|
+7. [PM2 进程管理](#7-pm2-进程管理)
|
|
|
|
|
+8. [Apache 配置](#8-apache-配置)
|
|
|
|
|
+9. [FastAPI ERP 桥接服务](#9-fastapi-erp-桥接服务)
|
|
|
|
|
+10. [日常更新流程](#10-日常更新流程)
|
|
|
|
|
+11. [部署验证清单](#11-部署验证清单)
|
|
|
|
|
+12. [环境变量速查](#12-环境变量速查)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 1. 环境要求
|
|
|
|
|
+
|
|
|
|
|
+| 项目 | 详情 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| 操作系统 | AlmaLinux 8.10 |
|
|
|
|
|
+| Web 服务器 | Apache httpd(主站已有,共用) |
|
|
|
|
|
+| 部署路径 | `/redant/web/homelegance-chatbot` |
|
|
|
|
|
+| Node.js | v20.20.2 LTS |
|
|
|
|
|
+| 包管理器 | pnpm v10.x |
|
|
|
|
|
+| 进程管理 | PM2 |
|
|
|
|
|
+| 数据库 | 内网独立 PostgreSQL 服务器,Schema `chatbot` |
|
|
|
|
|
+| LLM API | Anthropic Claude API(`claude-sonnet-4-6`) |
|
|
|
|
|
+| ERP 桥接 | Python FastAPI,端口 8080,仅本机访问 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 2. Node.js 安装
|
|
|
|
|
+
|
|
|
|
|
+### 2.1 通过 NodeSource 安装 Node.js 20
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 需要服务器能访问外网(如有防火墙限制,先联系 IT 放行 nodesource.com)
|
|
|
|
|
+curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
|
|
|
|
|
+sudo dnf install -y nodejs --allowerasing
|
|
|
|
|
+node --version # 应输出 v20.x.x
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+> **注意**:安装前如有旧版 Node.js(v10),需先卸载:
|
|
|
|
|
+> ```bash
|
|
|
|
|
+> sudo dnf remove -y nodejs npm
|
|
|
|
|
+> ```
|
|
|
|
|
+
|
|
|
|
|
+### 2.2 安装 pnpm 和 PM2
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+npm install -g pnpm pm2
|
|
|
|
|
+pnpm --version
|
|
|
|
|
+pm2 --version
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 2.3 安装 Python(用于 ERP 桥接服务)
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+sudo dnf install -y python3.11 python3.11-pip
|
|
|
|
|
+pip3.11 install fastapi uvicorn asyncpg python-dotenv
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 3. 代码部署
|
|
|
|
|
+
|
|
|
|
|
+### 3.1 克隆代码
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+sudo mkdir -p /redant/web/homelegance-chatbot
|
|
|
|
|
+cd /redant/web
|
|
|
|
|
+sudo git clone https://git.united-us.net/TonyT/chatbot.git homelegance-chatbot
|
|
|
|
|
+sudo chown -R $USER:$USER homelegance-chatbot
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 3.2 安装依赖
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd /redant/web/homelegance-chatbot
|
|
|
|
|
+pnpm install --frozen-lockfile
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 4. 数据库初始化
|
|
|
|
|
+
|
|
|
|
|
+### 4.1 在内网 PostgreSQL 服务器上创建数据库和用户
|
|
|
|
|
+
|
|
|
|
|
+```sql
|
|
|
|
|
+-- 以管理员身份在 PostgreSQL 服务器执行
|
|
|
|
|
+CREATE DATABASE homelegance_chat;
|
|
|
|
|
+CREATE USER chatbot_user WITH PASSWORD '<强密码>';
|
|
|
|
|
+GRANT ALL PRIVILEGES ON DATABASE homelegance_chat TO chatbot_user;
|
|
|
|
|
+
|
|
|
|
|
+-- 连接到 homelegance_chat 库后创建 Schema
|
|
|
|
|
+\c homelegance_chat
|
|
|
|
|
+CREATE SCHEMA chatbot;
|
|
|
|
|
+GRANT ALL ON SCHEMA chatbot TO chatbot_user;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 4.2 执行 Drizzle 迁移
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd /redant/web/homelegance-chatbot
|
|
|
|
|
+
|
|
|
|
|
+# 确保 .env.production 中 DATABASE_URL 已正确配置
|
|
|
|
|
+export DATABASE_URL="postgresql://chatbot_user:<密码>@<内网PG地址>:5432/homelegance_chat"
|
|
|
|
|
+
|
|
|
|
|
+pnpm db:push
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+> Drizzle 会自动在 `chatbot` schema 下创建所有表和枚举类型。
|
|
|
|
|
+
|
|
|
|
|
+### 4.3 创建管理员账号
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 首次部署后,通过 /chat/register 页面注册第一个账号
|
|
|
|
|
+# 然后在数据库中将其提升为 admin
|
|
|
|
|
+psql -U chatbot_user -h <内网PG地址> -d homelegance_chat -c \
|
|
|
|
|
+ "UPDATE chatbot.users SET role='admin' WHERE email='<管理员邮箱>';"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 5. 环境变量配置
|
|
|
|
|
+
|
|
|
|
|
+复制模板并填写真实值:
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cp /redant/web/homelegance-chatbot/deploy/env.production.example \
|
|
|
|
|
+ /redant/web/homelegance-chatbot/.env.production
|
|
|
|
|
+nano /redant/web/homelegance-chatbot/.env.production
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**`.env.production` 内容说明:**
|
|
|
|
|
+
|
|
|
|
|
+```env
|
|
|
|
|
+NODE_ENV=production
|
|
|
|
|
+PORT=3000
|
|
|
|
|
+
|
|
|
|
|
+# Chatbot 自身数据库(内网 PostgreSQL)
|
|
|
|
|
+DATABASE_URL=postgresql://chatbot_user:<密码>@<内网PG地址>:5432/homelegance_chat
|
|
|
|
|
+
|
|
|
|
|
+# JWT 签名密钥(随机生成64字符)
|
|
|
|
|
+JWT_SECRET=<openssl rand -hex 32>
|
|
|
|
|
+
|
|
|
|
|
+# Anthropic Claude API
|
|
|
|
|
+ANTHROPIC_API_KEY=sk-ant-...
|
|
|
|
|
+
|
|
|
|
|
+# ERP 桥接服务(内网,仅本机访问)
|
|
|
|
|
+ERP_API_URL=http://127.0.0.1:8080
|
|
|
|
|
+ERP_API_KEY=<内部随机密钥>
|
|
|
|
|
+
|
|
|
|
|
+# Dealer Portal SSO 共享密钥
|
|
|
|
|
+DEALER_PORTAL_SSO_SECRET=<与Portal约定的JWT签名密钥>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 6. 构建与启动
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd /redant/web/homelegance-chatbot
|
|
|
|
|
+
|
|
|
|
|
+# 构建前端(输出到 dist/public/)和后端(输出到 dist/index.js)
|
|
|
|
|
+pnpm build
|
|
|
|
|
+
|
|
|
|
|
+# 验证构建产物
|
|
|
|
|
+ls dist/public/ # 应有 index.html、assets/ 等
|
|
|
|
|
+ls dist/index.js # 后端入口
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 7. PM2 进程管理
|
|
|
|
|
+
|
|
|
|
|
+### 7.1 配置文件
|
|
|
|
|
+
|
|
|
|
|
+`ecosystem.config.cjs` 已在项目根目录:
|
|
|
|
|
+
|
|
|
|
|
+```js
|
|
|
|
|
+module.exports = {
|
|
|
|
|
+ apps: [{
|
|
|
|
|
+ name: 'homelegance-chat',
|
|
|
|
|
+ script: './dist/index.js',
|
|
|
|
|
+ env_file: '.env.production',
|
|
|
|
|
+ instances: 1,
|
|
|
|
|
+ autorestart: true,
|
|
|
|
|
+ max_memory_restart: '512M',
|
|
|
|
|
+ }]
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 7.2 启动与自启
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd /redant/web/homelegance-chatbot
|
|
|
|
|
+pm2 start ecosystem.config.cjs
|
|
|
|
|
+pm2 save
|
|
|
|
|
+
|
|
|
|
|
+# 配置系统启动时自动拉起(只需执行一次)
|
|
|
|
|
+pm2 startup systemd
|
|
|
|
|
+# 按提示执行输出的 sudo 命令
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 7.3 常用命令
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+pm2 list # 查看进程状态
|
|
|
|
|
+pm2 logs homelegance-chat # 查看实时日志
|
|
|
|
|
+pm2 logs homelegance-chat --lines 100 # 查看最近100行日志
|
|
|
|
|
+pm2 restart homelegance-chat # 重启服务
|
|
|
|
|
+pm2 stop homelegance-chat # 停止服务
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 8. Apache 配置
|
|
|
|
|
+
|
|
|
|
|
+### 8.1 说明
|
|
|
|
|
+
|
|
|
|
|
+Chatbot 挂载在 **www.homelegance.com 主站的 `/chat/` 路径下**,无需新建 VirtualHost。将 `deploy/homelegance-chat.conf` 中的内容添加到主站配置文件的 `<VirtualHost *:443>` 块内即可。
|
|
|
|
|
+
|
|
|
|
|
+### 8.2 主站配置文件位置
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 查找主站配置文件
|
|
|
|
|
+grep -r "ServerName.*homelegance.com" /etc/httpd/conf.d/
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 8.3 添加配置
|
|
|
|
|
+
|
|
|
|
|
+在主站 `<VirtualHost *:443>` 块内追加:
|
|
|
|
|
+
|
|
|
|
|
+```apache
|
|
|
|
|
+# ── Chatbot API:代理到 Node.js :3000 ─────────────────────────
|
|
|
|
|
+# ProxyPass 必须在 Alias 之前声明
|
|
|
|
|
+ProxyPreserveHost On
|
|
|
|
|
+ProxyPass /chat/api http://127.0.0.1:3000/api
|
|
|
|
|
+ProxyPassReverse /chat/api http://127.0.0.1:3000/api
|
|
|
|
|
+
|
|
|
|
|
+# ── Chatbot 静态文件:由 Apache 直接服务 ───────────────────────
|
|
|
|
|
+Alias /chat /redant/web/homelegance-chatbot/dist/public
|
|
|
|
|
+<Directory /redant/web/homelegance-chatbot/dist/public>
|
|
|
|
|
+ Options -Indexes
|
|
|
|
|
+ AllowOverride None
|
|
|
|
|
+ Require all granted
|
|
|
|
|
+</Directory>
|
|
|
|
|
+
|
|
|
|
|
+# ── SPA fallback:/chat/* 非文件请求返回 index.html ───────────
|
|
|
|
|
+RewriteEngine On
|
|
|
|
|
+RewriteCond %{REQUEST_URI} ^/chat/
|
|
|
|
|
+RewriteCond %{REQUEST_URI} !/chat/api/
|
|
|
|
|
+RewriteCond %{REQUEST_FILENAME} !-f
|
|
|
|
|
+RewriteRule ^ /redant/web/homelegance-chatbot/dist/public/index.html [L]
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 8.4 重载 Apache
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 检查配置语法
|
|
|
|
|
+sudo apachectl configtest
|
|
|
|
|
+
|
|
|
|
|
+# 重载(不中断现有连接)
|
|
|
|
|
+sudo systemctl reload httpd
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 8.5 确认所需模块已启用
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+httpd -M | grep -E "proxy|rewrite|alias"
|
|
|
|
|
+# 应看到:proxy_module, proxy_http_module, rewrite_module, alias_module
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+如未启用:
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+sudo dnf install -y mod_proxy_http
|
|
|
|
|
+# 在 /etc/httpd/conf.modules.d/ 中取消对应模块的注释
|
|
|
|
|
+sudo systemctl restart httpd
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 9. FastAPI ERP 桥接服务
|
|
|
|
|
+
|
|
|
|
|
+> **用途**:提供从 Chatbot 查询 ERP PostgreSQL 数据的只读接口,仅绑定 127.0.0.1,Apache 不代理此端口,外网不可达。
|
|
|
|
|
+
|
|
|
|
|
+### 9.1 创建服务目录
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+sudo mkdir -p /redant/web/erp-bridge
|
|
|
|
|
+sudo chown $USER:$USER /redant/web/erp-bridge
|
|
|
|
|
+cd /redant/web/erp-bridge
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 9.2 创建 `.env` 文件
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cat > /redant/web/erp-bridge/.env << 'EOF'
|
|
|
|
|
+ERP_DATABASE_URL=postgresql://chatbot_readonly:<密码>@<ERP_PG地址>:5432/<ERP数据库名>
|
|
|
|
|
+ERP_API_KEY=<与chatbot共享的内部随机密钥>
|
|
|
|
|
+PORT=8080
|
|
|
|
|
+EOF
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 9.3 创建 `main.py`
|
|
|
|
|
+
|
|
|
|
|
+```python
|
|
|
|
|
+from fastapi import FastAPI, HTTPException, Header, Depends
|
|
|
|
|
+from contextlib import asynccontextmanager
|
|
|
|
|
+from pydantic import BaseModel
|
|
|
|
|
+from typing import Optional
|
|
|
|
|
+import asyncpg, os
|
|
|
|
|
+from dotenv import load_dotenv
|
|
|
|
|
+
|
|
|
|
|
+load_dotenv()
|
|
|
|
|
+
|
|
|
|
|
+DB_POOL = None
|
|
|
|
|
+API_KEY = os.getenv("ERP_API_KEY")
|
|
|
|
|
+
|
|
|
|
|
+@asynccontextmanager
|
|
|
|
|
+async def lifespan(app: FastAPI):
|
|
|
|
|
+ global DB_POOL
|
|
|
|
|
+ DB_POOL = await asyncpg.create_pool(
|
|
|
|
|
+ os.getenv("ERP_DATABASE_URL"), min_size=2, max_size=10
|
|
|
|
|
+ )
|
|
|
|
|
+ yield
|
|
|
|
|
+ await DB_POOL.close()
|
|
|
|
|
+
|
|
|
|
|
+app = FastAPI(lifespan=lifespan)
|
|
|
|
|
+
|
|
|
|
|
+def verify_key(x_api_key: str = Header()):
|
|
|
|
|
+ if x_api_key != API_KEY:
|
|
|
|
|
+ raise HTTPException(status_code=401, detail="Unauthorized")
|
|
|
|
|
+
|
|
|
|
|
+# 健康检查
|
|
|
|
|
+@app.get("/health")
|
|
|
|
|
+async def health():
|
|
|
|
|
+ return {"status": "ok"}
|
|
|
|
|
+
|
|
|
|
|
+# 产品目录查询
|
|
|
|
|
+class CatalogQuery(BaseModel):
|
|
|
|
|
+ category: Optional[str] = None
|
|
|
|
|
+ model: Optional[str] = None
|
|
|
|
|
+ description: Optional[str] = None
|
|
|
|
|
+ limit: int = 20
|
|
|
|
|
+
|
|
|
|
|
+@app.post("/catalog", dependencies=[Depends(verify_key)])
|
|
|
|
|
+async def catalog(q: CatalogQuery):
|
|
|
|
|
+ # 根据实际 ERP 表结构调整
|
|
|
|
|
+ rows = await DB_POOL.fetch(
|
|
|
|
|
+ "SELECT item_code, description, category FROM items WHERE "
|
|
|
|
|
+ "($1::text IS NULL OR category ILIKE $1) AND "
|
|
|
|
|
+ "($2::text IS NULL OR item_code ILIKE $2) "
|
|
|
|
|
+ "LIMIT $3",
|
|
|
|
|
+ f"%{q.category}%" if q.category else None,
|
|
|
|
|
+ f"%{q.model}%" if q.model else None,
|
|
|
|
|
+ q.limit
|
|
|
|
|
+ )
|
|
|
|
|
+ return [dict(r) for r in rows]
|
|
|
|
|
+
|
|
|
|
|
+# 订单列表查询
|
|
|
|
|
+class OrderQuery(BaseModel):
|
|
|
|
|
+ so_id: Optional[str] = None
|
|
|
|
|
+ customer_name: Optional[str] = None
|
|
|
|
|
+ limit: int = 10
|
|
|
|
|
+
|
|
|
|
|
+@app.post("/orders", dependencies=[Depends(verify_key)])
|
|
|
|
|
+async def orders(q: OrderQuery):
|
|
|
|
|
+ rows = await DB_POOL.fetch(
|
|
|
|
|
+ "SELECT so_id, customer_name, status, order_date FROM sales_orders WHERE "
|
|
|
|
|
+ "($1::text IS NULL OR so_id ILIKE $1) AND "
|
|
|
|
|
+ "($2::text IS NULL OR customer_name ILIKE $2) "
|
|
|
|
|
+ "ORDER BY order_date DESC LIMIT $3",
|
|
|
|
|
+ f"%{q.so_id}%" if q.so_id else None,
|
|
|
|
|
+ f"%{q.customer_name}%" if q.customer_name else None,
|
|
|
|
|
+ q.limit
|
|
|
|
|
+ )
|
|
|
|
|
+ return [dict(r) for r in rows]
|
|
|
|
|
+
|
|
|
|
|
+# 单个订单详情
|
|
|
|
|
+@app.get("/orders/{so_id}", dependencies=[Depends(verify_key)])
|
|
|
|
|
+async def order_detail(so_id: str):
|
|
|
|
|
+ row = await DB_POOL.fetchrow(
|
|
|
|
|
+ "SELECT * FROM sales_orders WHERE so_id = $1", so_id
|
|
|
|
|
+ )
|
|
|
|
|
+ if not row:
|
|
|
|
|
+ raise HTTPException(status_code=404, detail="Order not found")
|
|
|
|
|
+ items = await DB_POOL.fetch(
|
|
|
|
|
+ "SELECT item_code, qty, price FROM sales_order_items WHERE so_id = $1", so_id
|
|
|
|
|
+ )
|
|
|
|
|
+ return {**dict(row), "items": [dict(i) for i in items]}
|
|
|
|
|
+
|
|
|
|
|
+# 库存查询
|
|
|
|
|
+class StockQuery(BaseModel):
|
|
|
|
|
+ model: str
|
|
|
|
|
+ limit: int = 20
|
|
|
|
|
+
|
|
|
|
|
+@app.post("/stock", dependencies=[Depends(verify_key)])
|
|
|
|
|
+async def stock(q: StockQuery):
|
|
|
|
|
+ rows = await DB_POOL.fetch(
|
|
|
|
|
+ "SELECT item_code, warehouse, qty_available FROM stock WHERE item_code ILIKE $1 LIMIT $2",
|
|
|
|
|
+ f"%{q.model}%", q.limit
|
|
|
|
|
+ )
|
|
|
|
|
+ return [dict(r) for r in rows]
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 9.4 DBA 创建 ERP 只读账号
|
|
|
|
|
+
|
|
|
|
|
+```sql
|
|
|
|
|
+-- 在 ERP PostgreSQL 服务器执行
|
|
|
|
|
+CREATE USER chatbot_readonly WITH PASSWORD '<密码>';
|
|
|
|
|
+GRANT SELECT ON TABLE items, contacts, sales_orders, sales_order_items, stock
|
|
|
|
|
+ TO chatbot_readonly;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 9.5 Systemd 服务(`deploy/erp-bridge.service`)
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+sudo cp /redant/web/homelegance-chatbot/deploy/erp-bridge.service \
|
|
|
|
|
+ /etc/systemd/system/erp-bridge.service
|
|
|
|
|
+sudo systemctl daemon-reload
|
|
|
|
|
+sudo systemctl enable --now erp-bridge
|
|
|
|
|
+sudo systemctl status erp-bridge
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**验证:**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+curl http://127.0.0.1:8080/health
|
|
|
|
|
+# 应返回:{"status":"ok"}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 10. 日常更新流程
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd /redant/web/homelegance-chatbot
|
|
|
|
|
+
|
|
|
|
|
+# 1. 拉取最新代码
|
|
|
|
|
+git pull origin master
|
|
|
|
|
+
|
|
|
|
|
+# 2. 更新依赖(仅新增包时需要)
|
|
|
|
|
+pnpm install --frozen-lockfile
|
|
|
|
|
+
|
|
|
|
|
+# 3. 重新构建
|
|
|
|
|
+pnpm build
|
|
|
|
|
+
|
|
|
|
|
+# 4. 重启 Node.js(Apache 静态文件无需重启)
|
|
|
|
|
+pm2 restart homelegance-chat
|
|
|
|
|
+
|
|
|
|
|
+# 5. 验证
|
|
|
|
|
+pm2 logs homelegance-chat --lines 20
|
|
|
|
|
+curl -I https://www.homelegance.com/chat/
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 11. 部署验证清单
|
|
|
|
|
+
|
|
|
|
|
+| 检查项 | 命令/方式 | 预期结果 |
|
|
|
|
|
+|--------|-----------|----------|
|
|
|
|
|
+| Node.js 版本 | `node --version` | v20.x.x |
|
|
|
|
|
+| pnpm 版本 | `pnpm --version` | v10.x.x |
|
|
|
|
|
+| PM2 进程运行 | `pm2 list` | `homelegance-chat` online |
|
|
|
|
|
+| Node.js 监听端口 | `ss -tlnp \| grep 3000` | 0.0.0.0:3000 |
|
|
|
|
|
+| FastAPI 运行 | `curl http://127.0.0.1:8080/health` | `{"status":"ok"}` |
|
|
|
|
|
+| Apache 配置语法 | `sudo apachectl configtest` | Syntax OK |
|
|
|
|
|
+| 首页可访问 | `curl -I https://www.homelegance.com/chat/` | HTTP 200 |
|
|
|
|
|
+| API 可访问 | `curl https://www.homelegance.com/chat/api/trpc` | JSON 响应 |
|
|
|
|
|
+| 数据库连接 | `pm2 logs` 中无 DB 错误 | 无报错 |
|
|
|
|
|
+| HTTPS 证书 | 浏览器访问 | 无证书警告 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 12. 环境变量速查
|
|
|
|
|
+
|
|
|
|
|
+| 变量名 | 说明 | 示例 |
|
|
|
|
|
+|--------|------|------|
|
|
|
|
|
+| `NODE_ENV` | 运行环境 | `production` |
|
|
|
|
|
+| `PORT` | Node.js 监听端口 | `3000` |
|
|
|
|
|
+| `DATABASE_URL` | Chatbot 自身 PG 连接串 | `postgresql://chatbot_user:pwd@db:5432/homelegance_chat` |
|
|
|
|
|
+| `JWT_SECRET` | JWT 签名密钥(64字符随机) | `openssl rand -hex 32` |
|
|
|
|
|
+| `ANTHROPIC_API_KEY` | Claude API 密钥 | `sk-ant-...` |
|
|
|
|
|
+| `ERP_API_URL` | ERP 桥接服务地址 | `http://127.0.0.1:8080` |
|
|
|
|
|
+| `ERP_API_KEY` | ERP 桥接内部密钥 | 随机字符串 |
|
|
|
|
|
+| `DEALER_PORTAL_SSO_SECRET` | Dealer Portal SSO 共享密钥 | HS256 签名密钥 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 附录
|
|
|
|
|
+
|
|
|
|
|
+### Git 仓库
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+https://git.united-us.net/TonyT/chatbot.git
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### deploy/ 目录文件说明
|
|
|
|
|
+
|
|
|
|
|
+| 文件 | 用途 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| `homelegance-chat.conf` | Apache 配置片段(添加到主站 VirtualHost) |
|
|
|
|
|
+| `erp-bridge.service` | FastAPI ERP 桥接的 systemd 服务文件 |
|
|
|
|
|
+| `env.production.example` | 环境变量模板 |
|
|
|
|
|
+| `部署文档.md` | 本文档 |
|
|
|
|
|
+
|
|
|
|
|
+### 目录结构
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+/redant/web/
|
|
|
|
|
+├── homelegance-chatbot/ ← Chatbot 项目
|
|
|
|
|
+│ ├── dist/
|
|
|
|
|
+│ │ ├── public/ ← 前端静态文件(Apache 直接服务)
|
|
|
|
|
+│ │ └── index.js ← 后端入口(PM2 管理)
|
|
|
|
|
+│ ├── .env.production ← 环境变量(不提交 Git)
|
|
|
|
|
+│ └── ecosystem.config.cjs ← PM2 配置
|
|
|
|
|
+└── erp-bridge/ ← FastAPI ERP 桥接服务
|
|
|
|
|
+ ├── main.py
|
|
|
|
|
+ └── .env
|
|
|
|
|
+```
|