docs: replace environment-specific IPs with localhost
This commit is contained in:
@@ -50,7 +50,7 @@ function loadConfig(env = process.env) {
|
|||||||
siteSearchUrl: String(pick('SITE_SEARCH_URL', 'https://www.yehwang.com/search.html?q=')),
|
siteSearchUrl: String(pick('SITE_SEARCH_URL', 'https://www.yehwang.com/search.html?q=')),
|
||||||
|
|
||||||
// widget 身份签发:站点 JWT -> LibreDesk widget JWT
|
// widget 身份签发:站点 JWT -> LibreDesk widget JWT
|
||||||
libredeskBaseUrl: String(pick('LIBREDESK_BASE_URL', 'http://192.168.31.61:9000')).replace(/\/+$/, ''),
|
libredeskBaseUrl: String(pick('LIBREDESK_BASE_URL', 'http://localhost:9000')).replace(/\/+$/, ''),
|
||||||
libredeskApiKey: String(pick('LIBREDESK_API_KEY', '')),
|
libredeskApiKey: String(pick('LIBREDESK_API_KEY', '')),
|
||||||
libredeskApiSecret: String(pick('LIBREDESK_API_SECRET', '')),
|
libredeskApiSecret: String(pick('LIBREDESK_API_SECRET', '')),
|
||||||
libredeskWebhookSecret: String(pick('LIBREDESK_WEBHOOK_SECRET', '')),
|
libredeskWebhookSecret: String(pick('LIBREDESK_WEBHOOK_SECRET', '')),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ server {
|
|||||||
client_max_body_size 30M;
|
client_max_body_size 30M;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://127.0.0.1:9000;
|
proxy_pass http://localhost:9000;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection 'upgrade';
|
proxy_set_header Connection 'upgrade';
|
||||||
|
|||||||
+5
-5
@@ -4,9 +4,9 @@ name: crm-new
|
|||||||
# 与旧栈 crm/crm-ai-demo 完全隔离:独立 PG/Redis/端口/数据卷。
|
# 与旧栈 crm/crm-ai-demo 完全隔离:独立 PG/Redis/端口/数据卷。
|
||||||
#
|
#
|
||||||
# 对外端口:
|
# 对外端口:
|
||||||
# LibreDesk http://192.168.31.61:9000
|
# LibreDesk http://localhost:9000
|
||||||
# Twenty http://192.168.31.61:3100
|
# Twenty http://localhost:3100
|
||||||
# bridge http://192.168.31.61:4100
|
# bridge http://localhost:4100
|
||||||
# Postgres(宿主机) 127.0.0.1:5440
|
# Postgres(宿主机) 127.0.0.1:5440
|
||||||
# Redis(宿主机) 127.0.0.1:6390
|
# Redis(宿主机) 127.0.0.1:6390
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
NODE_PORT: 3000
|
NODE_PORT: 3000
|
||||||
PG_DATABASE_URL: postgres://${POSTGRES_USER:-crmnew}:${POSTGRES_PASSWORD}@postgres:5432/twenty
|
PG_DATABASE_URL: postgres://${POSTGRES_USER:-crmnew}:${POSTGRES_PASSWORD}@postgres:5432/twenty
|
||||||
SERVER_URL: ${TWENTY_SERVER_URL:-http://192.168.31.61:3100}
|
SERVER_URL: ${TWENTY_SERVER_URL:-http://localhost:3100}
|
||||||
REDIS_URL: redis://redis:6379/1
|
REDIS_URL: redis://redis:6379/1
|
||||||
DISABLE_DB_MIGRATIONS: "false"
|
DISABLE_DB_MIGRATIONS: "false"
|
||||||
DISABLE_CRON_JOBS_REGISTRATION: "false"
|
DISABLE_CRON_JOBS_REGISTRATION: "false"
|
||||||
@@ -113,7 +113,7 @@ services:
|
|||||||
command: ["yarn", "worker:prod"]
|
command: ["yarn", "worker:prod"]
|
||||||
environment:
|
environment:
|
||||||
PG_DATABASE_URL: postgres://${POSTGRES_USER:-crmnew}:${POSTGRES_PASSWORD}@postgres:5432/twenty
|
PG_DATABASE_URL: postgres://${POSTGRES_USER:-crmnew}:${POSTGRES_PASSWORD}@postgres:5432/twenty
|
||||||
SERVER_URL: ${TWENTY_SERVER_URL:-http://192.168.31.61:3100}
|
SERVER_URL: ${TWENTY_SERVER_URL:-http://localhost:3100}
|
||||||
REDIS_URL: redis://redis:6379/1
|
REDIS_URL: redis://redis:6379/1
|
||||||
DISABLE_DB_MIGRATIONS: "true"
|
DISABLE_DB_MIGRATIONS: "true"
|
||||||
DISABLE_CRON_JOBS_REGISTRATION: "true"
|
DISABLE_CRON_JOBS_REGISTRATION: "true"
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ LibreDesk 创建会话 → Automation 分配给 AI Assistant
|
|||||||
| LibreDesk / Chatwoot | 9000 | 3001 |
|
| LibreDesk / Chatwoot | 9000 | 3001 |
|
||||||
| Twenty | 3100 | 3000 |
|
| Twenty | 3100 | 3000 |
|
||||||
| bridge | 4100 | 4000 |
|
| bridge | 4100 | 4000 |
|
||||||
| Postgres | 127.0.0.1:5440 | 127.0.0.1:5432 |
|
| Postgres | localhost:5440 | localhost:5432 |
|
||||||
| Redis | 127.0.0.1:6390 | 127.0.0.1:6379 |
|
| Redis | localhost:6390 | localhost:6379 |
|
||||||
|
|
||||||
新栈 Postgres 内含三个库:`libredesk` / `twenty` / `bridge`;Redis 分 db:LibreDesk=2、Twenty=1、bridge=3。
|
新栈 Postgres 内含三个库:`libredesk` / `twenty` / `bridge`;Redis 分 db:LibreDesk=2、Twenty=1、bridge=3。
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -57,14 +57,14 @@ Email (inbox 2) / WhatsApp (inbox 3)
|
|||||||
|
|
||||||
| 服务 | 地址 | 备注 |
|
| 服务 | 地址 | 备注 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| LibreDesk | `http://192.168.31.61:9000` | 管理端 / 工作台 |
|
| LibreDesk | `http://localhost:9000` | 管理端 / 工作台 |
|
||||||
| Twenty CRM | `http://192.168.31.61:3100` | CRM |
|
| Twenty CRM | `http://localhost:3100` | CRM |
|
||||||
| bridge | `http://192.168.31.61:4100` | 内部工具/健康检查 |
|
| bridge | `http://localhost:4100` | 内部工具/健康检查 |
|
||||||
| Widget 测试页 | `http://192.168.31.61:8088/demo.html` | 本机测试用 |
|
| Widget 测试页 | `http://localhost:8088/demo.html` | 本机测试用 |
|
||||||
| 公网入口 | `.env` 的 `PUBLIC_BASE_URL` | Cloudflare Quick Tunnel,**URL 会变** |
|
| 公网入口 | `.env` 的 `PUBLIC_BASE_URL` | Cloudflare Quick Tunnel,**URL 会变** |
|
||||||
| Postgres | `127.0.0.1:5440` | 仅本机 |
|
| Postgres | `localhost:5440` | 仅本机 |
|
||||||
| Redis | `127.0.0.1:6390` | 仅本机 |
|
| Redis | `localhost:6390` | 仅本机 |
|
||||||
| IMAP proxy | `127.0.0.1:1993` | 仅本机 |
|
| IMAP proxy | `localhost:1993` | 仅本机 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -190,8 +190,8 @@ Cloudflare Quick Tunnel URL 每次重启可能变化,需要同步:
|
|||||||
### 7.1 基础健康
|
### 7.1 基础健康
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s http://127.0.0.1:4100/healthz
|
curl -s http://localhost:4100/healthz
|
||||||
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3100/healthz
|
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3100/healthz
|
||||||
cd bridge && npm test
|
cd bridge && npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
```bash
|
```bash
|
||||||
bash scripts/bootstrap.sh # LibreDesk 已启动
|
bash scripts/bootstrap.sh # LibreDesk 已启动
|
||||||
bash scripts/start-tools.sh # 另开终端,tools 服务 :4010
|
bash scripts/start-tools.sh # 另开终端,tools 服务 :4010
|
||||||
curl -s http://127.0.0.1:4100/healthz
|
curl -s http://localhost:4100/healthz
|
||||||
```
|
```
|
||||||
|
|
||||||
## 1. AI Provider(必须先配)
|
## 1. AI Provider(必须先配)
|
||||||
@@ -33,7 +33,7 @@ curl -s http://127.0.0.1:4100/healthz
|
|||||||
|
|
||||||
本栈已把旧 `customer-service-kb` 导入为**帮助中心文章**(而不是 snippets),原因:只有文章能被 AI 引用(`[[cite:id]]`),并且同时进入帮助中心站内搜索。
|
本栈已把旧 `customer-service-kb` 导入为**帮助中心文章**(而不是 snippets),原因:只有文章能被 AI 引用(`[[cite:id]]`),并且同时进入帮助中心站内搜索。
|
||||||
|
|
||||||
公开地址:`http://192.168.31.61:9000/hc/yehwang-help/en`(1 个帮助中心 / 9 个 collection / 108 篇文章,全部 `published + ai_enabled`)。
|
公开地址:`http://localhost:9000/hc/yehwang-help/en`(1 个帮助中心 / 9 个 collection / 108 篇文章,全部 `published + ai_enabled`)。
|
||||||
|
|
||||||
重新导入(幂等):
|
重新导入(幂等):
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ node scripts/import-kb-helpcenter.js # 登录 System 并导入
|
|||||||
3. **API 批量导入**(迁移旧 KB 时用):
|
3. **API 批量导入**(迁移旧 KB 时用):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST http://192.168.31.61:9000/api/v1/ai/snippets \
|
curl -X POST http://localhost:9000/api/v1/ai/snippets \
|
||||||
-H "Authorization: token ${LIBREDESK_API_KEY}:${LIBREDESK_API_SECRET}" \
|
-H "Authorization: token ${LIBREDESK_API_KEY}:${LIBREDESK_API_SECRET}" \
|
||||||
-H 'Content-Type: application/json' \
|
-H 'Content-Type: application/json' \
|
||||||
-d '{"title":"Minimum order","content":"The minimum order value is €30.","enabled":true}'
|
-d '{"title":"Minimum order","content":"The minimum order value is €30.","enabled":true}'
|
||||||
@@ -88,7 +88,7 @@ curl -X POST http://192.168.31.61:9000/api/v1/ai/snippets \
|
|||||||
| Copilot / Generate reply | 开 | 开 | 开 | 开 |
|
| Copilot / Generate reply | 开 | 开 | 开 | 开 |
|
||||||
| Require agent approval | 否 | 否 | 否 | 否 |
|
| Require agent approval | 否 | 否 | 否 | 否 |
|
||||||
|
|
||||||
`GET http://127.0.0.1:4100/tools/manifest`(带 `X-Tools-Key`)会输出每个工具的完整 JSON Schema,可直接复制。
|
`GET http://localhost:4100/tools/manifest`(带 `X-Tools-Key`)会输出每个工具的完整 JSON Schema,可直接复制。
|
||||||
|
|
||||||
## 4. 创建 AI Assistant
|
## 4. 创建 AI Assistant
|
||||||
|
|
||||||
@@ -152,11 +152,11 @@ Assistant **只有被分配给会话才会回复**。配置:
|
|||||||
```html
|
```html
|
||||||
<script>
|
<script>
|
||||||
window.LibredeskSettings = {
|
window.LibredeskSettings = {
|
||||||
baseURL: 'http://192.168.31.61:9000',
|
baseURL: 'http://localhost:9000',
|
||||||
inboxID: 'YOUR_INBOX_UUID'
|
inboxID: 'YOUR_INBOX_UUID'
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script async src="http://192.168.31.61:9000/widget.js"></script>
|
<script async src="http://localhost:9000/widget.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 登录用户身份锚定(已实现)
|
### 登录用户身份锚定(已实现)
|
||||||
@@ -220,7 +220,7 @@ const payload = {
|
|||||||
- [ ] widget 能开聊,收到 AI 回复
|
- [ ] widget 能开聊,收到 AI 回复
|
||||||
- [ ] 未验证时问订单 → AI 引导验证;验证后能查单
|
- [ ] 未验证时问订单 → AI 引导验证;验证后能查单
|
||||||
- [ ] 说“我要人工” → handoff 到 Support 团队
|
- [ ] 说“我要人工” → handoff 到 Support 团队
|
||||||
- [ ] `curl -s http://127.0.0.1:4100/healthz` 正常
|
- [ ] `curl -s http://localhost:4100/healthz` 正常
|
||||||
|
|
||||||
## 10. 常见问题
|
## 10. 常见问题
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -27,9 +27,9 @@ docker compose logs -f --tail=100 twenty-server
|
|||||||
docker compose logs -f --tail=100 bridge
|
docker compose logs -f --tail=100 bridge
|
||||||
|
|
||||||
# 健康
|
# 健康
|
||||||
curl -s http://192.168.31.61:9000/health
|
curl -s http://localhost:9000/health
|
||||||
curl -s http://192.168.31.61:3100/healthz
|
curl -s http://localhost:3100/healthz
|
||||||
curl -s http://192.168.31.61:4100/healthz
|
curl -s http://localhost:4100/healthz
|
||||||
```
|
```
|
||||||
|
|
||||||
## 内容与 AI 配置脚本
|
## 内容与 AI 配置脚本
|
||||||
@@ -90,7 +90,7 @@ node scripts/configure-email.js
|
|||||||
node scripts/add-email-inbox.js
|
node scripts/add-email-inbox.js
|
||||||
|
|
||||||
# 本地静态测试页(widget 接入演示)
|
# 本地静态测试页(widget 接入演示)
|
||||||
bash scripts/serve-web.sh # http://192.168.31.61:8088/demo.html
|
bash scripts/serve-web.sh # http://localhost:8088/demo.html
|
||||||
|
|
||||||
# 端到端验证 widget JWT(登录用户可查订单)
|
# 端到端验证 widget JWT(登录用户可查订单)
|
||||||
node scripts/e2e-widget-jwt.js "Can you check the status of my order SO-1?"
|
node scripts/e2e-widget-jwt.js "Can you check the status of my order SO-1?"
|
||||||
@@ -159,7 +159,7 @@ ss -ltnp | grep -E ':(9000|3100|4100|5440|6390)\s'
|
|||||||
| 现象 | 原因 | 处理 |
|
| 现象 | 原因 | 处理 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 容器启动报 `database "xxx" does not exist` | 首次初始化脚本未执行 | `docker exec crmnew-postgres psql -U crmnew -d postgres -c 'CREATE DATABASE xxx;'` |
|
| 容器启动报 `database "xxx" does not exist` | 首次初始化脚本未执行 | `docker exec crmnew-postgres psql -U crmnew -d postgres -c 'CREATE DATABASE xxx;'` |
|
||||||
| bridge 健康检查 `connection refused` | 容器内 `localhost` 解析到 IPv6 | 健康检查已改用 `127.0.0.1` |
|
| bridge 健康检查 `connection refused` | 容器内 `localhost` 解析到 IPv6 | 健康检查固定用回环地址(避免 IPv6) |
|
||||||
| LibreDesk 反复重启 | System 密码不满足强度(10–72 位、大小写+数字+特殊字符) | 改 `.env` 的 `LIBREDESK_SYSTEM_USER_PASSWORD` 后重建 |
|
| LibreDesk 反复重启 | System 密码不满足强度(10–72 位、大小写+数字+特殊字符) | 改 `.env` 的 `LIBREDESK_SYSTEM_USER_PASSWORD` 后重建 |
|
||||||
| 工具 401 | `X-Tools-Key` 与 `TOOLS_SHARED_KEY` 不一致 | 核对 `.env` 与 LibreDesk 工具 Header |
|
| 工具 401 | `X-Tools-Key` 与 `TOOLS_SHARED_KEY` 不一致 | 核对 `.env` 与 LibreDesk 工具 Header |
|
||||||
| 工具 403 verification_required | 联系人未验证 | 先走平台 OTP 验证,或该工具不需要验证时关闭 `requires_verification` |
|
| 工具 403 verification_required | 联系人未验证 | 先走平台 OTP 验证,或该工具不需要验证时关闭 `requires_verification` |
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ TOOLS_SHARED_KEY=change-me-please
|
|||||||
# LibreDesk 容器访问宿主机的地址
|
# LibreDesk 容器访问宿主机的地址
|
||||||
TOOLS_PUBLIC_BASE_URL=http://host.docker.internal:4010
|
TOOLS_PUBLIC_BASE_URL=http://host.docker.internal:4010
|
||||||
|
|
||||||
# 业务 RPC(默认指向测试服 47.76.223.252)
|
# 业务 RPC(默认指向测试服 localhost)
|
||||||
RECOMMEND_URL=jsonrpc://47.76.223.252:24503
|
RECOMMEND_URL=jsonrpc://localhost:24503
|
||||||
ORDER_API_URL=jsonrpc://47.76.223.252:24505
|
ORDER_API_URL=jsonrpc://localhost:24505
|
||||||
INVENTORY_API_URL=jsonrpc://47.76.223.252:24509
|
INVENTORY_API_URL=jsonrpc://localhost:24509
|
||||||
MEMBER_RPC_URL=jsonrpc://47.76.223.252:24506
|
MEMBER_RPC_URL=jsonrpc://localhost:24506
|
||||||
RPC_TIMEOUT_MS=8000
|
RPC_TIMEOUT_MS=8000
|
||||||
|
|
||||||
# 商品搜索无结果时的兜底搜索页
|
# 商品搜索无结果时的兜底搜索页
|
||||||
|
|||||||
@@ -97,9 +97,9 @@ bash scripts/smoke.sh
|
|||||||
| 组件 | 地址 | 说明 |
|
| 组件 | 地址 | 说明 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| LibreDesk | http://localhost:9000 | `System` + bootstrap 生成的密码 |
|
| LibreDesk | http://localhost:9000 | `System` + bootstrap 生成的密码 |
|
||||||
| crm-tools | http://127.0.0.1:4010 | `/healthz`、`/tools/manifest`、`/tools/<name>` |
|
| crm-tools | http://localhost:4010 | `/healthz`、`/tools/manifest`、`/tools/<name>` |
|
||||||
| Postgres | 127.0.0.1:5433 | 独立实例,库 `libredesk` |
|
| Postgres | localhost:5433 | 独立实例,库 `libredesk` |
|
||||||
| Redis | 127.0.0.1:6380 | 独立实例 |
|
| Redis | localhost:6380 | 独立实例 |
|
||||||
|
|
||||||
## 工具清单
|
## 工具清单
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ const data = (j) => (j && j.data !== undefined ? j.data : j);
|
|||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const old = JSON.parse(fs.readFileSync(OLD_MAIL_CFG, 'utf8'));
|
const old = JSON.parse(fs.readFileSync(OLD_MAIL_CFG, 'utf8'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
const c = createClient(base);
|
const c = createClient(base);
|
||||||
await c.post('/api/v1/auth/login', { email: env.LIBREDESK_SYSTEM_EMAIL || 'System', password: env.LIBREDESK_SYSTEM_USER_PASSWORD });
|
await c.post('/api/v1/auth/login', { email: env.LIBREDESK_SYSTEM_EMAIL || 'System', password: env.LIBREDESK_SYSTEM_USER_PASSWORD });
|
||||||
console.log('登录成功');
|
console.log('登录成功');
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const data = (j) => (j && j.data !== undefined ? j.data : j);
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
const required = ['WA_PHONE_NUMBER_ID', 'WA_WABA_ID', 'WA_ACCESS_TOKEN', 'WA_APP_SECRET', 'WA_VERIFY_TOKEN'];
|
const required = ['WA_PHONE_NUMBER_ID', 'WA_WABA_ID', 'WA_ACCESS_TOKEN', 'WA_APP_SECRET', 'WA_VERIFY_TOKEN'];
|
||||||
const missing = required.filter((k) => !env[k]);
|
const missing = required.filter((k) => !env[k]);
|
||||||
if (missing.length) throw new Error(`.env 缺少: ${missing.join(', ')}`);
|
if (missing.length) throw new Error(`.env 缺少: ${missing.join(', ')}`);
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ echo "==================== crm-new 已启动 ===================="
|
|||||||
echo " LibreDesk : http://localhost:9000 (System / ${LIBREDESK_SYSTEM_USER_PASSWORD})"
|
echo " LibreDesk : http://localhost:9000 (System / ${LIBREDESK_SYSTEM_USER_PASSWORD})"
|
||||||
echo " Twenty : http://localhost:3100 (首次访问需注册 workspace)"
|
echo " Twenty : http://localhost:3100 (首次访问需注册 workspace)"
|
||||||
echo " bridge : http://localhost:4100 (/healthz, /tools/manifest)"
|
echo " bridge : http://localhost:4100 (/healthz, /tools/manifest)"
|
||||||
echo " Postgres : 127.0.0.1:5440 (libredesk / twenty / bridge)"
|
echo " Postgres : localhost:5440 (libredesk / twenty / bridge)"
|
||||||
echo " Redis : 127.0.0.1:6390"
|
echo " Redis : localhost:6390"
|
||||||
echo
|
echo
|
||||||
echo " 下一步:"
|
echo " 下一步:"
|
||||||
echo " 1. 打开 LibreDesk 配 AI Provider(DashScope)"
|
echo " 1. 打开 LibreDesk 配 AI Provider(DashScope)"
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ const mask = (k) => (k ? k.slice(0, 6) + '…' + k.slice(-4) : '(empty)');
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
const password = env.LIBREDESK_SYSTEM_USER_PASSWORD;
|
const password = env.LIBREDESK_SYSTEM_USER_PASSWORD;
|
||||||
const email = env.LIBREDESK_SYSTEM_EMAIL || 'System';
|
const email = env.LIBREDESK_SYSTEM_EMAIL || 'System';
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ function createClient(baseURL) {
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
|
|
||||||
// 163 凭据:优先 .env 覆盖,否则读旧项目 mail.config.json
|
// 163 凭据:优先 .env 覆盖,否则读旧项目 mail.config.json
|
||||||
let user = env.SMTP_USER;
|
let user = env.SMTP_USER;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const path = require('path');
|
|||||||
|
|
||||||
const ROOT = path.resolve(__dirname, '..');
|
const ROOT = path.resolve(__dirname, '..');
|
||||||
const message = process.argv.slice(2).join(' ') || 'Can you check the status of my order SO-1?';
|
const message = process.argv.slice(2).join(' ') || 'Can you check the status of my order SO-1?';
|
||||||
const SITE_ORIGIN = 'http://192.168.31.61:9000';
|
|
||||||
|
|
||||||
function loadEnv(file) {
|
function loadEnv(file) {
|
||||||
const out = {};
|
const out = {};
|
||||||
@@ -33,8 +32,9 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const lr = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const SITE_ORIGIN = process.env.SITE_ORIGIN || env.IDENTITY_CORS_ORIGIN || 'http://localhost:9000';
|
||||||
const bridge = (env.BRIDGE_BASE_URL || 'http://192.168.31.61:4100').replace(/\/+$/, '');
|
const lr = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
|
const bridge = (env.BRIDGE_BASE_URL || 'http://localhost:4100').replace(/\/+$/, '');
|
||||||
const inboxUUID = env.LIBREDESK_INBOX_UUID;
|
const inboxUUID = env.LIBREDESK_INBOX_UUID;
|
||||||
if (!inboxUUID) throw new Error('缺少 LIBREDESK_INBOX_UUID');
|
if (!inboxUUID) throw new Error('缺少 LIBREDESK_INBOX_UUID');
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
|
|
||||||
// 1. admin session: 找到 Website inbox 的 UUID
|
// 1. admin session: 找到 Website inbox 的 UUID
|
||||||
const loginRes = await fetch(`${base}/api/v1/auth/login`, {
|
const loginRes = await fetch(`${base}/api/v1/auth/login`, {
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ function asData(json) {
|
|||||||
// ---------------------------------------------------------------- main
|
// ---------------------------------------------------------------- main
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv();
|
const env = loadEnv();
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
const email = env.LIBREDESK_SYSTEM_EMAIL || 'System';
|
const email = env.LIBREDESK_SYSTEM_EMAIL || 'System';
|
||||||
const password = env.LIBREDESK_SYSTEM_USER_PASSWORD;
|
const password = env.LIBREDESK_SYSTEM_USER_PASSWORD;
|
||||||
if (!password) throw new Error('缺少 LIBREDESK_SYSTEM_USER_PASSWORD');
|
if (!password) throw new Error('缺少 LIBREDESK_SYSTEM_USER_PASSWORD');
|
||||||
|
|||||||
@@ -34,5 +34,5 @@ WhatsApp webhook 地址: $URL/webhooks/whatsapp/<inbox_id>
|
|||||||
/hc/* (帮助中心,AI 引用链接)
|
/hc/* (帮助中心,AI 引用链接)
|
||||||
/widget* /static/public/*
|
/widget* /static/public/*
|
||||||
|
|
||||||
管理后台 / API 仍只在内网 http://192.168.31.61:9000
|
管理后台 / API 仍只在内网 http://localhost:9000
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ function createClient(baseURL) {
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
const toolsKey = env.TOOLS_SHARED_KEY;
|
const toolsKey = env.TOOLS_SHARED_KEY;
|
||||||
if (!toolsKey) throw new Error('TOOLS_SHARED_KEY 未配置');
|
if (!toolsKey) throw new Error('TOOLS_SHARED_KEY 未配置');
|
||||||
|
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# 本地静态测试页(widget JWT 演示)
|
# 本地静态测试页(widget JWT 演示)
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
cd "$(dirname "${BASH_SOURCE[0]}")/../web"
|
cd "$(dirname "${BASH_SOURCE[0]}")/../web"
|
||||||
echo "http://192.168.31.61:${WEB_PORT:-8088}/demo.html"
|
echo "http://localhost:${WEB_PORT:-8088}/demo.html"
|
||||||
exec python3 -m http.server "${WEB_PORT:-8088}" --bind 0.0.0.0
|
exec python3 -m http.server "${WEB_PORT:-8088}" --bind 0.0.0.0
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function loadEnv(file) {
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
|
|
||||||
const login = await fetch(base + '/api/v1/auth/login', {
|
const login = await fetch(base + '/api/v1/auth/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ Never create an opportunity before the contact is verified.`;
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
const c = createClient(base);
|
const c = createClient(base);
|
||||||
await c.post('/api/v1/auth/login', { email: env.LIBREDESK_SYSTEM_EMAIL || 'System', password: env.LIBREDESK_SYSTEM_USER_PASSWORD });
|
await c.post('/api/v1/auth/login', { email: env.LIBREDESK_SYSTEM_EMAIL || 'System', password: env.LIBREDESK_SYSTEM_USER_PASSWORD });
|
||||||
console.log('登录成功');
|
console.log('登录成功');
|
||||||
@@ -147,7 +147,7 @@ async function main() {
|
|||||||
launcher: { position: 'right', icon_scale: 100, spacing: { side: 24, bottom: 24 } },
|
launcher: { position: 'right', icon_scale: 100, spacing: { side: 24, bottom: 24 } },
|
||||||
greeting_message: 'Hi! How can we help you today?',
|
greeting_message: 'Hi! How can we help you today?',
|
||||||
chat_introduction: 'Ask about products, orders, shipping or returns.',
|
chat_introduction: 'Ask about products, orders, shipping or returns.',
|
||||||
trusted_domains: ['192.168.31.61:8088', 'localhost:8088', '127.0.0.1:8088', '192.168.31.61', 'localhost', '127.0.0.1', 'www.yehwang.com', 'yehwang.com'],
|
trusted_domains: ['localhost:8088', '127.0.0.1:8088', 'localhost', '127.0.0.1', 'www.yehwang.com', 'yehwang.com'],
|
||||||
help: { help_center_id: 0 },
|
help: { help_center_id: 0 },
|
||||||
users: { allow_start_conversation: true, prevent_multiple_conversations: false },
|
users: { allow_start_conversation: true, prevent_multiple_conversations: false },
|
||||||
visitors: { allow_start_conversation: true, prevent_multiple_conversations: false },
|
visitors: { allow_start_conversation: true, prevent_multiple_conversations: false },
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.TWENTY_SERVER_URL || 'http://192.168.31.61:3100').replace(/\/+$/, '');
|
const base = (env.TWENTY_SERVER_URL || 'http://localhost:3100').replace(/\/+$/, '');
|
||||||
const email = env.TWENTY_ADMIN_EMAIL;
|
const email = env.TWENTY_ADMIN_EMAIL;
|
||||||
const password = env.TWENTY_ADMIN_PASSWORD;
|
const password = env.TWENTY_ADMIN_PASSWORD;
|
||||||
if (!email || !password) throw new Error('缺少 TWENTY_ADMIN_EMAIL / TWENTY_ADMIN_PASSWORD(写入 .env,不要硬编码)');
|
if (!email || !password) throw new Error('缺少 TWENTY_ADMIN_EMAIL / TWENTY_ADMIN_PASSWORD(写入 .env,不要硬编码)');
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ function createClient(baseURL) {
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const env = loadEnv(path.join(ROOT, '.env'));
|
const env = loadEnv(path.join(ROOT, '.env'));
|
||||||
const base = (env.LIBREDESK_BASE_URL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
const base = (env.LIBREDESK_BASE_URL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
const c = createClient(base);
|
const c = createClient(base);
|
||||||
await c.post('/api/v1/auth/login', { email: env.LIBREDESK_SYSTEM_EMAIL || 'System', password: env.LIBREDESK_SYSTEM_USER_PASSWORD });
|
await c.post('/api/v1/auth/login', { email: env.LIBREDESK_SYSTEM_EMAIL || 'System', password: env.LIBREDESK_SYSTEM_USER_PASSWORD });
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
## 首次使用
|
## 首次使用
|
||||||
|
|
||||||
1. 浏览器打开 `http://192.168.31.61:3100`
|
1. 浏览器打开 `http://localhost:3100`
|
||||||
2. 注册第一个 workspace(邮箱 + 密码),工作区名建议 `Yehwang`
|
2. 注册第一个 workspace(邮箱 + 密码),工作区名建议 `Yehwang`
|
||||||
3. 进入 **Settings → Developers → API Keys** 创建 API key(JWT 形式)
|
3. 进入 **Settings → Developers → API Keys** 创建 API key(JWT 形式)
|
||||||
4. 把 API key 和 workspace id 写入顶层 `.env`:
|
4. 把 API key 和 workspace id 写入顶层 `.env`:
|
||||||
@@ -35,7 +35,7 @@ docker compose up -d --force-recreate bridge
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash scripts/smoke.sh
|
bash scripts/smoke.sh
|
||||||
curl -s http://192.168.31.61:4100/healthz
|
curl -s http://localhost:4100/healthz
|
||||||
```
|
```
|
||||||
|
|
||||||
## 数据存储
|
## 数据存储
|
||||||
|
|||||||
+4
-4
@@ -5,9 +5,9 @@
|
|||||||
*
|
*
|
||||||
* <script>
|
* <script>
|
||||||
* window.YehwangChatConfig = {
|
* window.YehwangChatConfig = {
|
||||||
* baseURL: 'http://192.168.31.61:9000',
|
* baseURL: 'http://localhost:9000',
|
||||||
* inboxID: '10fd5207-d235-4c49-beaa-a65eed0ddd0e',
|
* inboxID: '10fd5207-d235-4c49-beaa-a65eed0ddd0e',
|
||||||
* identityURL: 'http://192.168.31.61:4100/identity',
|
* identityURL: 'http://localhost:4100/identity',
|
||||||
* siteJWT: window.__SITE_JWT__ || null // 站点登录后注入
|
* siteJWT: window.__SITE_JWT__ || null // 站点登录后注入
|
||||||
* };
|
* };
|
||||||
* </script>
|
* </script>
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
*/
|
*/
|
||||||
(function () {
|
(function () {
|
||||||
var cfg = window.YehwangChatConfig || {};
|
var cfg = window.YehwangChatConfig || {};
|
||||||
var baseURL = String(cfg.baseURL || 'http://192.168.31.61:9000').replace(/\/+$/, '');
|
var baseURL = String(cfg.baseURL || 'http://localhost:9000').replace(/\/+$/, '');
|
||||||
var inboxID = cfg.inboxID || '10fd5207-d235-4c49-beaa-a65eed0ddd0e';
|
var inboxID = cfg.inboxID || '10fd5207-d235-4c49-beaa-a65eed0ddd0e';
|
||||||
var identityURL = cfg.identityURL || 'http://192.168.31.61:4100/identity';
|
var identityURL = cfg.identityURL || 'http://localhost:4100/identity';
|
||||||
|
|
||||||
var state = { loaded: false, userJWT: null };
|
var state = { loaded: false, userJWT: null };
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -44,7 +44,7 @@
|
|||||||
<b>排查</b><br />
|
<b>排查</b><br />
|
||||||
· 气泡没出现:打开浏览器控制台看 <code>[YehwangChat]</code> / <code>Failed to initialize Libredesk Widget</code> 报错<br />
|
· 气泡没出现:打开浏览器控制台看 <code>[YehwangChat]</code> / <code>Failed to initialize Libredesk Widget</code> 报错<br />
|
||||||
· 登录身份:页面会先调 bridge <code>POST /identity</code> 拿 <code>userJWT</code>,再加载 widget<br />
|
· 登录身份:页面会先调 bridge <code>POST /identity</code> 拿 <code>userJWT</code>,再加载 widget<br />
|
||||||
· 聊天窗口打不开:检查 LibreDesk 可信域名里是否有 <code>192.168.31.61:8088</code>(CSP frame-ancestors)
|
· 聊天窗口打不开:检查 LibreDesk 可信域名里是否有 <code>localhost:8088</code>(CSP frame-ancestors)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -68,9 +68,9 @@
|
|||||||
|
|
||||||
function boot() {
|
function boot() {
|
||||||
var cfg = {
|
var cfg = {
|
||||||
baseURL: 'http://192.168.31.61:9000',
|
baseURL: 'http://localhost:9000',
|
||||||
inboxID: '10fd5207-d235-4c49-beaa-a65eed0ddd0e',
|
inboxID: '10fd5207-d235-4c49-beaa-a65eed0ddd0e',
|
||||||
identityURL: 'http://192.168.31.61:4100/identity',
|
identityURL: 'http://localhost:4100/identity',
|
||||||
};
|
};
|
||||||
if (mode === 'login') {
|
if (mode === 'login') {
|
||||||
var siteJwt = params.get('siteJwt');
|
var siteJwt = params.get('siteJwt');
|
||||||
|
|||||||
Reference in New Issue
Block a user