d04e837d9c
- 新增V3.0数据库表结构(12-15)和数据填充脚本(16)
- 新增后端路由: store-grade, enterprise, product, intelligence, alert, scheduler, target
- 新增前端页面: StoreGradePage, EnterprisePage, ProductLifecyclePage, IntelligencePage, AlertManagementPage, DataImportPage, SchedulerManagementPage, TargetManagementPage
- 门店分级: 自动分级算法(达成率40%+毛利率25%+会员15%+风险20%)
- 风险等级: 基于mv_store_risk_rating模型展示风险分布和原因
- 弹窗: 雷达图+详细指标+分级原因+风险原因(primary_issue)
- FilterableTable: filterOptions支持{value,label}对象格式
183 lines
7.8 KiB
Markdown
183 lines
7.8 KiB
Markdown
当前数据库是本机Homebrew PostgreSQL 15,数据库名为 bill_query,端口5432,仅监听 localhost;当前用户 freedak 是超级用户,本机认证方式为 trust。这适合本机开发,但不适合直接照搬到服务器生产环境。前端浏览器也不应直接连接PostgreSQL,必须通过后端API访问。
|
||
|
||
## 登录账号
|
||
|
||
### 平台管理员
|
||
|
||
| 用户名 | 密码 | 角色 | 说明 |
|
||
|--------|------|------|------|
|
||
| 平台管理员 | 123 | platform_admin | 管理所有租户,登录后进入平台管理后台 |
|
||
|
||
### 租户用户(存储在服务器 sbrain_admin 数据库)
|
||
|
||
| 用户名 | 密码 | 角色 | 租户 |
|
||
|--------|------|------|------|
|
||
| 总部管理员 | 123 | hq | tenant_a(西部马华) |
|
||
|
||
> 租户管理员(hq)登录后可在系统内创建区域经理、店长、商品部等角色用户。
|
||
> 密码使用 bcrypt 加密存储。
|
||
|
||
## 架构(2026-08-02 更新:SaaS 多租户)
|
||
|
||
```
|
||
浏览器 → https://dm.all8ai.top
|
||
→ Nginx(服务器) → /api/ → 127.0.0.1:9333 (服务器后端, pm2管理)
|
||
→ 服务器本地 PostgreSQL:5432 → sbrain_admin(平台库:租户配置、用户认证)
|
||
→ frp隧道 127.0.0.1:15432 → 本机PostgreSQL:5432 → bill_query(租户业务库)
|
||
```
|
||
|
||
### 数据库连接(重要)
|
||
|
||
后端连接两个不同的数据库,走不同端口:
|
||
|
||
| 连接池 | 目标数据库 | 连接地址 | 认证方式 | 配置来源 |
|
||
|--------|-----------|---------|---------|---------|
|
||
| `adminPool` | `sbrain_admin`(平台库) | `127.0.0.1:5432`(服务器本地 PG) | scram-sha-256(用户 `sbrain_admin`,密码 `sbrain2026`) | `.env` 中 `ADMIN_DB_*` |
|
||
| `tenantPool` | `bill_query`(业务库) | `127.0.0.1:15432`(FRP 隧道 → 本机 PG) | trust(用户 `freedak`,无需密码) | `tenant_configs.db_port=15432` |
|
||
| `pool` | `bill_query`(业务库) | `127.0.0.1:15432`(FRP 隧道 → 本机 PG) | trust(用户 `freedak`,无需密码) | `.env` 中 `DB_*` |
|
||
|
||
> ⚠️ `tenant_configs` 表中 `db_port` 必须为 `15432`(FRP 隧道),`db_password` 为 NULL(trust 认证)。
|
||
> ⚠️ `adminPool` 连接服务器本地 5432,需要 `ADMIN_DB_PASSWORD=sbrain2026`。
|
||
|
||
### 数据库分布
|
||
|
||
| 数据库 | 位置 | 存储内容 |
|
||
|--------|------|---------|
|
||
| `sbrain_admin` | 服务器本地 PostgreSQL(5432) | 平台管理员、租户配置(tenant_configs)、所有租户用户(tenant_users) |
|
||
| `bill_query` | 本机 PostgreSQL(通过 frp 暴露为 15432) | 租户业务数据(销售、任务、成本分析等) |
|
||
|
||
### 多租户数据隔离
|
||
|
||
- **认证流程**:用户登录 → 查 `sbrain_admin.tenant_users` → bcrypt 验证 → JWT 含 `tenantId`
|
||
- **数据隔离**:业务请求 → `tenantDbMiddleware` 根据 JWT 中的 `tenantId` 查 `tenant_configs` 获取该租户数据库连接信息 → `AsyncLocalStorage` 设置租户连接池 → 所有 `query()` 自动走对应租户数据库
|
||
- **租户用户管理**:平台管理员为租户创建管理员(hq),租户管理员在系统内创建区域经理/店长/商品部等用户,均存储在 `sbrain_admin.tenant_users` 表中,通过 `tenant_id` 字段区分
|
||
|
||
### 关键文件
|
||
|
||
| 文件 | 职责 |
|
||
|------|------|
|
||
| `server/src/config/tenant-db.ts` | 租户连接池缓存 + AsyncLocalStorage |
|
||
| `server/src/config/admin-pool.ts` | 平台库连接池(通过 `ADMIN_DB_*` 环境变量配置) |
|
||
| `server/src/config/database.ts` | 主业务库连接池 + 全局 `query()` 函数(自动注入数据权限) |
|
||
| `server/src/middleware/tenant-db.ts` | 根据 JWT tenantId 动态切换数据库 + 注入用户 scope |
|
||
| `server/src/middleware/data-scope.ts` | 数据权限工具函数(`getDataScope` / `scopeStoreFilter`) |
|
||
| `server/src/routes/auth.ts` | 租户用户登录(查 tenant_users + bcrypt) |
|
||
| `server/src/routes/admin.ts` | 平台管理 API + 租户内用户管理 API |
|
||
| `server/sql/11_tenant_management.sql` | 平台数据库建表 SQL |
|
||
|
||
## 部署流程
|
||
|
||
### 一键部署(前端+后端)
|
||
|
||
```bash
|
||
bash deploy.sh # 全量部署(后端+前端)
|
||
bash deploy.sh server # 只部署后端
|
||
bash deploy.sh front # 只部署前端
|
||
```
|
||
|
||
- 后端:rsync 同步到服务器 `/opt/sbrain-server` + npm install + pm2 重启
|
||
- 前端:构建 + scp 上传到服务器 `/var/www/dm.all8ai.top`
|
||
|
||
### 本机 frp 隧道(launchd 系统级服务)
|
||
|
||
frpc 配置(`/Users/freedak/frp/frpc.toml`):
|
||
|
||
```toml
|
||
serverAddr = "152.136.182.184"
|
||
serverPort = 7000
|
||
loginFailExit = false
|
||
auth.token = "frp_gitea_2026"
|
||
|
||
[[proxies]]
|
||
name = "dm-db"
|
||
type = "tcp"
|
||
localIP = "127.0.0.1"
|
||
localPort = 5432
|
||
remotePort = 15432
|
||
```
|
||
|
||
已配置为 macOS launchd 系统级服务,开机自动启动,崩溃自动重启,与 IDE 无关。
|
||
|
||
| 服务 | plist | 日志 |
|
||
|------|-------|------|
|
||
| frp 隧道 (5432→15432) | `~/Library/LaunchAgents/com.frp.client.plist` | `~/Library/Logs/frpc.log` |
|
||
|
||
#### 管理命令
|
||
|
||
```bash
|
||
# 停止 frpc
|
||
launchctl bootout gui/$(id -u)/com.frp.client
|
||
|
||
# 启动 frpc
|
||
launchctl load ~/Library/LaunchAgents/com.frp.client.plist
|
||
|
||
# 查看日志
|
||
tail -f ~/Library/Logs/frpc.log
|
||
|
||
# 检查状态
|
||
pgrep -l frpc
|
||
curl -s https://dm.all8ai.top/api/health
|
||
```
|
||
|
||
#### 手动启动 frpc(备用,launchd 未运行时)
|
||
|
||
```bash
|
||
cd /Users/freedak/frp && ./frpc -c frpc.toml &
|
||
```
|
||
|
||
## 本地开发
|
||
|
||
### 后端开发
|
||
|
||
```bash
|
||
cd server && npm run dev
|
||
```
|
||
|
||
后端运行在 `http://localhost:3333`,连接本地 PostgreSQL(`localhost:5432`,数据库 `bill_query`)。
|
||
|
||
### 前端开发
|
||
|
||
```bash
|
||
cd client && npm run dev
|
||
```
|
||
|
||
访问 `http://localhost:5173`(Vite proxy 自动转发 `/api` 到 `localhost:3333`)。
|
||
|
||
## 服务器后端管理
|
||
|
||
```bash
|
||
# 查看后端状态
|
||
ssh ubuntu@152.136.182.184 'pm2 status sbrain-server'
|
||
|
||
# 查看后端日志
|
||
ssh ubuntu@152.136.182.184 'pm2 logs sbrain-server --lines 50'
|
||
|
||
# 重启后端
|
||
ssh ubuntu@152.136.182.184 'pm2 restart sbrain-server'
|
||
|
||
# 查看后端 .env
|
||
ssh ubuntu@152.136.182.184 'cat /opt/sbrain-server/.env'
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
- **平台库 `sbrain_admin` 在服务器本地 PostgreSQL(5432)**,业务库 `bill_query` 在本机 PostgreSQL(通过 frp 暴露为 15432)
|
||
- `adminPool` 连服务器本地 5432 的 `sbrain_admin`(SCRAM 认证,用户 `sbrain_admin`,密码 `sbrain2026`)
|
||
- `tenantPool` / `pool` 连 FRP 隧道 15432 的 `bill_query`(trust 认证,用户 `freedak`,无需密码)
|
||
- `tenant_configs` 表中 `db_port` 必须为 `15432`,`db_password` 为 NULL(trust 认证)
|
||
- `pg` 库在 `password` 为空字符串时会触发 SCRAM 认证失败,因此 `admin-pool.ts`、`database.ts`、`tenant-db.ts` 中空密码时不传 `password` 参数
|
||
- `deploy.sh` 每次部署会覆盖服务器 `.env`,其中包含 `ADMIN_DB_*` 配置(`ADMIN_DB_PORT=5432`,`ADMIN_DB_PASSWORD=sbrain2026`),修改 `.env` 配置必须同步修改 `deploy.sh`
|
||
- 租户用户统一存储在 `sbrain_admin.tenant_users` 表,通过 `tenant_id` 区分租户
|
||
- `tenant_users.region` 字段为 `VARCHAR(500)`,区域经理的 `region` 存储逗号分隔的 `store_code` 列表(如 `0010,0011,0014`)
|
||
- 密码使用 bcrypt 加密,平台管理员密码目前仍为明文(后续可改)
|
||
- 本机只需运行 frpc(launchd 自启),后端已部署到服务器
|
||
- 修改后端代码后执行 `bash deploy.sh server` 部署到服务器
|
||
- 修改前端代码后执行 `bash deploy.sh front` 部署到服务器
|
||
- 全量部署执行 `bash deploy.sh`(后端+前端)
|
||
- `server/.env`(本机开发用)中 `DB_PORT=5432` 连接本地数据库,不要改为 5433
|
||
- 服务器 `/opt/sbrain-server/.env` 中 `DB_PORT=15432` 连接 frp 隧道端口
|
||
- frpc 断开后线上前端 API 会失效,需重新启动 frpc
|
||
- launchd 服务开机自启,关闭 IDE/终端不影响;仅注销/关机时停止,下次登录/开机自动恢复
|
||
|
||
0.1/0.2分支为 SBrainCO,备份在/Volumes/Projects/2026/SBrainCO-20260805.zip
|
||
0.3分支为 SBrainCO3 |