Files
kefu_cloud/README.md
T
yml2213 f88030acf5 chore(seed): 种子数据最小化,移除全部虚构演示/测试数据
- seed 仅初始化平台管理员与三个套餐,不再预置假租户/坐席/客户/知识库/公告
- 租户改由平台后台正常开通(自动创建管理员账号与默认网页渠道)
- README 与 deploy 文档、脚本中的演示账号说明同步更新
2026-09-05 15:58:00 +08:00

304 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 客服云(kefu_cloud)
多租户在线客服 SaaS:租户坐席工作台 + 访客 Widget + 平台超管后台。
消息模型为 **HTTP 落库 + WebSocket 实时推送**;图片经对象存储(MinIO / S3 兼容)上传后以 URL 入消息。
---
## 功能总览
### 租户侧(坐席 / 主管 / 租户管理员)
| 模块 | 能力 |
|------|------|
| **工作台** | 会话列表、领取/转接/结束、文字与图片、输入中提示、内部备注、知识库快捷引用 |
| **实时通信** | 客服/访客 WebSocket(ws/wss);推送可直接上屏;断线重连后按 `seq` 增量同步 |
| **访客 Widget** | 嵌入脚本、欢迎语、离线留言、结束评价(星级+快捷评语)、重新咨询 |
| **客户管理** | 客户档案、标签、历史会话、CSV 导出 |
| **对话记录** | 筛选、归档、详情回放、CSV 导出 |
| **知识库** | 分类树 CRUD、条目管理 |
| **数据统计** | KPI、趋势、响应分布、渠道分布、坐席绩效、CSV 报告导出 |
| **系统设置** | 基本信息、渠道与嵌入代码、坐席账号/配额、**自动分配策略**、欢迎语/工作时间/通知 |
### 平台侧(`platform_admin`)
| 模块 | 能力 |
|------|------|
| **运营概览** | 租户量、套餐分布、增长等 |
| **租户管理** | 开通/暂停/恢复、联系人与套餐 |
| **套餐定价** | 套餐 CRUD |
| **系统运维** | **真实 metrics**(CPU/内存/磁盘、24h 请求量与错误率、DB/WS/对象存储探测)、操作日志、平台公告 |
### 分配与会话
- **自动分配**(可配置):`least_load`(负载最低)/ `round_robin`(轮询)
- **最大并发**:每位坐席 `active` 会话上限(0 = 不限)
- **人工**:领取、转接(事件记录操作人与目标)、结束与评价
---
## 技术架构
```
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ React + Vite │────▶│ Gin API :8080 │────▶│ PostgreSQL │
│ Antd/Tailwind │ WS │ JWT 多租户 │ │ (开发 :5433) │
│ :5173 │◀────│ Hub 内存广播 │ └─────────────────┘
└─────────────────┘ │ metrics 中间件 │
└────────┬─────────┘
│
▼
┌─────────────────┐
│ MinIO / S3 │
│ (开发 :9100) │
└─────────────────┘
```
| 层 | 选型 |
|----|------|
| 前端 | React 19、Vite 8、Ant Design 6、Tailwind 4、React Router |
| 后端 | Go、Gin、GORM、JWT、Gorilla WebSocket |
| 数据库 | PostgreSQL(生产/开发主库);测试可用 SQLite |
| 存储 | MinIO(S3 兼容),图片转 WebP |
| 实时 | 进程内 WebSocket Hub;多 API 副本时通过 `REDIS_ADDR` 启用 Redis Pub/Sub 跨节点广播 |
### 消息链路(简要)
```
发送方 ──POST 消息/上传──▶ API 落库(seq 单调)
│
├── WebSocket type=message 推送(可带消息体)
└── 对端追加或 after_seq 增量拉取
```
- 客服:`/api/ws`(子协议鉴权)
- 访客:`/api/widget/ws?session_id=…`(访客 token)
- 图片:先 `/uploads` 或 `/widget/upload`,再 `type=image` + URL
---
## 目录结构
```
kefu_cloud/ # 仓库目录名(本地可能仍为旧名,以模块名为准)
├── docker-compose.dev.yml # Postgres + MinIO
├── Makefile
├── docs/ # 产品原型 / 需求 HTML
├── server/ # Go module: kefu-cloud/server
│ ├── cmd/main.go # 服务入口
│ ├── cmd/seed/ # 最小种子(平台账号 + 套餐)
│ └── internal/
│ ├── config/ # 环境变量配置
│ ├── handler/ # HTTP / Widget / 导出 / 分配
│ ├── metrics/ # 请求统计与运维指标
│ ├── middleware/ # JWT / 平台权限
│ ├── model/ # GORM 模型与消息序号
│ ├── storage/ # 对象存储抽象
│ └── ws/ # WebSocket Hub
└── web/
├── public/widget.js # 嵌入脚本入口
└── src/
├── pages/agent/ # 租户工作台等
├── pages/admin/ # 平台后台
├── widgets/ # 访客聊天组件
└── services/ # API 与 CSV 下载
```
---
## 生产部署(腾讯云 Docker)
单机一键部署(应用内 Nginx + API + PostgreSQL + MinIO)。默认宿主机端口 **18080**,便于与已有 **Caddy(80/443)** 共存:
```bash
# 服务器安装 Docker 后
chmod +x deploy/scripts/*.sh
./deploy/scripts/deploy.sh # 首次会生成 deploy/.env.prod,请改域名与密钥
./deploy/scripts/deploy.sh --seed # 可选:初始化平台账号与套餐
```
说明见 **[deploy/README.md](deploy/README.md)**(Caddy 共存、安全组、HTTPS、COS、备份升级)。Caddy 站点示例:`deploy/caddy/Caddyfile.example`。
---
## 本地开发
### 环境要求
- Go 1.26+(与仓库 `go.mod` 和生产构建镜像一致)
- Node.js 20+
- Docker(数据库与 MinIO)
### 1. 基础设施
```bash
make db-up
# 或:docker compose -f docker-compose.dev.yml up -d
```
| 服务 | 地址 |
|------|------|
| PostgreSQL | `localhost:5433`(用户/库/密码见下表) |
| MinIO API | `http://localhost:9100` |
| MinIO 控制台 | `http://localhost:9101`(minioadmin / minioadmin) |
### 2. 后端
```bash
cd server
go mod download
go run ./cmd/main.go
# 默认 :8080
```
首次启动会 AutoMigrate。可选种子数据:
```bash
cd server && go run ./cmd/seed
```
### 3. 前端
```bash
cd web
npm install
npm run dev
# 默认 http://localhost:5173 ,/api 与 WS 代理到 :8080
```
### 4. 一键(Makefile)
```bash
make install # 前后端依赖
make db-up
# 再分别启动后端与前端,或使用 make dev(按需调整)
```
### 默认账号(seed 后)
seed 仅初始化平台管理员与默认套餐,不预置任何虚构的租户/坐席/客户数据:
| 角色 | 用户名 | 密码 |
|------|--------|------|
| 平台管理员 | `platform_admin` | `kefu_admin123` |
租户请在平台后台「租户管理」开通(会自动创建租户管理员账号与默认网页渠道),坐席由租户管理员在「成员账号」中创建。**生产环境部署后请立即修改默认密码。**
### 常用入口
| 地址 | 说明 |
|------|------|
| http://localhost:5173/login | 登录 |
| http://localhost:5173/agent/dashboard | 客服工作台 |
| http://localhost:5173/admin | 平台后台 |
| http://localhost:5173/widget/preview | 访客 Widget 预览 |
| 渠道嵌入 | 设置 → 渠道管理 → 复制 script(`data-id` 为 channel_key) |
---
## 主要环境变量
后端通过环境变量加载(可 `server/.env` 配合 shell `set -a`):
| 变量 | 默认 | 说明 |
|------|------|------|
| `SERVER_PORT` | `8080` | HTTP 端口 |
| `GIN_MODE` | `debug` | Gin 模式 |
| `DB_HOST` / `DB_PORT` | `localhost` / `5433` | 数据库 |
| `DB_USER` / `DB_PASSWORD` / `DB_NAME` | `postgres` / `postgres` / `kefu_cloud` | |
| `JWT_SECRET` | 内置开发密钥 | **生产务必修改** |
| `STORAGE_ENDPOINT` | `localhost:9100` | MinIO/S3 |
| `STORAGE_ACCESS_KEY` / `STORAGE_SECRET_KEY` | `minioadmin` | |
| `STORAGE_BUCKET` | `kefu` | |
| `STORAGE_PUBLIC_BASE_URL` | `http://localhost:9100/kefu` | 浏览器访问前缀 |
| `REDIS_ADDR` | 空 | 为空=单实例进程内广播;设置后 WS 广播走 Redis Pub/Sub 跨节点扇出 |
| `REDIS_PASSWORD` / `REDIS_DB` | 空 / `0` | 与 `REDIS_ADDR` 配合使用 |
---
## 角色与权限(概要)
| 角色 | 范围 |
|------|------|
| `platform_admin` | 平台租户/套餐/运维(`TenantID=0`) |
| `admin` | 租户管理员:设置、坐席、全量会话等 |
| `supervisor` | 主管:统计、客户、会话监管 |
| `agent` | 一线:本人会话 + 排队领取;客户可见范围为相关会话客户 |
Widget 访客使用 `visitor_token`,与会话绑定,不走 JWT 坐席体系。
---
## API 分组(摘录)
| 前缀 | 说明 |
|------|------|
| `POST /api/login` | 登录 |
| `/api/widget/*` | 访客 init/消息/留言/评价/上传/WS |
| `/api/ws` | 坐席 WebSocket |
| `/api/sessions/*` | 会话、消息、`after_seq` 增量、导出 |
| `/api/customers/*` | 客户 CRUD、导出 |
| `/api/statistics/*` | 统计与导出 |
| `/api/settings` | 租户设置(含分配策略) |
| `/api/staff` | 坐席账号 |
| `/api/admin/*` | 平台管理 + `ops/metrics` |
| `GET /health` | 健康检查 |
完整路由见 `server/internal/handler/router.go`。
---
## 测试
```bash
cd server && go test ./...
cd web && npx tsc --noEmit
```
集成测试覆盖鉴权隔离、自动分配、转接、Widget 等(`handler` 包内)。
---
## 产品现状与后续方向
### 已具备(适合演示 / 中小单实例)
- 完整接待闭环:进线 → 分配 → 聊天 → 转接/结束 → 评价 → 重新咨询
- 租户隔离、坐席配额、知识库、统计与 CSV 导出
- 运维页进程级真实负载与请求错误率
- 分配策略可配置(负载最低 / 轮询 + 并发上限)
### 已知边界(有意未做或单实例限制)
| 项 | 说明 |
|----|------|
| 多 API 实例 | 设置 `REDIS_ADDR` 后 Hub 广播经 Redis Pub/Sub 跨节点扇出(各节点本地投递、连接仍节点本地,需入口层 sticky/共享连接);单实例无需 Redis |
| 独立消息队列 | 当前不需要;实时靠 WS Hub(+ 可选 Redis 广播) |
| 技能组 / 渠道专属坐席 | 未做;可在候选过滤层扩展 |
| 厂商推送(APNs/FCM) | 未做 |
| 微信/APP/电话渠道 | 模型预留,完整对接未做 |
### 建议演进顺序
1. 生产配置加固(JWT、HTTPS、存储与 DB 备份)
2. 需要水平扩展时:`REDIS_ADDR` 启用跨节点广播 + sticky 或共享连接层(已内置)
3. 技能组 / 渠道路由
4. 监控可对接 Prometheus(现有 metrics 可作过渡)
---
## 设计稿与需求
`docs/` 下保留各页面 HTML 原型与需求说明:
- `docs/spec/` 开发需求
- `docs/agent/` 租户端页面
- `docs/admin/` 平台端页面
---
## 许可证
内部项目 / 按团队约定使用。未单独声明开源协议时,默认保留所有权利。