fix(用户管理): 修复用户列表页面加载失败问题
修复用户列表页面加载失败导致测试超时的问题,确保页面元素正确渲染
This commit is contained in:
@@ -3,41 +3,97 @@
|
||||
## 设计思想
|
||||
|
||||
开发环境在 **Windows** 宿主机直接运行所有服务:
|
||||
- PostgreSQL 16+ 和 Redis 7+ 通过 Windows 原生安装运行
|
||||
- PostgreSQL 通过 Windows 原生安装运行
|
||||
- Redis 7+ 通过 Windows 原生安装运行(可选,缺省时限流降级为 fail-open)
|
||||
- 后端 Rust 服务通过 `cargo run` 快速重启
|
||||
- 前端 Vite 热更新直接在宿主机
|
||||
- PowerShell 脚本 (`dev.ps1`) 提供一键启动/停止
|
||||
|
||||
> Docker Compose 配置保留在 `docker/` 目录下,可供需要容器化环境的场景使用,但日常开发不依赖 Docker。
|
||||
|
||||
## 代码逻辑
|
||||
## 本机环境实际配置
|
||||
|
||||
### 服务配置
|
||||
> **重要:以下为当前开发机的实际配置,以本文件为准。**
|
||||
|
||||
| 组件 | 安装路径 | 配置 |
|
||||
|------|---------|------|
|
||||
| PostgreSQL 18 | `D:\postgreSQL\` | 服务名 `postgresql-x64-18`, 端口 5432 |
|
||||
| Redis | 云端实例 | `redis://:redis_KBCYJk@129.204.154.246:6379`, 限流中间件已正常工作 |
|
||||
| Rust | stable (cargo in PATH) | workspace 根目录编译 |
|
||||
| Node.js + pnpm | in PATH | apps/web/ |
|
||||
|
||||
### 数据库连接
|
||||
|
||||
```
|
||||
用户: postgres
|
||||
密码: 123123
|
||||
数据库: erp
|
||||
连接串: postgres://postgres:123123@localhost:5432/erp
|
||||
```
|
||||
|
||||
psql 路径: `D:\postgreSQL\bin\psql.exe -U postgres -h localhost -d erp`
|
||||
|
||||
### 后端启动命令
|
||||
|
||||
后端**必须**从 `crates/erp-server/` 目录启动(需要读取 `config/default.toml`),或通过环境变量覆盖:
|
||||
|
||||
```powershell
|
||||
# 方式一:从 crates/erp-server 目录启动(使用 default.toml + 环境变量覆盖)
|
||||
cd crates/erp-server
|
||||
$env:ERP__DATABASE__URL = "postgres://postgres:123123@localhost:5432/erp"
|
||||
$env:ERP__JWT__SECRET = "dev-secret-key-change-in-prod"
|
||||
$env:ERP__AUTH__SUPER_ADMIN_PASSWORD = "Admin@2026"
|
||||
cargo run -p erp-server
|
||||
|
||||
# 方式二:一键启动脚本(推荐)
|
||||
.\dev.ps1
|
||||
```
|
||||
|
||||
### 登录凭据
|
||||
|
||||
```
|
||||
用户名: admin
|
||||
密码: Admin@2026
|
||||
```
|
||||
|
||||
## 服务端口
|
||||
|
||||
| 服务 | 端口 | 用途 |
|
||||
|------|------|------|
|
||||
| PostgreSQL 16+ | 5432 | 主数据库 |
|
||||
| Redis 7+ | 6379 | 缓存 + 会话 |
|
||||
| PostgreSQL 18 | 5432 | 主数据库 |
|
||||
| Redis 7+ | 6379 (云端) | 缓存 + 限流 |
|
||||
| erp-server (Axum) | 3000 | 后端 API |
|
||||
| Vite dev server | 5174 | 前端 SPA |
|
||||
| Vite dev server | 5174 | 前端 SPA(固定端口,--strictPort) |
|
||||
|
||||
### 连接信息
|
||||
### 连接信息(配置文件版本)
|
||||
```
|
||||
PostgreSQL: postgres://erp:erp_dev_2024@localhost:5432/erp
|
||||
Redis: redis://localhost:6379
|
||||
PostgreSQL: postgres://postgres:123123@localhost:5432/erp
|
||||
Redis: redis://:redis_KBCYJk@129.204.154.246:6379 (云端实例)
|
||||
```
|
||||
|
||||
### 一键启动
|
||||
## 一键启动
|
||||
|
||||
```powershell
|
||||
.\dev.ps1 # 启动后端 + 前端
|
||||
.\dev.ps1 # 启动后端 + 前端(自动清理旧进程 5174-5189)
|
||||
.\dev.ps1 -Status # 查看端口状态
|
||||
.\dev.ps1 -Stop # 停止所有服务
|
||||
.\dev.ps1 -Restart # 重启所有服务
|
||||
```
|
||||
|
||||
> `dev.ps1` 会在启动前清理端口 5174-5189 范围内所有残留进程,并使用 `--strictPort` 确保 Vite 固定在 5174 端口。
|
||||
|
||||
### 环境变量
|
||||
通过 `crates/erp-server/config/default.toml` 配置,无需额外环境变量文件即可启动。
|
||||
|
||||
必须通过环境变量设置的值(`default.toml` 中为占位符):
|
||||
|
||||
| 变量 | 说明 | 开发值 |
|
||||
|------|------|--------|
|
||||
| `ERP__DATABASE__URL` | 数据库连接串 | `postgres://postgres:123123@localhost:5432/erp` |
|
||||
| `ERP__JWT__SECRET` | JWT 签名密钥 | 自定义字符串 |
|
||||
| `ERP__AUTH__SUPER_ADMIN_PASSWORD` | admin 初始密码 | `Admin@2026` |
|
||||
| `ERP__REDIS__URL` | Redis 连接串 | `redis://:redis_KBCYJk@129.204.154.246:6379` |
|
||||
|
||||
> 所有四个变量在 `default.toml` 中都是 `__MUST_SET_VIA_ENV__` 占位符,**必须**通过环境变量设置,否则服务拒绝启动。
|
||||
|
||||
## 关联模块
|
||||
|
||||
@@ -50,9 +106,10 @@ Redis: redis://localhost:6379
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `dev.ps1` | 一键启动/停止脚本 |
|
||||
| `dev.ps1` | 一键启动/停止脚本(自动清理端口 5174-5189) |
|
||||
| `docker/docker-compose.yml` | 可选的 Docker Compose 配置 |
|
||||
| `crates/erp-server/config/default.toml` | 默认连接配置 |
|
||||
| `crates/erp-server/config/default.toml` | 默认配置模板(密钥为占位符) |
|
||||
| `D:\postgreSQL\bin\psql.exe` | PostgreSQL 客户端 |
|
||||
|
||||
## 常用命令
|
||||
|
||||
@@ -60,12 +117,22 @@ Redis: redis://localhost:6379
|
||||
# 一键启动(推荐)
|
||||
.\dev.ps1
|
||||
|
||||
# 手动启动后端
|
||||
# 手动启动后端(从 crates/erp-server 目录)
|
||||
cd crates/erp-server
|
||||
$env:ERP__DATABASE__URL="postgres://postgres:123123@localhost:5432/erp"
|
||||
$env:ERP__JWT__SECRET="dev-secret"
|
||||
$env:ERP__AUTH__SUPER_ADMIN_PASSWORD="Admin@2026"
|
||||
cargo run -p erp-server
|
||||
|
||||
# 手动启动前端
|
||||
cd apps/web && pnpm dev
|
||||
# 手动启动前端(固定端口)
|
||||
cd apps/web && pnpm dev -- --strictPort
|
||||
|
||||
# 连接数据库
|
||||
psql -U erp -d erp -h localhost
|
||||
D:\postgreSQL\bin\psql.exe -U postgres -h localhost -d erp
|
||||
|
||||
# 健康检查
|
||||
curl http://localhost:3000/api/v1/health
|
||||
|
||||
# 登录测试
|
||||
curl -s http://localhost:3000/api/v1/auth/login -H "Content-Type: application/json" -d '{"username":"admin","password":"Admin@2026"}'
|
||||
```
|
||||
|
||||
@@ -443,3 +443,72 @@ let limits = StoreLimitsBuilder::new()
|
||||
- **动态表**: 支持 `db_insert("dynamic_table", ...)` 自动创建/迁移表
|
||||
- **前端集成**: PluginCRUDPage 组件根据 WIT 定义自动生成 CRUD 页面
|
||||
- **插件市场**: 插件元数据、版本管理、签名验证
|
||||
|
||||
## 插件权限系统(关键)
|
||||
|
||||
### 权限码格式
|
||||
|
||||
插件数据操作的权限码由 `data_handler.rs` 中的 `compute_permission_code()` 按以下规则自动生成:
|
||||
|
||||
```
|
||||
{manifest_id}.{url_entity_name}.{action_suffix}
|
||||
```
|
||||
|
||||
- `manifest_id`:plugin.toml 中 `[metadata].id`(如 `erp-crm`)
|
||||
- `url_entity_name`:REST API 路径中的实体名(如 `customer_tag`)
|
||||
- `action_suffix`:`list`(读操作)或 `manage`(写操作)
|
||||
|
||||
| 操作 | 权限码示例 |
|
||||
|------|-----------|
|
||||
| 列表/详情 | `erp-crm.customer.list` |
|
||||
| 创建/更新/删除 | `erp-crm.customer.manage` |
|
||||
|
||||
### 权限码命名铁律(P0 级)
|
||||
|
||||
**`plugin.toml` 中 `permissions[].code` 的前缀必须与 `schema.entities[].name` 完全一致。**
|
||||
|
||||
```
|
||||
data_handler 生成:{manifest_id}.{url_entity_name}.{action}
|
||||
↑ 来自 URL 路径中的 entity 参数
|
||||
manifest 声明: {entity_name}.{action}
|
||||
↑ 必须与 URL 中的 entity name 匹配
|
||||
```
|
||||
|
||||
每个实体必须同时声明 `.list` 和 `.manage` 两个权限:
|
||||
|
||||
```toml
|
||||
# ✅ 正确:权限码前缀与实体名一致
|
||||
[[schema.entities]]
|
||||
name = "customer_tag"
|
||||
|
||||
[[permissions]]
|
||||
code = "customer_tag.list" # 匹配!
|
||||
|
||||
[[permissions]]
|
||||
code = "customer_tag.manage" # 匹配!
|
||||
|
||||
# ❌ 错误:权限码用了简写,与实体名不一致 → 403
|
||||
[[permissions]]
|
||||
code = "tag.manage" # data_handler 生成 erp-crm.customer_tag.manage
|
||||
# 但 DB 中只有 erp-crm.tag.manage → 403
|
||||
```
|
||||
|
||||
**历史教训:** CRM 插件首个版本中,`customer_tag` 实体的权限码写成了 `tag.manage`,`customer_relationship` 实体的权限码写成了 `relationship.list/manage`。结果标签管理、客户关系、关系图谱三个页面全部 403。修复迁移:`m20260419_000038_fix_crm_permission_codes.rs`。
|
||||
|
||||
### 权限注册流程
|
||||
|
||||
1. **插件安装时** → `register_plugin_permissions()` 将 manifest 中声明的权限批量 INSERT 到 `permissions` 表(`ON CONFLICT DO NOTHING` 保证幂等)
|
||||
2. **权限分配** → `grant_permissions_to_admin()` 自动将权限分配给 admin 角色
|
||||
3. **运行时校验** → `data_handler.rs` 的 `compute_permission_code()` 按 URL entity name 生成权限码,通过 `require_permission()` 检查 JWT 中的权限列表
|
||||
|
||||
### 已修复问题
|
||||
|
||||
| 问题 | 修复 |
|
||||
|------|------|
|
||||
| 权限未自动分配给 admin 角色 → 403 | `grant_permissions_to_admin()` 在 install/enable 时自动调用 |
|
||||
| 权限码与实体名不匹配 → 403 | 迁移 m20260419_000038 + plugin.toml 修正 |
|
||||
### 插件 API 路由注意事项
|
||||
|
||||
- 后端路由使用 `Path<(Uuid, String)>` 解析 `plugin_id`,必须是 UUID 格式
|
||||
- 前端使用 `plugin.id`(数据库 UUID)而非 `manifest_id`(如 `erp-crm`)构建请求 URL
|
||||
- 直接用 manifest_id 调用 API 会返回 `UUID parsing failed` 错误
|
||||
|
||||
Reference in New Issue
Block a user