feat: 1. 添加axios全局路由拦截进行自动添加请求jwt。 2.重新整理路由表。 3. 文档列表新增版本差异对比。 4.菜单路由可访问列表通过对接接口返回,添加全局路由检测。

5. 修改统一认证登录和管理员登录是通过接口形式进行,存储返回的accessToken。    6. 修改交叉评查的部分样式
This commit is contained in:
2025-11-18 11:06:24 +08:00
parent 8a50671c39
commit bfe39e45a9
53 changed files with 9503 additions and 2796 deletions
+435
View File
@@ -0,0 +1,435 @@
# API接口速查表
**版本**: v1.0
**日期**: 2025-11-17
**后端地址**: `http://172.16.0.55:8073`
---
## 📌 认证接口
### 1. 统一登录接口
**端点**: `POST /auth/login`
**支持两种方式**:
#### OAuth登录
```typescript
POST /auth/login
Content-Type: application/json
{
"userInfo": {
"sub": "user123", // 必填
"username": "zhangsan", // 可选
"nickname": "张三", // 可选
"email": "...", // 可选
"phone_number": "...", // 可选
"ou_id": "dept001", // 可选
"ou_name": "技术部", // 可选
"is_leader": false // 可选
},
"expiresIn": 3600, // 必填
"area": "梅州" // 可选,仅首次创建时保存
}
```
#### 密码登录
```typescript
POST /auth/login
Content-Type: application/json
{
"username": "000", // 实际是sub字段
"password": "admin06111"
}
```
**成功响应**:
```json
{
"success": true,
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"user_info": {
"user_id": "5",
"username": "admin",
"nick_name": "管理员",
"email": null,
"phone_number": null,
"ou_id": "default",
"ou_name": "未分配部门",
"is_leader": true,
"user_role": "admin",
"sub": "000"
}
}
}
```
**失败响应**:
```json
{
"success": false,
"error": "用户名或密码错误"
}
```
---
## 📌 RBAC路由接口
### 2. 获取用户路由
**端点**: `GET /user/routes``GET /rbac/user/routes`
**请求头**:
```
Authorization: Bearer {JWT_TOKEN}
```
**响应**:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"user_id": 6,
"username": "001",
"routes": [
{
"id": 1,
"route_path": "/",
"route_name": "Layout",
"component": "layout/index",
"route_title": "入口页",
"icon": "el-icon-s-home",
"sort_order": 1,
"is_hidden": false,
"is_cache": true,
"children": [...]
}
]
}
}
```
### 3. 检查路由权限
**端点**: `GET /rbac/check-route`
**请求参数**:
```
route_path: /system/users
```
**请求头**:
```
Authorization: Bearer {JWT_TOKEN}
```
**响应**:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"route_path": "/system/users",
"has_access": true
}
}
```
### 4. 清除路由缓存
**端点**: `POST /rbac/clear-routes-cache`
**请求头**:
```
Authorization: Bearer {JWT_TOKEN}
```
**响应**:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"message": "路由缓存已清除"
}
}
```
---
## 📌 PostgREST数据接口
### 通用规则
**所有数据表访问格式**:
```
GET /{table_name} # 查询
POST /{table_name} # 创建
PATCH /{table_name}?{filter} # 更新
DELETE /{table_name}?{filter} # 删除
```
**请求头**:
```
Authorization: Bearer {JWT_TOKEN}
Content-Type: application/json
```
### PostgREST过滤操作符
| 操作符 | 说明 | 示例 |
|-------|------|------|
| `eq` | 等于 | `id=eq.5` |
| `neq` | 不等于 | `status=neq.1` |
| `gt` | 大于 | `id=gt.10` |
| `gte` | 大于等于 | `id=gte.10` |
| `lt` | 小于 | `id=lt.100` |
| `lte` | 小于等于 | `id=lte.100` |
| `like` | 模糊匹配 | `title=like.*合同*` |
| `ilike` | 不区分大小写模糊匹配 | `title=ilike.*word*` |
| `in` | 在列表中 | `id=in.(1,2,3)` |
| `is` | 是NULL | `deleted_at=is.null` |
| `not.is` | 不是NULL | `deleted_at=not.is.null` |
### 查询参数
| 参数 | 说明 | 示例 |
|-----|------|------|
| `select` | 选择字段 | `select=id,title,created_at` |
| `order` | 排序 | `order=created_at.desc` |
| `limit` | 限制数量 | `limit=20` |
| `offset` | 偏移量 | `offset=40` |
---
## 📌 常用数据表
### documents(文档表)
**查询文档列表**:
```typescript
GET /documents?user_id=eq.5&status=eq.0&select=id,title,created_at&order=created_at.desc&limit=20&offset=0
```
**创建文档**:
```typescript
POST /documents
Content-Type: application/json
{
"title": "测试文档",
"user_id": 5,
"status": 0
}
```
**更新文档**:
```typescript
PATCH /documents?id=eq.123
Content-Type: application/json
{
"title": "新标题",
"status": 1
}
```
**删除文档**:
```typescript
DELETE /documents?id=eq.123
```
### sso_users(用户表)
**查询用户**:
```typescript
GET /sso_users?sub=eq.000&select=id,username,nick_name,email
```
**注意**: 普通用户无法直接访问 `sso_users` 表,需要通过特殊接口。
### roles(角色表)
**查询所有角色**:
```typescript
GET /roles?is_system_role=eq.true&select=id,role_key,role_name,priority&order=priority.desc
```
### user_role(用户-角色关联表)
**查询用户角色**:
```typescript
GET /user_role?user_id=eq.5&select=role_id
```
### sys_routes(路由表)
**查询所有路由**:
```typescript
GET /sys_routes?status=eq.0&deleted_at=is.null&select=id,route_path,route_title&order=sort_order
```
### role_route(角色-路由关联表)
**查询角色路由**:
```typescript
GET /role_route?role_id=eq.1&select=route_id
```
---
## 📌 完整示例
### 登录 + 获取路由 + 查询数据
```typescript
import axios from 'axios';
const API_BASE = 'http://172.16.0.55:8073';
// 1. 登录
const login = async () => {
const response = await axios.post(`${API_BASE}/auth/login`, {
username: '001',
password: 'gdyc06111'
});
const { access_token, user_info } = response.data.data;
localStorage.setItem('token', access_token);
return { token: access_token, userInfo: user_info };
};
// 2. 获取路由
const fetchRoutes = async (token: string) => {
const response = await axios.get(`${API_BASE}/user/routes`, {
headers: { 'Authorization': `Bearer ${token}` }
});
return response.data.data.routes;
};
// 3. 查询文档(普通用户)
const fetchDocuments = async (token: string, userId: string) => {
const response = await axios.get(`${API_BASE}/documents`, {
params: {
user_id: `eq.${userId}`, // 只查自己的数据
status: `eq.0`,
select: 'id,title,created_at',
order: 'created_at.desc',
limit: 20,
offset: 0
},
headers: { 'Authorization': `Bearer ${token}` }
});
return response.data;
};
// 4. 创建文档
const createDocument = async (token: string, userId: string) => {
const response = await axios.post(`${API_BASE}/documents`, {
title: '测试文档',
user_id: parseInt(userId),
status: 0
}, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
return response.data;
};
// 使用示例
const main = async () => {
// 登录
const { token, userInfo } = await login();
console.log('登录成功:', userInfo);
// 获取路由
const routes = await fetchRoutes(token);
console.log('用户路由:', routes);
// 查询文档
const docs = await fetchDocuments(token, userInfo.user_id);
console.log('文档列表:', docs);
// 创建文档
const newDoc = await createDocument(token, userInfo.user_id);
console.log('新建文档:', newDoc);
};
main();
```
---
## 📌 错误码对照表
| HTTP状态码 | 说明 | 处理方式 |
|-----------|------|---------|
| 200 | 成功 | 正常处理 |
| 400 | 请求参数错误 | 检查请求参数 |
| 401 | 未授权/Token过期 | 重新登录 |
| 403 | 无权限访问 | 提示用户无权限 |
| 404 | 资源不存在 | 检查路径是否正确 |
| 500 | 服务器错误 | 联系后端开发人员 |
---
## 📌 测试账号
| 用户名 | 密码 | 角色 | 路由数 | 说明 |
|--------|------|------|-------|------|
| 000 | admin06111 | 超级管理员 | 29 | 所有权限 |
| 001 | gdyc06111 | 普通用户 | 19 | 有限权限 |
| jy001 | jyyc0814 | 系统管理员 | 29 | 管理员权限 |
| mz001 | mzyc06111 | 系统管理员 | 29 | 管理员权限 |
| yf001 | yfyc06111 | 系统管理员 | 29 | 管理员权限 |
| cz001 | czyc06111 | 系统管理员 | 29 | 管理员权限 |
---
## 📌 快速链接
- **完整对接文档**: `docs/RBAC/前端完整对接文档_RBAC与PostgREST.md`
- **快速开始**: `docs/RBAC/前端快速开始_5分钟集成.md`
- **用户管理**: `docs/RBAC/用户管理完整指南.md`
- **RBAC总结**: `docs/RBAC/RBAC系统使用总结.md`
---
**创建时间**: 2025-11-17
**维护者**: Claude Code
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,121 @@
# API端点列表
## PostgREST代理端点
所有PostgREST代理端点都位于 `/api/v1/postgrest/{table_name}`
支持的HTTP方法:GET, POST, PATCH, DELETE
### 文档管理模块
| 表名 | 端点 | 说明 | 所需权限 |
|------|------|------|---------|
| documents | /api/v1/postgrest/documents | 文档表 | document:document:view/create/update/delete |
| document_types | /api/v1/postgrest/document_types | 文档类型(公共数据) | document:type:view/create/update/delete |
| document_metadata | /api/v1/postgrest/document_metadata | 文档元数据 | document:metadata:view/create/update/delete |
### 评查管理模块
| 表名 | 端点 | 说明 | 所需权限 |
|------|------|------|---------|
| evaluation_results | /api/v1/postgrest/evaluation_results | 评查结果 | evaluation:result:view/create/update/delete |
| evaluation_points | /api/v1/postgrest/evaluation_points | 评查点配置 | evaluation:point:view/create/update/delete |
| evaluation_point_categories | /api/v1/postgrest/evaluation_point_categories | 评查点分类 | evaluation:category:view/create/update/delete |
| evaluation_rules | /api/v1/postgrest/evaluation_rules | 评查规则 | evaluation:rule:view/create/update/delete |
### 交叉评查模块
| 表名 | 端点 | 说明 | 所需权限 |
|------|------|------|---------|
| cross_examination_tasks | /api/v1/postgrest/cross_examination_tasks | 交叉评查任务 | crossreview:task:view/create/update/delete |
| cross_task_document_mapping | /api/v1/postgrest/cross_task_document_mapping | 任务-文档映射 | crossreview:mapping:view/create/update/delete |
| cross_scoring_proposals | /api/v1/postgrest/cross_scoring_proposals | 评分提案 | crossreview:proposal:view/create/update/delete |
| cross_proposal_votes | /api/v1/postgrest/cross_proposal_votes | 提案投票 | crossreview:vote:view/create/update/delete |
### 用户管理模块
| 表名 | 端点 | 说明 | 所需权限 |
|------|------|------|---------|
| sso_users | /api/v1/postgrest/sso_users | 用户表 | system:user:view/create/update/delete |
| user_role | /api/v1/postgrest/user_role | 用户-角色关联 | system:user_role:view/create/update/delete |
### 系统管理模块
| 表名 | 端点 | 说明 | 所需权限 |
|------|------|------|---------|
| roles | /api/v1/postgrest/roles | 角色表 | system:role:view/create/update/delete |
| sys_routes | /api/v1/postgrest/sys_routes | 系统路由(菜单) | system:route:view/create/update/delete |
| role_route | /api/v1/postgrest/role_route | 角色-路由关联 | system:role_route:view/create/update/delete |
### RBAC权限管理模块
| 表名 | 端点 | 说明 | 所需权限 |
|------|------|------|---------|
| permissions | /api/v1/postgrest/permissions | 权限定义 | system:permission:view/create/update/delete |
| role_permissions | /api/v1/postgrest/role_permissions | 角色-权限关联 | system:role_permission:view/create/update/delete |
| user_permissions | /api/v1/postgrest/user_permissions | 用户-权限关联 | system:user_permission:view/create/update/delete |
| data_permission_rules | /api/v1/postgrest/data_permission_rules | 数据权限规则 | system:data_rule:view/create/update/delete |
| permission_audit_logs | /api/v1/postgrest/permission_audit_logs | 权限审计日志 | system:audit_log:view/create/update/delete |
| jwt_tokens | /api/v1/postgrest/jwt_tokens | JWT Token管理 | system:jwt_token:view/create/update/delete |
### 报表统计模块
| 表名 | 端点 | 说明 | 所需权限 |
|------|------|------|---------|
| statistics_summary | /api/v1/postgrest/statistics_summary | 统计汇总 | report:summary:view/create/update/delete |
## FastAPI业务端点
### 认证端点
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| /api/v1/auth/login | POST | 用户登录 | 否 |
| /api/v1/auth/logout | POST | 用户登出 | 是 |
| /api/v1/auth/refresh | POST | 刷新Token | 是 |
### 文档业务端点(示例)
| 端点 | 方法 | 说明 | 认证 |
|------|------|------|------|
| /api/v1/documents/{id}/ocr | POST | 文档OCR处理 | 是 |
| /api/v1/documents/{id}/merge | POST | 合并PDF文档 | 是 |
| /api/v1/documents/{id}/extract | POST | AI提取信息 | 是 |
## 请求示例
### GET请求示例
```bash
GET /api/v1/postgrest/documents?status=eq.active&limit=10&order=created_at.desc
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
### POST请求示例
```bash
POST /api/v1/postgrest/documents
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"title": "新文档",
"content": "文档内容",
"status": "draft"
}
```
### PATCH请求示例
```bash
PATCH /api/v1/postgrest/documents?id=eq.1936
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"status": "reviewed"
}
```
### DELETE请求示例
```bash
DELETE /api/v1/postgrest/documents?id=eq.1936
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
@@ -0,0 +1,316 @@
# PostgREST查询参考
## 过滤运算符完整列表
### 比较运算符
| 运算符 | 说明 | PostgREST语法 | JavaScript示例 |
|--------|------|---------------|----------------|
| eq | 等于 | `field=eq.value` | `{ field: 'eq.value' }` |
| neq | 不等于 | `field=neq.value` | `{ field: 'neq.value' }` |
| gt | 大于 | `field=gt.value` | `{ field: 'gt.100' }` |
| gte | 大于等于 | `field=gte.value` | `{ field: 'gte.100' }` |
| lt | 小于 | `field=lt.value` | `{ field: 'lt.100' }` |
| lte | 小于等于 | `field=lte.value` | `{ field: 'lte.100' }` |
### 模式匹配运算符
| 运算符 | 说明 | PostgREST语法 | JavaScript示例 |
|--------|------|---------------|----------------|
| like | 模糊匹配(区分大小写) | `field=like.*pattern*` | `{ field: 'like.*测试*' }` |
| ilike | 模糊匹配(不区分大小写) | `field=ilike.*pattern*` | `{ field: 'ilike.*TEST*' }` |
**模式匹配通配符**:
- `*`: 匹配任意字符(等同于SQL的`%`
- `_`: 匹配单个字符
**示例**:
```javascript
// 查询标题以"合同"开头的文档
{ title: 'like.合同*' }
// 查询标题以"合同"结尾的文档
{ title: 'like.*合同' }
// 查询标题包含"合同"的文档
{ title: 'like.*合同*' }
// 不区分大小写查找
{ title: 'ilike.*contract*' }
```
### 列表运算符
| 运算符 | 说明 | PostgREST语法 | JavaScript示例 |
|--------|------|---------------|----------------|
| in | 在列表中 | `field=in.(value1,value2,...)` | `{ field: 'in.(active,pending)' }` |
| cs | 包含(数组字段) | `field=cs.{value1,value2}` | `{ tags: 'cs.{重要,紧急}' }` |
| cd | 被包含(数组字段) | `field=cd.{value1,value2}` | `{ tags: 'cd.{重要,紧急}' }` |
| ov | 重叠(数组字段) | `field=ov.{value1,value2}` | `{ tags: 'ov.{重要,紧急}' }` |
**示例**:
```javascript
// 查询状态为active或pending的文档
{ status: 'in.(active,pending)' }
// 查询ID在[1, 2, 3]中的文档
{ id: 'in.(1,2,3)' }
// 查询标签包含"重要"和"紧急"的文档(数组字段)
{ tags: 'cs.{重要,紧急}' }
```
### Null检查运算符
| 运算符 | 说明 | PostgREST语法 | JavaScript示例 |
|--------|------|---------------|----------------|
| is | 是null | `field=is.null` | `{ field: 'is.null' }` |
| nt | 不是null | `field=nt.null` (或 `is.not.null`) | `{ field: 'nt.null' }` |
**示例**:
```javascript
// 查询deleted_at为null的文档(未删除)
{ deleted_at: 'is.null' }
// 查询deleted_at不为null的文档(已删除)
{ deleted_at: 'nt.null' }
```
## 排序
### 单字段排序
```javascript
// 按创建时间升序
{ order: 'created_at.asc' }
// 按创建时间降序
{ order: 'created_at.desc' }
```
### 多字段排序
```javascript
// 先按状态升序,再按创建时间降序
{ order: 'status.asc,created_at.desc' }
```
## 分页
### Limit和Offset
```javascript
// 每页10条,第1页
{ limit: 10, offset: 0 }
// 每页10条,第2页
{ limit: 10, offset: 10 }
// 每页20条,第3页
{ limit: 20, offset: 40 }
```
### 获取总数
PostgREST会在响应头中返回`Content-Range`,包含总记录数:
```
Content-Range: 0-9/50
```
表示:返回第0-9条记录,总共50条记录。
**解析示例**:
```javascript
const response = await apiClient.get('/postgrest/documents', {
params: { limit: 10, offset: 0 }
});
const contentRange = response.headers['content-range'];
const total = parseInt(contentRange.split('/')[1]); // 50
```
## 字段选择
### 选择特定字段
```javascript
// 只返回id, title, status字段
{ select: 'id,title,status' }
```
### 嵌套查询(外键关联)
PostgREST支持嵌套查询,但DocAuditAI暂未启用此功能。
## 高级查询
### 逻辑运算符
**注意**: 前端应避免使用`or``and``not`参数,这些参数由后端自动生成(用于数据范围和交叉评查权限)。
### 复杂查询示例
```javascript
// 查询状态为active且创建时间在2025年之后的文档,按创建时间降序,每页10条
const params = {
status: 'eq.active',
created_at: 'gte.2025-01-01',
order: 'created_at.desc',
limit: 10,
offset: 0
};
const response = await apiClient.get('/postgrest/documents', { params });
```
## 完整示例
### 示例1:文档列表查询
```javascript
// 需求:查询标题包含"合同"、状态为active的文档,
// 按创建时间降序排列,每页20条,第2页
async function getDocumentList() {
const response = await apiClient.get('/postgrest/documents', {
params: {
title: 'ilike.*合同*',
status: 'eq.active',
order: 'created_at.desc',
limit: 20,
offset: 20 // 第2页
}
});
return {
data: response.data,
total: parseInt(response.headers['content-range'].split('/')[1])
};
}
```
### 示例2:高级搜索
```javascript
// 需求:搜索2025年创建的、状态为active或pending的文档
async function advancedSearch() {
const response = await apiClient.get('/postgrest/documents', {
params: {
status: 'in.(active,pending)',
created_at: 'gte.2025-01-01',
created_at: 'lt.2026-01-01', // 注意:PostgREST会组合多个同名参数
order: 'created_at.desc'
}
});
return response.data;
}
```
### 示例3:分页封装
```javascript
// 通用分页函数
async function fetchPaginated(table, page, pageSize, filters = {}) {
const params = {
limit: pageSize,
offset: (page - 1) * pageSize,
...filters
};
const response = await apiClient.get(`/postgrest/${table}`, { params });
const contentRange = response.headers['content-range'];
const total = contentRange ? parseInt(contentRange.split('/')[1]) : 0;
return {
data: response.data,
total: total,
page: page,
pageSize: pageSize,
totalPages: Math.ceil(total / pageSize)
};
}
// 使用示例
const result = await fetchPaginated('documents', 1, 10, {
status: 'eq.active',
order: 'created_at.desc'
});
console.log(`${result.total}条记录,第${result.page}/${result.totalPages}`);
```
## 性能优化建议
### 1. 始终使用分页
```javascript
// ✅ 好的做法
{ limit: 10, offset: 0 }
// ❌ 不好的做法(返回所有数据)
{}
```
### 2. 只查询需要的字段
```javascript
// ✅ 好的做法(只查询id和title)
{ select: 'id,title' }
// ❌ 不好的做法(查询所有字段)
{}
```
### 3. 使用索引字段进行过滤
优先使用已建立索引的字段(如id, user_id, ou_id, status)进行过滤,提升查询性能。
### 4. 避免过度模糊查询
```javascript
// ✅ 好的做法(明确的过滤条件)
{ title: 'like.合同*' }
// ❌ 不好的做法(前后通配符,性能差)
{ title: 'like.*合同*' }
```
## 常见错误
### 错误1:运算符拼写错误
```javascript
// ❌ 错误
{ status: 'equal.active' } // 应该是 eq
// ✅ 正确
{ status: 'eq.active' }
```
### 错误2:日期格式错误
```javascript
// ❌ 错误
{ created_at: 'gte.2025/01/01' } // 格式错误
// ✅ 正确
{ created_at: 'gte.2025-01-01' } // ISO 8601格式
```
### 错误3in运算符语法错误
```javascript
// ❌ 错误
{ status: 'in.active,pending' } // 缺少括号
// ✅ 正确
{ status: 'in.(active,pending)' }
```
## 参考资料
- [PostgREST官方文档](https://postgrest.org/en/stable/)
- [PostgREST API查询语法](https://postgrest.org/en/stable/api.html#horizontal-filtering-rows)
+338
View File
@@ -0,0 +1,338 @@
# 权限列表
本文档列出DocAuditAI系统中所有权限及其对应的操作。
## 权限键格式
权限键格式:`{module}:{resource}:{action}`
- **module**: 模块名称(如document, system, evaluation
- **resource**: 资源名称(如document, user, role
- **action**: 操作类型(view, create, update, delete等)
## 文档管理模块 (document)
| 权限键 | 说明 | 对应操作 |
|--------|------|---------|
| document:document:view | 查看文档 | GET /postgrest/documents |
| document:document:create | 创建文档 | POST /postgrest/documents |
| document:document:update | 更新文档 | PATCH /postgrest/documents |
| document:document:delete | 删除文档 | DELETE /postgrest/documents |
| document:type:view | 查看文档类型 | GET /postgrest/document_types |
| document:type:create | 创建文档类型 | POST /postgrest/document_types |
| document:type:update | 更新文档类型 | PATCH /postgrest/document_types |
| document:type:delete | 删除文档类型 | DELETE /postgrest/document_types |
| document:metadata:view | 查看文档元数据 | GET /postgrest/document_metadata |
| document:metadata:create | 创建文档元数据 | POST /postgrest/document_metadata |
| document:metadata:update | 更新文档元数据 | PATCH /postgrest/document_metadata |
| document:metadata:delete | 删除文档元数据 | DELETE /postgrest/document_metadata |
## 评查管理模块 (evaluation)
| 权限键 | 说明 | 对应操作 |
|--------|------|---------|
| evaluation:result:view | 查看评查结果 | GET /postgrest/evaluation_results |
| evaluation:result:create | 创建评查结果 | POST /postgrest/evaluation_results |
| evaluation:result:update | 更新评查结果 | PATCH /postgrest/evaluation_results |
| evaluation:result:delete | 删除评查结果 | DELETE /postgrest/evaluation_results |
| evaluation:point:view | 查看评查点 | GET /postgrest/evaluation_points |
| evaluation:point:create | 创建评查点 | POST /postgrest/evaluation_points |
| evaluation:point:update | 更新评查点 | PATCH /postgrest/evaluation_points |
| evaluation:point:delete | 删除评查点 | DELETE /postgrest/evaluation_points |
| evaluation:category:view | 查看评查点分类 | GET /postgrest/evaluation_point_categories |
| evaluation:category:create | 创建评查点分类 | POST /postgrest/evaluation_point_categories |
| evaluation:category:update | 更新评查点分类 | PATCH /postgrest/evaluation_point_categories |
| evaluation:category:delete | 删除评查点分类 | DELETE /postgrest/evaluation_point_categories |
| evaluation:rule:view | 查看评查规则 | GET /postgrest/evaluation_rules |
| evaluation:rule:create | 创建评查规则 | POST /postgrest/evaluation_rules |
| evaluation:rule:update | 更新评查规则 | PATCH /postgrest/evaluation_rules |
| evaluation:rule:delete | 删除评查规则 | DELETE /postgrest/evaluation_rules |
## 交叉评查模块 (crossreview)
| 权限键 | 说明 | 对应操作 |
|--------|------|---------|
| crossreview:task:view | 查看交叉评查任务 | GET /postgrest/cross_examination_tasks |
| crossreview:task:create | 创建交叉评查任务 | POST /postgrest/cross_examination_tasks |
| crossreview:task:update | 更新交叉评查任务 | PATCH /postgrest/cross_examination_tasks |
| crossreview:task:delete | 删除交叉评查任务 | DELETE /postgrest/cross_examination_tasks |
| crossreview:mapping:view | 查看任务文档映射 | GET /postgrest/cross_task_document_mapping |
| crossreview:mapping:create | 创建任务文档映射 | POST /postgrest/cross_task_document_mapping |
| crossreview:mapping:update | 更新任务文档映射 | PATCH /postgrest/cross_task_document_mapping |
| crossreview:mapping:delete | 删除任务文档映射 | DELETE /postgrest/cross_task_document_mapping |
| crossreview:proposal:view | 查看评分提案 | GET /postgrest/cross_scoring_proposals |
| crossreview:proposal:create | 创建评分提案 | POST /postgrest/cross_scoring_proposals |
| crossreview:proposal:update | 更新评分提案 | PATCH /postgrest/cross_scoring_proposals |
| crossreview:proposal:delete | 删除评分提案 | DELETE /postgrest/cross_scoring_proposals |
| crossreview:vote:view | 查看提案投票 | GET /postgrest/cross_proposal_votes |
| crossreview:vote:create | 创建提案投票 | POST /postgrest/cross_proposal_votes |
| crossreview:vote:update | 更新提案投票 | PATCH /postgrest/cross_proposal_votes |
| crossreview:vote:delete | 删除提案投票 | DELETE /postgrest/cross_proposal_votes |
## 系统管理模块 (system)
| 权限键 | 说明 | 对应操作 |
|--------|------|---------|
| system:user:view | 查看用户 | GET /postgrest/sso_users |
| system:user:create | 创建用户 | POST /postgrest/sso_users |
| system:user:update | 更新用户 | PATCH /postgrest/sso_users |
| system:user:delete | 删除用户 | DELETE /postgrest/sso_users |
| system:role:view | 查看角色 | GET /postgrest/roles |
| system:role:create | 创建角色 | POST /postgrest/roles |
| system:role:update | 更新角色 | PATCH /postgrest/roles |
| system:role:delete | 删除角色 | DELETE /postgrest/roles |
| system:route:view | 查看系统路由 | GET /postgrest/sys_routes |
| system:route:create | 创建系统路由 | POST /postgrest/sys_routes |
| system:route:update | 更新系统路由 | PATCH /postgrest/sys_routes |
| system:route:delete | 删除系统路由 | DELETE /postgrest/sys_routes |
| system:user_role:view | 查看用户-角色关联 | GET /postgrest/user_role |
| system:user_role:create | 创建用户-角色关联 | POST /postgrest/user_role |
| system:user_role:update | 更新用户-角色关联 | PATCH /postgrest/user_role |
| system:user_role:delete | 删除用户-角色关联 | DELETE /postgrest/user_role |
| system:role_route:view | 查看角色-路由关联 | GET /postgrest/role_route |
| system:role_route:create | 创建角色-路由关联 | POST /postgrest/role_route |
| system:role_route:update | 更新角色-路由关联 | PATCH /postgrest/role_route |
| system:role_route:delete | 删除角色-路由关联 | DELETE /postgrest/role_route |
| system:permission:view | 查看权限定义 | GET /postgrest/permissions |
| system:permission:create | 创建权限定义 | POST /postgrest/permissions |
| system:permission:update | 更新权限定义 | PATCH /postgrest/permissions |
| system:permission:delete | 删除权限定义 | DELETE /postgrest/permissions |
| system:role_permission:view | 查看角色-权限关联 | GET /postgrest/role_permissions |
| system:role_permission:create | 创建角色-权限关联 | POST /postgrest/role_permissions |
| system:role_permission:update | 更新角色-权限关联 | PATCH /postgrest/role_permissions |
| system:role_permission:delete | 删除角色-权限关联 | DELETE /postgrest/role_permissions |
| system:user_permission:view | 查看用户-权限关联 | GET /postgrest/user_permissions |
| system:user_permission:create | 创建用户-权限关联 | POST /postgrest/user_permissions |
| system:user_permission:update | 更新用户-权限关联 | PATCH /postgrest/user_permissions |
| system:user_permission:delete | 删除用户-权限关联 | DELETE /postgrest/user_permissions |
| system:data_rule:view | 查看数据权限规则 | GET /postgrest/data_permission_rules |
| system:data_rule:create | 创建数据权限规则 | POST /postgrest/data_permission_rules |
| system:data_rule:update | 更新数据权限规则 | PATCH /postgrest/data_permission_rules |
| system:data_rule:delete | 删除数据权限规则 | DELETE /postgrest/data_permission_rules |
| system:audit_log:view | 查看审计日志 | GET /postgrest/permission_audit_logs |
| system:audit_log:create | 创建审计日志 | POST /postgrest/permission_audit_logs |
| system:audit_log:update | 更新审计日志 | PATCH /postgrest/permission_audit_logs |
| system:audit_log:delete | 删除审计日志 | DELETE /postgrest/permission_audit_logs |
| system:jwt_token:view | 查看JWT Token | GET /postgrest/jwt_tokens |
| system:jwt_token:create | 创建JWT Token | POST /postgrest/jwt_tokens |
| system:jwt_token:update | 更新JWT Token | PATCH /postgrest/jwt_tokens |
| system:jwt_token:delete | 删除JWT Token | DELETE /postgrest/jwt_tokens |
## 报表统计模块 (report)
| 权限键 | 说明 | 对应操作 |
|--------|------|---------|
| report:summary:view | 查看统计汇总 | GET /postgrest/statistics_summary |
| report:summary:create | 创建统计汇总 | POST /postgrest/statistics_summary |
| report:summary:update | 更新统计汇总 | PATCH /postgrest/statistics_summary |
| report:summary:delete | 删除统计汇总 | DELETE /postgrest/statistics_summary |
## 预定义角色及其权限
### 1. 系统管理员
拥有所有权限(71个权限)
### 2. 文档管理员
- document:document:view
- document:document:create
- document:document:update
- document:document:delete
- document:type:view
- document:type:create
- document:type:update
- document:type:delete
- document:metadata:view
- document:metadata:create
- document:metadata:update
- document:metadata:delete
### 3. 文档审查员
- document:document:view
- document:document:update
- evaluation:result:view
- evaluation:result:create
- evaluation:result:update
- evaluation:point:view
### 4. 交叉评查管理员
- crossreview:task:view
- crossreview:task:create
- crossreview:task:update
- crossreview:task:delete
- crossreview:mapping:view
- crossreview:mapping:create
- crossreview:mapping:update
- crossreview:mapping:delete
- crossreview:proposal:view
- crossreview:proposal:create
- crossreview:proposal:update
- crossreview:vote:view
- crossreview:vote:create
- crossreview:vote:update
### 5. 交叉评查参与者
- crossreview:task:view
- crossreview:mapping:view
- crossreview:proposal:view
- crossreview:proposal:create
- crossreview:vote:view
- crossreview:vote:create
### 6. 评价点管理员
- evaluation:point:view
- evaluation:point:create
- evaluation:point:update
- evaluation:point:delete
- evaluation:category:view
- evaluation:category:create
- evaluation:category:update
- evaluation:category:delete
- evaluation:rule:view
- evaluation:rule:create
- evaluation:rule:update
- evaluation:rule:delete
### 7. 报表查看员
- report:summary:view
- document:document:view
- evaluation:result:view
### 8. 普通用户
- document:document:view
- document:type:view
- evaluation:point:view
- evaluation:category:view
### 9. 审计员
- system:audit_log:view
- document:document:view
- evaluation:result:view
- crossreview:task:view
## 前端权限控制示例
### 示例1:按钮权限控制
```vue
<template>
<!-- 只有拥有document:document:delete权限的用户才能看到删除按钮 -->
<button v-permission="'document:document:delete'" @click="deleteDoc">
删除文档
</button>
<!-- 只有系统管理员才能看到 -->
<button v-role="'系统管理员'" @click="showAdminPanel">
管理面板
</button>
</template>
```
### 示例2:菜单权限控制
```javascript
// 菜单配置(根据权限动态生成)
const menuConfig = [
{
name: '文档管理',
permission: 'document:document:view',
children: [
{ name: '文档列表', permission: 'document:document:view', path: '/documents' },
{ name: '新建文档', permission: 'document:document:create', path: '/documents/new' }
]
},
{
name: '评查管理',
permission: 'evaluation:point:view',
children: [
{ name: '评查点配置', permission: 'evaluation:point:view', path: '/evaluation/points' },
{ name: '评查结果', permission: 'evaluation:result:view', path: '/evaluation/results' }
]
},
{
name: '系统管理',
role: '系统管理员', // 只有系统管理员才能看到
children: [
{ name: '用户管理', permission: 'system:user:view', path: '/system/users' },
{ name: '角色管理', permission: 'system:role:view', path: '/system/roles' }
]
}
];
// 过滤菜单(根据用户权限)
function filterMenuByPermission(menu, userPermissions, userRoles) {
return menu.filter(item => {
// 检查角色
if (item.role && !userRoles.includes(item.role)) {
return false;
}
// 检查权限
if (item.permission && !userPermissions.includes(item.permission)) {
return false;
}
// 递归过滤子菜单
if (item.children) {
item.children = filterMenuByPermission(item.children, userPermissions, userRoles);
}
return true;
});
}
```
### 示例3:路由守卫
```javascript
// router.js
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/documents',
component: DocumentList,
meta: { permission: 'document:document:view' }
},
{
path: '/system/users',
component: UserManagement,
meta: { role: '系统管理员' }
}
]
});
// 全局路由守卫
router.beforeEach((to, from, next) => {
const userInfo = JSON.parse(localStorage.getItem('user_info') || '{}');
// 检查角色
if (to.meta.role && !userInfo.roles?.includes(to.meta.role)) {
alert('无权访问此页面');
next('/');
return;
}
// 检查权限(简化版,实际应维护权限列表)
if (to.meta.permission) {
// TODO: 检查用户是否有该权限
}
next();
});
```
## 注意事项
1. **权限检查由后端强制执行**
即使前端绕过权限控制,后端也会拒绝无权请求。
2. **前端权限控制是为了提升用户体验**
隐藏用户无权操作的按钮和菜单,避免用户点击后被拒绝。
3. **定期同步权限列表**
登录时从后端获取用户的完整权限列表,存储到前端状态管理中。
4. **角色权限继承**
用户通过角色继承权限,也可以直接分配权限(优先级高于角色)。
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,333 @@
# 前端快速开始 - 5分钟集成RBAC系统
**版本**: v1.0
**日期**: 2025-11-17
**目标**: 最快速度集成登录、动态路由和数据访问
---
## ⚡ 5分钟集成步骤
### 步骤1: 安装依赖(1分钟)
```bash
npm install axios pinia vue-router@4 element-plus
```
### 步骤2: 配置环境变量(30秒)
创建 `.env.development`
```env
VITE_API_BASE_URL=http://172.16.0.55:8073
```
### 步骤3: 创建请求工具(1分钟)
**文件**: `src/utils/request.ts`
```typescript
import axios from 'axios';
import { ElMessage } from 'element-plus';
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || 'http://172.16.0.55:8073',
timeout: 30000
});
// 请求拦截器:自动添加Token
service.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
});
// 响应拦截器:统一错误处理
service.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
ElMessage.error('登录已过期');
localStorage.clear();
window.location.href = '/login';
}
return Promise.reject(error);
}
);
export default service;
```
### 步骤4: 创建用户Store2分钟)
**文件**: `src/stores/user.ts`
```typescript
import { defineStore } from 'pinia';
import { ref } from 'vue';
import request from '@/utils/request';
import router from '@/router';
export const useUserStore = defineStore('user', () => {
const token = ref('');
const userInfo = ref<any>(null);
const routes = ref<any[]>([]);
// 登录
const login = async (username: string, password: string) => {
const res = await request.post('/auth/login', { username, password });
if (res.data.success) {
token.value = res.data.data.access_token;
userInfo.value = res.data.data.user_info;
localStorage.setItem('token', token.value);
localStorage.setItem('userInfo', JSON.stringify(userInfo.value));
return true;
}
return false;
};
// 获取路由
const fetchRoutes = async () => {
const res = await request.get('/user/routes');
if (res.data.code === 200) {
routes.value = res.data.data.routes;
// 动态注册路由
routes.value.forEach(route => {
router.addRoute({
path: route.route_path,
name: route.route_name,
component: () => import(`@/views/${route.component}.vue`),
meta: { title: route.route_title }
});
});
return routes.value;
}
};
// 登出
const logout = () => {
token.value = '';
userInfo.value = null;
routes.value = [];
localStorage.clear();
router.push('/login');
};
return { token, userInfo, routes, login, fetchRoutes, logout };
});
```
### 步骤5: 配置路由守卫(30秒)
**文件**: `src/router/index.ts`
```typescript
import { createRouter, createWebHistory } from 'vue-router';
import { useUserStore } from '@/stores/user';
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/login', component: () => import('@/views/Login.vue') }
]
});
router.beforeEach(async (to, from, next) => {
const userStore = useUserStore();
const token = localStorage.getItem('token');
if (token && !userStore.token) {
userStore.token = token;
userStore.userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');
}
if (to.path !== '/login' && !token) {
next('/login');
} else if (token && !userStore.routes.length) {
await userStore.fetchRoutes();
next({ ...to, replace: true });
} else {
next();
}
});
export default router;
```
### 步骤6: 创建登录页(30秒)
**文件**: `src/views/Login.vue`
```vue
<template>
<el-form @submit.prevent="handleLogin">
<el-form-item>
<el-input v-model="username" placeholder="用户名" />
</el-form-item>
<el-form-item>
<el-input v-model="password" type="password" placeholder="密码" />
</el-form-item>
<el-form-item>
<el-button type="primary" native-type="submit" :loading="loading">
登录
</el-button>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { useUserStore } from '@/stores/user';
import { ElMessage } from 'element-plus';
const router = useRouter();
const userStore = useUserStore();
const username = ref('');
const password = ref('');
const loading = ref(false);
const handleLogin = async () => {
loading.value = true;
try {
const success = await userStore.login(username.value, password.value);
if (success) {
await userStore.fetchRoutes();
router.push('/home');
} else {
ElMessage.error('登录失败');
}
} catch (error) {
ElMessage.error('登录失败');
} finally {
loading.value = false;
}
};
</script>
```
---
## ✅ 完成!
现在你已经完成了基础集成,可以:
1. ✅ 用户登录
2. ✅ 动态加载路由
3. ✅ 访问受保护的页面
---
## 🚀 下一步:数据访问
### 查询数据
```typescript
import request from '@/utils/request';
// 查询文档列表
const fetchDocuments = async () => {
const res = await request.get('/documents', {
params: {
user_id: `eq.${userInfo.user_id}`, // 只查自己的数据
limit: 20,
offset: 0
}
});
return res.data;
};
```
### 创建数据
```typescript
const createDocument = async (data: any) => {
const res = await request.post('/documents', data);
return res.data;
};
```
### 更新数据
```typescript
const updateDocument = async (id: number, data: any) => {
const res = await request.patch(`/documents?id=eq.${id}`, data);
return res.data;
};
```
### 删除数据
```typescript
const deleteDocument = async (id: number) => {
const res = await request.delete(`/documents?id=eq.${id}`);
return res.data;
};
```
---
## 📚 测试账号
| 用户名 | 密码 | 角色 | 说明 |
|--------|------|------|------|
| 000 | admin06111 | 超级管理员 | 所有权限(29个路由) |
| 001 | gdyc06111 | 普通用户 | 有限权限(19个路由) |
| jy001 | jyyc0814 | 系统管理员 | 所有权限(29个路由) |
---
## 🔧 常见问题
### 1. Token过期怎么办?
后端返回401时,自动清除Token并跳转登录页。
### 2. 路由404怎么办?
检查组件路径是否正确:
```typescript
// 后端返回: component: "views/Home"
// 前端import: @/views/views/Home.vue ❌
// 修改为:
component: () => import(`@/views/Home.vue`)
```
### 3. 普通用户能看到所有数据?
前端必须手动添加 `user_id` 过滤:
```typescript
// ❌ 错误
const docs = await request.get('/documents');
// ✅ 正确
const docs = await request.get('/documents', {
params: { user_id: `eq.${userInfo.user_id}` }
});
```
---
## 📖 详细文档
完整API说明请查看:
- **完整对接文档**: `docs/RBAC/前端完整对接文档_RBAC与PostgREST.md`
---
**创建时间**: 2025-11-17
**维护者**: Claude Code
File diff suppressed because it is too large Load Diff