diff --git a/docs/PostgREST使用情况-后端API替代建议.md b/docs/PostgREST使用情况-后端API替代建议.md new file mode 100644 index 0000000..d4ee2ae --- /dev/null +++ b/docs/PostgREST使用情况-后端API替代建议.md @@ -0,0 +1,1478 @@ +# PostgREST 使用情况及后端 API 替代建议 + +> **本文档详细列出所有正在使用的 PostgREST 请求** +> **排除"评查点详情"相关的必须保留功能** +> **标注建议改为后端 API 的模块** +> +> **更新时间**: 2025-11-25 + +--- + +## 📋 图例说明 + +| 标记 | 含义 | +|------|------| +| 🔄 | **强烈建议**改为后端 API | +| ⚠️ | **建议评估**是否改为后端 API | +| ✅ | **保留** PostgREST(技术原因或低优先级) | +| 🔒 | **必须保留** PostgREST(评查点详情相关) | + +--- + +## 目录 + +1. [认证服务](#1-认证服务) +2. [首页与统计](#2-首页与统计) +3. [文档管理](#3-文档管理) +4. [文件上传](#4-文件上传) +5. [评查点管理](#5-评查点管理) +6. [评查点分组](#6-评查点分组) +7. [评查文件审核](#7-评查文件审核) +8. [评审结果](#8-评审结果) +9. [文档类型](#9-文档类型) +10. [入口模块](#10-入口模块) +11. [交叉评查](#11-交叉评查) +12. [提示词模板](#12-提示词模板) +13. [合同模板](#13-合同模板) +14. [汇总统计](#汇总统计) + +--- + +## 1. 认证服务 + +**文件**: `app/api/login/auth.server.ts` + +### 1.1 用户信息同步 - `saveUserInfo()` + +| 项目 | 内容 | +|------|------| +| **函数** | `saveUserInfo()` | +| **行号** | 551-681 | +| **PostgREST 操作** | `postgrestGet` + `postgrestPut` / `postgrestPost` | +| **表名** | `sso_users` | +| **功能** | OAuth 登录后将用户信息同步到本地数据库 | +| **调用位置** | `app/routes/callback.tsx` - OAuth 回调 | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现:前端直接操作数据库 +1. postgrestGet 查询用户是否存在(根据 sub) +2. 如果存在 → postgrestPut 更新用户信息 +3. 如果不存在 → postgrestPost 插入新用户 +``` + +**建议后端 API**: +``` +POST /api/auth/sync-user +Body: { userInfo, userRole, area } +Response: { success, user_id, ... } +``` + +**优点**: +- ✅ 统一用户数据管理逻辑 +- ✅ 避免前端直接操作用户表 +- ✅ 更好的数据一致性保障 + +--- + +### 1.2 添加默认角色 - `addDefaultRole()` + +| 项目 | 内容 | +|------|------| +| **函数** | `addDefaultRole()` | +| **行号** | 691-738 | +| **PostgREST 操作** | `postgrestGet` + `postgrestPost` | +| **表名** | `user_role` | +| **功能** | 为新用户自动添加默认角色(common) | +| **调用位置** | `saveUserInfo()` 内部调用 | +| **建议** | 🔄 **改为后端 API**(随 `saveUserInfo` 一起) | + +**详细说明**: +```typescript +// 当前实现 +1. postgrestGet 检查用户是否已有角色 +2. 如果没有 → postgrestPost 添加角色 +``` + +**建议**: 合并到 `/api/auth/sync-user` 接口中,后端自动处理 + +--- + +## 2. 首页与统计 + +**文件**: `app/api/home/home.ts` + +### 2.1 获取入口模块 - `getEntryModules()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getEntryModules()` | +| **行号** | 232-371 | +| **PostgREST 操作** | `postgrestGet` × 2 | +| **表名** | `entry_modules` + `document_types` | +| **功能** | 获取用户可访问的入口模块及关联的文档类型 | +| **调用位置** | `app/routes/home.tsx` - 首页 | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +1. postgrestGet 查询 entry_modules(根据用户角色和地区过滤) +2. 对每个模块:postgrestGet 查询关联的 document_types +3. 前端进行地区启用状态过滤 +``` + +**建议后端 API**: +``` +GET /api/home/entry-modules?userRole={role}&userArea={area} +Response: { + modules: [ + { + id, name, description, path, areas, + documentTypes: [...] // 已关联的文档类型 + } + ] +} +``` + +**优点**: +- ✅ 减少多次数据库查询 +- ✅ 后端统一处理权限逻辑 +- ✅ 支持更复杂的业务规则 + +--- + +## 3. 文档管理 + +**文件**: `app/api/files/documents.ts` + +### 3.1 获取单个文档 - `getDocument()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getDocument()` | +| **行号** | 286-331 | +| **PostgREST 操作** | `postgrestGet` + 内部调用多个查询 | +| **表名** | `documents` + `evaluation_results` + `document_types` | +| **功能** | 获取单个文档详情及评查结果统计 | +| **调用位置** | `home.tsx`, `documents.list.tsx`, `documents.edit.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +1. postgrestGet 查询文档基本信息(documents 表) +2. 调用 getDocumentTypes() → postgrestGet 查询文档类型 +3. 调用 getEvaluationResults() → postgrestGet 查询评查结果 +4. 前端计算问题数量(issues) +5. 前端组装 DocumentUI 对象 +``` + +**建议后端 API**: +``` +GET /api/documents/{id}?userId={userId} +Response: { + id, name, documentNumber, type, typeName, + auditStatus, fileStatus, issues, // 后端计算 + uploadTime, pageCount, ... +} +``` + +**优点**: +- ✅ 一次请求获取所有数据 +- ✅ 后端计算问题数量,提高性能 +- ✅ 减少前端数据组装逻辑 + +--- + +### 3.2 获取文档(无用户限制) - `getDocumentWithNoUserId()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getDocumentWithNoUserId()` | +| **行号** | 339-383 | +| **PostgREST 操作** | `postgrestGet` + 内部调用多个查询 | +| **表名** | `documents` + `evaluation_results` + `document_types` | +| **功能** | 获取文档详情(跨用户查询,用于交叉评查) | +| **调用位置** | 交叉评查模块 | +| **建议** | 🔄 **改为后端 API** | + +**建议后端 API**: +``` +GET /api/documents/{id}/detail +Response: { ... } // 与 getDocument 类似,但无用户ID限制 +``` + +--- + +### 3.3 更新文档 - `updateDocument()` + +| 项目 | 内容 | +|------|------| +| **函数** | `updateDocument()` | +| **行号** | 393-458 | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `documents` | +| **功能** | 更新文档信息(文档编号、审核状态、备注等) | +| **调用位置** | `documents.edit.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +postgrestPut('documents', { + document_number, audit_status, is_test_document, remark +}, { id, user_id }) +``` + +**建议后端 API**: +``` +PUT /api/documents/{id} +Body: { documentNumber, auditStatus, isTest, remark } +Response: { success, updatedDocument } +``` + +**优点**: +- ✅ 后端可以添加业务逻辑(如状态变更日志) +- ✅ 统一权限校验 +- ✅ 支持事务处理 + +--- + +### 3.4 删除文档 - `deleteDocument()` + +| 项目 | 内容 | +|------|------| +| **函数** | `deleteDocument()` | +| **行号** | 242-279 | +| **PostgREST 操作** | `postgrestDelete` | +| **表名** | `documents` | +| **功能** | 删除文档(只能删除自己的文档) | +| **调用位置** | 文档列表操作 | +| **建议** | 🔄 **改为后端 API** | + +**建议后端 API**: +``` +DELETE /api/documents/{id}?userId={userId} +Response: { success } +``` + +**优点**: +- ✅ 后端可以执行级联删除(评查结果、文件存储等) +- ✅ 记录删除日志 +- ✅ 更安全的权限控制 + +--- + +## 4. 文件上传 + +**文件**: `app/api/files/files-upload.ts` + +### 4.1 获取当天文档列表 - `getTodayDocuments()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getTodayDocuments()` | +| **行号** | 440-524 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `documents` | +| **功能** | 获取当天上传的文档列表(支持按文档类型过滤) | +| **调用位置** | `documents.list.tsx`, `files.upload.tsx`, `ReviewTabs.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +postgrestGet('documents', { + select: 'id, name, type_id, file_size, status, ...', + filter: { + 'created_at': `gte.${today}`, + 'user_id': `eq.${userInfo.user_id}`, + 'type_id': `in.(${typeIds})` // 从 sessionStorage 读取 + }, + order: 'created_at.desc' +}) +``` + +**建议后端 API**: +``` +GET /api/documents/today?userId={userId}&typeIds={ids} +Response: { + documents: [...] +} +``` + +**优点**: +- ✅ 后端可以优化查询性能 +- ✅ 支持更复杂的筛选条件 +- ✅ 统一日期范围逻辑 + +--- + +### 4.2 获取文档类型列表 - `getDocumentTypes()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getDocumentTypes()` | +| **行号** | 531-574 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `document_types` | +| **功能** | 获取文档类型列表(支持动态过滤) | +| **调用位置** | `documents.list.tsx`, `files.upload.tsx` | +| **建议** | ⚠️ **建议评估** | + +**详细说明**: +```typescript +// 当前实现 +postgrestGet('document_types', { + select: 'id, name', + filter: { 'id': `in.(${typeIds})` } // 从 sessionStorage 读取 +}) +``` + +**建议**: +- 如果只是简单查询,可以保留 PostgREST +- 如果需要关联更多数据(如提示词配置),改为后端 API + +--- + +### 4.3 获取文档状态 - `getDocumentsStatus()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getDocumentsStatus()` | +| **行号** | 583-658 | +| **PostgREST 操作** | `postgrestGet` × 2 | +| **表名** | `documents` + `contract_structure_comparison` | +| **功能** | 批量查询文档和合同附件的处理状态(用于轮询) | +| **调用位置** | `documents.list.tsx`, `files.upload.tsx`, `ReviewTabs.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +1. postgrestGet('documents', { filter: { id: 'in.(1,2,3)' } }) +2. postgrestGet('contract_structure_comparison', { filter: { id: 'in.(4,5)' } }) +3. 前端合并结果 +``` + +**建议后端 API**: +``` +POST /api/documents/status +Body: { documentIds: [1,2,3], attachmentIds: [4,5] } +Response: { + documents: [{ id, status }, ...] +} +``` + +**优点**: +- ✅ 一次请求获取所有状态 +- ✅ 减少前端逻辑 +- ✅ 支持 WebSocket 推送(未来优化) + +--- + +## 5. 评查点管理 + +**文件**: `app/api/evaluation_points/rules.ts` + +### 5.1 获取评查点列表 - `getRulesList()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getRulesList()` | +| **行号** | 182-408 | +| **PostgREST 操作** | `postgrestGet` × 2 | +| **表名** | `evaluation_points` + `evaluation_point_groups` | +| **功能** | 获取评查点列表(支持分页、排序、多条件筛选) | +| **调用位置** | `rules.list.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +1. postgrestGet('evaluation_point_groups', ...) // 查询类型筛选 +2. postgrestGet('evaluation_points', { + select: `id, code, name, + child_group:evaluation_point_groups!fk_evaluation_points_group(...), + parent_group:evaluation_point_groups!fk_evaluation_points_parent_group(...)` + }) // 使用资源嵌入查询父子分组 +3. 前端进行地区过滤、编码清洗 +``` + +**建议后端 API**: +``` +GET /api/rules/list?page={p}&pageSize={ps}&type={t}&group={g}&status={s}&keyword={k}&area={a} +Response: { + rules: [...], + total: 100, + page: 1, + pageSize: 10 +} +``` + +**优点**: +- ✅ 简化复杂的资源嵌入查询 +- ✅ 后端处理地区过滤和编码清洗 +- ✅ 更好的查询性能优化 + +--- + +### 5.2 获取单个评查点 - `getRule()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getRule()` | +| **行号** | 409-502 | +| **PostgREST 操作** | `postgrestGet` × 2 | +| **表名** | `evaluation_points` + `evaluation_point_groups` | +| **功能** | 获取单个评查点详情 | +| **调用位置** | 评查点编辑页面 | +| **建议** | 🔒 **必须保留**(评查点详情) | + +**说明**: 这是评查点详情相关功能,必须使用 PostgREST + +--- + +### 5.3 创建评查点 - `createRule()` + +| 项目 | 内容 | +|------|------| +| **函数** | `createRule()` | +| **行号** | 503-563 | +| **PostgREST 操作** | `postgrestPost` | +| **表名** | `evaluation_points` | +| **功能** | 创建新的评查点 | +| **调用位置** | 评查点编辑页面 | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 5.4 更新评查点 - `updateRule()` + +| 项目 | 内容 | +|------|------| +| **函数** | `updateRule()` | +| **行号** | 564-624 | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `evaluation_points` | +| **功能** | 更新评查点 | +| **调用位置** | 评查点编辑页面 | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 5.5 删除评查点 - `deleteRule()` + +| 项目 | 内容 | +|------|------| +| **函数** | `deleteRule()` | +| **行号** | 625-739 | +| **PostgREST 操作** | `postgrestDelete` | +| **表名** | `evaluation_points` | +| **功能** | 删除评查点 | +| **调用位置** | 评查点列表 | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 5.6 获取规则类型 - `getRuleTypes()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getRuleTypes()` | +| **行号** | 803-945 | +| **PostgREST 操作** | `postgrestGet` × 2 | +| **表名** | `document_types` + `evaluation_point_groups` | +| **功能** | 获取文档类型和评查点类型(用于筛选) | +| **调用位置** | `rules.list.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 5.7 根据类型获取规则组 - `getRuleGroupsByType()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getRuleGroupsByType()` | +| **行号** | 946-1078 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `evaluation_point_groups` | +| **功能** | 根据文档类型ID获取规则组 | +| **调用位置** | `rules.list.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 5.8 获取评查点数据(编辑用) - `getEvaluationPoint()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getEvaluationPoint()` | +| **行号** | 1152-1202 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `evaluation_points` | +| **功能** | 获取评查点数据(用于编辑页面) | +| **调用位置** | `rules.new.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 5.9 获取评查点组列表 - `getEvaluationPointGroups()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getEvaluationPointGroups()` | +| **行号** | 1203-1327 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `evaluation_point_groups` | +| **功能** | 获取所有评查点组(用于下拉选择) | +| **调用位置** | `rules.new.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 5.10 保存评查点 - `saveEvaluationPoint()` + +| 项目 | 内容 | +|------|------| +| **函数** | `saveEvaluationPoint()` | +| **行号** | 1328+ | +| **PostgREST 操作** | `postgrestPut` / `postgrestPost` | +| **表名** | `evaluation_points` | +| **功能** | 保存评查点(新建或更新) | +| **调用位置** | `rules.new.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +## 6. 评查点分组 + +**文件**: `app/api/evaluation_points/rule-groups.ts` + +### 6.1 获取顶级分组 - `getRuleGroups()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getRuleGroups()` | +| **行号** | 74-145 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `evaluation_point_groups` | +| **功能** | 获取顶级评查点分组列表 | +| **调用位置** | `rule-groups._index.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 6.2 获取子分组 - `getChildGroups()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getChildGroups()` | +| **行号** | 146-245 | +| **PostgREST 操作** | `postgrestGet` × 2 | +| **表名** | `evaluation_point_groups` + `evaluation_points` | +| **功能** | 获取子分组列表及评查点数量 | +| **调用位置** | `rule-groups._index.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 6.3 获取所有分组(树形) - `getAllRuleGroups()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getAllRuleGroups()` | +| **行号** | 246-330 | +| **PostgREST 操作** | `postgrestGet` × 多次 | +| **表名** | `evaluation_point_groups` + `evaluation_points` | +| **功能** | 获取所有分组并构建树形结构 | +| **调用位置** | `document-types.new.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 6.4 获取单个分组 - `getRuleGroup()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getRuleGroup()` | +| **行号** | 331-429 | +| **PostgREST 操作** | `postgrestGet` × 2 | +| **表名** | `evaluation_point_groups` + `evaluation_points` | +| **功能** | 获取单个分组详情及评查点数量 | +| **调用位置** | `rule-groups.new.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 6.5 创建分组 - `createRuleGroup()` + +| 项目 | 内容 | +|------|------| +| **函数** | `createRuleGroup()` | +| **行号** | 430-513 | +| **PostgREST 操作** | `postgrestPost` | +| **表名** | `evaluation_point_groups` | +| **功能** | 创建新的评查点分组 | +| **调用位置** | `rule-groups.new.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 6.6 更新分组 - `updateRuleGroup()` + +| 项目 | 内容 | +|------|------| +| **函数** | `updateRuleGroup()` | +| **行号** | 514-576 | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `evaluation_point_groups` | +| **功能** | 更新评查点分组 | +| **调用位置** | `rule-groups.new.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 6.7 删除分组 - `deleteRuleGroup()` + +| 项目 | 内容 | +|------|------| +| **函数** | `deleteRuleGroup()` | +| **行号** | 577+ | +| **PostgREST 操作** | `postgrestDelete` × 2 | +| **表名** | `evaluation_point_groups` + `evaluation_points` | +| **功能** | 删除分组(级联删除子分组和评查点) | +| **调用位置** | `rule-groups._index.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +## 7. 评查文件审核 + +**文件**: `app/api/evaluation_points/rules-files.ts` + +### 7.1 更新文档审核状态 - `updateDocumentAuditStatus()` + +| 项目 | 内容 | +|------|------| +| **函数** | `updateDocumentAuditStatus()` | +| **行号** | 118-167 | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `documents` | +| **功能** | 更新文件的审核状态(通过/不通过/警告) | +| **调用位置** | `documents.list.tsx`, `files.upload.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +postgrestPut('documents', + { audit_status: auditStatus }, + { id, user_id } +) +``` + +**建议后端 API**: +``` +PUT /api/documents/{id}/audit-status +Body: { auditStatus, userId } +Response: { success } +``` + +**优点**: +- ✅ 后端可以记录审核日志 +- ✅ 触发审核状态变更的业务逻辑 +- ✅ 统一权限校验 + +--- + +## 8. 评审结果 + +**文件**: `app/api/evaluation_points/reviews.ts` + +### 8.1 获取评查点列表 - `getReviewPoints()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getReviewPoints()` | +| **行号** | 132-750 | +| **PostgREST 操作** | `postgrestGet` × 6 | +| **表名** | `contract_structure_comparison`, `evaluation_results`, `evaluation_points`, `evaluation_point_groups`, `audit_status`, `cross_scoring_proposals` | +| **功能** | 获取文档的完整评查结果(关联 6 个表) | +| **调用位置** | `reviews.tsx`, `cross-checking.result.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现:复杂的多表关联查询 +1. postgrestGet('contract_structure_comparison', ...) // 合同附件 +2. postgrestGet('evaluation_results', ...) // 评查结果 +3. postgrestGet('evaluation_points', ...) // 评查点 +4. postgrestGet('evaluation_point_groups', ...) // 评查点组 +5. postgrestGet('audit_status', ...) // 审核状态 +6. postgrestGet('cross_scoring_proposals', ...) // 交叉提案 +7. 前端复杂的数据组装和分组 +``` + +**建议后端 API**: +``` +GET /api/documents/{id}/review-points +Response: { + reviewPoints: [ + { + id, evaluationPointId, evaluationPointName, + groupName, result, score, + auditStatus, crossProposals, ... + } + ], + groupedByCategory: {...} +} +``` + +**优点**: +- ✅ 大幅减少数据库查询(从 6 次到 1 次) +- ✅ 后端优化 JOIN 查询性能 +- ✅ 简化前端数据处理逻辑 +- ✅ 统一数据格式 + +--- + +### 8.2 更新评查结果 - `updateReviewResult()` + +| 项目 | 内容 | +|------|------| +| **函数** | `updateReviewResult()` | +| **行号** | 751-894 | +| **PostgREST 操作** | `postgrestGet` + `postgrestPut` / `postgrestPost` | +| **表名** | `evaluation_results` + `audit_status` | +| **功能** | 更新评查结果和审核状态 | +| **调用位置** | `reviews.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +1. postgrestGet('evaluation_results', ...) // 获取当前结果 +2. postgrestPut('evaluation_results', ...) // 更新结果 +3. 根据情况: + - postgrestPut('audit_status', ...) // 更新审核状态 + - 或 postgrestPost('audit_status', ...) // 创建审核状态 +``` + +**建议后端 API**: +``` +PUT /api/review-results/{id} +Body: { + evaluationResultId, + evaluatedResult, + evaluationOpinion, + userOpinion, + isReEvaluation +} +Response: { success, updatedResult } +``` + +**优点**: +- ✅ 事务处理,保证数据一致性 +- ✅ 后端处理复杂的状态逻辑 +- ✅ 记录修改历史 + +--- + +### 8.3 确认评查结果 - `confirmReviewResults()` + +| 项目 | 内容 | +|------|------| +| **函数** | `confirmReviewResults()` | +| **行号** | 895+ | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `documents` | +| **功能** | 确认评查并更新文档状态 | +| **调用位置** | `reviews.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**建议后端 API**: +``` +POST /api/documents/{id}/confirm-review +Response: { success } +``` + +**优点**: +- ✅ 后端可以执行确认后的业务逻辑 +- ✅ 触发通知或工作流 + +--- + +## 9. 文档类型 + +**文件**: `app/api/document-types/document-types.ts` + +### 9.1 获取所有评查点分组 - `getAllEvaluationPointGroups()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getAllEvaluationPointGroups()` | +| **行号** | 101-148 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `evaluation_point_groups` | +| **功能** | 获取所有评查点分组(用于文档类型关联) | +| **调用位置** | `document-types.new.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 9.2 获取父级分组 - `getParentEvaluationPointGroups()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getParentEvaluationPointGroups()` | +| **行号** | 149-200 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `evaluation_point_groups` | +| **功能** | 获取父级评查点分组 | +| **调用位置** | `document-types._index.tsx` | +| **建议** | 🔒 **必须保留**(评查点详情) | + +--- + +### 9.3 获取入口模块 - `getEntryModules()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getEntryModules()` | +| **行号** | 201-244 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `entry_modules` | +| **功能** | 获取入口模块列表(用于文档类型关联) | +| **调用位置** | `document-types.new.tsx` | +| **建议** | ⚠️ **建议评估** | + +**说明**: 如果只是简单查询,可以保留;如果需要复杂业务逻辑,改为后端 API + +--- + +### 9.4 获取文档类型列表 - `getDocumentTypes()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getDocumentTypes()` | +| **行号** | 311-465 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `document_types` | +| **功能** | 获取文档类型列表(支持分页、筛选) | +| **调用位置** | `documents.list.tsx`, `document-types.new.tsx`, `document-types._index.tsx`, `documents.edit.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现 +postgrestGet('document_types', { + select: `id, name, description, ..., + entry_modules!fk_document_types_entry_module(id,name)`, // 资源嵌入 + filter: { ... }, + order: '...', + limit: pageSize, + offset: offset +}) +``` + +**建议后端 API**: +``` +GET /api/document-types?page={p}&pageSize={ps}&name={n}&groupId={g} +Response: { + types: [...], + total: 100 +} +``` + +**优点**: +- ✅ 简化资源嵌入查询 +- ✅ 后端优化查询性能 +- ✅ 支持更复杂的业务逻辑 + +--- + +### 9.5 删除文档类型 - `deleteDocumentType()` + +| 项目 | 内容 | +|------|------| +| **函数** | `deleteDocumentType()` | +| **行号** | 466-559 | +| **PostgREST 操作** | `postgrestDelete` | +| **表名** | `document_types` | +| **功能** | 删除文档类型 | +| **调用位置** | `document-types._index.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**建议后端 API**: +``` +DELETE /api/document-types/{id} +Response: { success } +``` + +**优点**: +- ✅ 后端可以检查是否有关联数据 +- ✅ 执行级联删除或软删除 +- ✅ 记录删除日志 + +--- + +### 9.6 获取单个文档类型 - `getDocumentType()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getDocumentType()` | +| **行号** | 560-654 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `document_types` | +| **功能** | 获取单个文档类型详情 | +| **调用位置** | `document-types.new.tsx` | +| **建议** | ⚠️ **建议评估** | + +**说明**: 简单查询,优先级较低 + +--- + +### 9.7 创建文档类型 - `createDocumentType()` + +| 项目 | 内容 | +|------|------| +| **函数** | `createDocumentType()` | +| **行号** | 655-781 | +| **PostgREST 操作** | `postgrestPost` | +| **表名** | `document_types` | +| **功能** | 创建新的文档类型 | +| **调用位置** | `document-types.new.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**建议后端 API**: +``` +POST /api/document-types +Body: { name, description, entryModuleId, groupIds, promptConfigs, ... } +Response: { success, id } +``` + +**优点**: +- ✅ 后端可以验证数据完整性 +- ✅ 处理关联关系的创建 +- ✅ 事务处理 + +--- + +### 9.8 更新文档类型 - `updateDocumentType()` + +| 项目 | 内容 | +|------|------| +| **函数** | `updateDocumentType()` | +| **行号** | 782+ | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `document_types` | +| **功能** | 更新文档类型 | +| **调用位置** | `document-types.new.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**建议后端 API**: +``` +PUT /api/document-types/{id} +Body: { ... } +Response: { success } +``` + +--- + +## 10. 入口模块 + +**文件**: `app/api/entry-modules/entry-modules.ts` + +### 10.1 获取入口模块列表 - `getEntryModules()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getEntryModules()` | +| **行号** | 45-118 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `entry_modules` | +| **功能** | 获取入口模块列表(支持分页、JSONB 数组查询) | +| **调用位置** | `entry-modules._index.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现:使用 JSONB 数组查询 +postgrestGet('entry_modules', { + filter: { + name: 'ilike.*关键词*', + areas: 'cs.{"梅州"}' // JSONB contains + } +}) +``` + +**建议后端 API**: +``` +GET /api/entry-modules?page={p}&pageSize={ps}&name={n}&area={a} +Response: { + modules: [...], + total: 100 +} +``` + +**优点**: +- ✅ 简化 JSONB 查询逻辑 +- ✅ 后端优化查询性能 + +--- + +### 10.2 根据 ID 获取入口模块 - `getEntryModuleById()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getEntryModuleById()` | +| **行号** | 126-150 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `entry_modules` | +| **功能** | 获取单个入口模块详情 | +| **调用位置** | `entry-modules.new.tsx` | +| **建议** | ✅ **保留**(简单查询) | + +--- + +### 10.3 创建入口模块 - `createEntryModule()` + +| 项目 | 内容 | +|------|------| +| **函数** | `createEntryModule()` | +| **行号** | 158-179 | +| **PostgREST 操作** | `postgrestPost` | +| **表名** | `entry_modules` | +| **功能** | 创建新的入口模块 | +| **调用位置** | `entry-modules.new.tsx` | +| **建议** | 🔄 **改为后端 API** | + +--- + +### 10.4 更新入口模块 - `updateEntryModule()` + +| 项目 | 内容 | +|------|------| +| **函数** | `updateEntryModule()` | +| **行号** | 188-211 | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `entry_modules` | +| **功能** | 更新入口模块 | +| **调用位置** | `entry-modules.new.tsx` | +| **建议** | 🔄 **改为后端 API** | + +--- + +### 10.5 删除入口模块 - `deleteEntryModule()` + +| 项目 | 内容 | +|------|------| +| **函数** | `deleteEntryModule()` | +| **行号** | 219-242 | +| **PostgREST 操作** | `postgrestDelete` | +| **表名** | `entry_modules` | +| **功能** | 删除入口模块 | +| **调用位置** | `entry-modules._index.tsx` | +| **建议** | 🔄 **改为后端 API** | + +--- + +## 11. 交叉评查 + +**文件**: `app/api/cross-checking/` + +### 11.1 更新文档审核状态 - `updateDocumentAuditStatus()` + +**文件**: `cross-files.ts` + +| 项目 | 内容 | +|------|------| +| **函数** | `updateDocumentAuditStatus()` | +| **行号** | 476-507 | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `documents` | +| **功能** | 更新文件的审核状态(交叉评查场景) | +| **调用位置** | `cross-checking` 相关页面 | +| **建议** | 🔄 **改为后端 API** | + +**说明**: 与 `rules-files.ts` 中的同名函数类似,建议统一改为后端 API + +--- + +### 11.2 查找是否是发起人 - `findIsProposer()` + +**文件**: `cross-file-result.ts` + +| 项目 | 内容 | +|------|------| +| **函数** | `findIsProposer()` | +| **行号** | 91-112 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `cross_examination_tasks` | +| **功能** | 判断当前用户是否是任务发起人 | +| **调用位置** | 交叉评查意见操作 | +| **建议** | 🔄 **改为后端 API** | + +**建议后端 API**: +``` +GET /api/cross-review/tasks/{taskId}/is-proposer?userId={userId} +Response: { isProposer: true/false } +``` + +**优点**: +- ✅ 后端统一权限判断逻辑 +- ✅ 可以扩展更复杂的权限规则 + +--- + +### 11.3 完成评查 - `confirmReviewResults()` + +**文件**: `cross-file-result.ts` + +| 项目 | 内容 | +|------|------| +| **函数** | `confirmReviewResults()` | +| **行号** | 359-394 | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `documents` | +| **功能** | 完成评查并更新文档审核状态为通过 | +| **调用位置** | `cross-checking.result.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**建议后端 API**: +``` +POST /api/cross-review/documents/{id}/confirm +Response: { success } +``` + +--- + +## 12. 提示词模板 + +**文件**: `app/api/prompts/prompts.ts` + +### 12.1 获取提示词模板列表 - `getPromptTemplates()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getPromptTemplates()` | +| **行号** | 127-232 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `prompt_templates` | +| **功能** | 获取提示词模板列表(支持分页、筛选、关联创建者) | +| **调用位置** | `prompts._index.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现:使用资源嵌入查询创建者 +postgrestGet('prompt_templates', { + select: `id, template_name, ..., + sso_users!created_by(username)`, // 资源嵌入 + filter: { ... }, + order: 'created_at.desc' +}) +``` + +**建议后端 API**: +``` +GET /api/prompts?page={p}&pageSize={ps}&name={n}&type={t}&status={s} +Response: { + templates: [ + { id, name, type, status, createdBy, createdAt, ... } + ], + total: 100 +} +``` + +**优点**: +- ✅ 简化资源嵌入查询 +- ✅ 后端优化查询性能 + +--- + +### 12.2 获取单个提示词模板 - `getPromptTemplate()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getPromptTemplate()` | +| **行号** | 233-279 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `prompt_templates` | +| **功能** | 获取单个提示词模板详情 | +| **调用位置** | `prompts.new.tsx` | +| **建议** | ✅ **保留**(简单查询) | + +--- + +### 12.3 创建提示词模板 - `createPromptTemplate()` + +| 项目 | 内容 | +|------|------| +| **函数** | `createPromptTemplate()` | +| **行号** | 280-359 | +| **PostgREST 操作** | `postgrestPost` | +| **表名** | `prompt_templates` | +| **功能** | 创建新的提示词模板 | +| **调用位置** | `prompts.new.tsx` | +| **建议** | 🔄 **改为后端 API** | + +--- + +### 12.4 更新提示词模板 - `updatePromptTemplate()` + +| 项目 | 内容 | +|------|------| +| **函数** | `updatePromptTemplate()` | +| **行号** | 360-458 | +| **PostgREST 操作** | `postgrestPut` | +| **表名** | `prompt_templates` | +| **功能** | 更新提示词模板 | +| **调用位置** | `prompts.new.tsx` | +| **建议** | 🔄 **改为后端 API** | + +--- + +### 12.5 删除提示词模板 - `deletePromptTemplate()` + +| 项目 | 内容 | +|------|------| +| **函数** | `deletePromptTemplate()` | +| **行号** | 459-499 | +| **PostgREST 操作** | `postgrestDelete` | +| **表名** | `prompt_templates` | +| **功能** | 删除提示词模板 | +| **调用位置** | `prompts._index.tsx` | +| **建议** | 🔄 **改为后端 API** | + +--- + +### 12.6 获取提示词选项列表 - `getPromptTemplateOptions()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getPromptTemplateOptions()` | +| **行号** | 500+ | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `prompt_templates` | +| **功能** | 获取指定类型的模板选项(用于下拉选择) | +| **调用位置** | `document-types.new.tsx`, `rules.new.tsx` | +| **建议** | ✅ **保留**(简单查询,低优先级) | + +--- + +## 13. 合同模板 + +**文件**: `app/api/contract-template/templates.ts` + +### 13.1 获取合同分类 - `getContractCategories()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getContractCategories()` | +| **行号** | 76-105 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `contract_categories` | +| **功能** | 获取所有合同分类 | +| **调用位置** | 合同模板页面 | +| **建议** | ✅ **保留**(简单查询) | + +--- + +### 13.2 获取分类及模板数量 - `getContractCategoriesWithCount()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getContractCategoriesWithCount()` | +| **行号** | 106-169 | +| **PostgREST 操作** | `postgrestGet` × 多次 | +| **表名** | `contract_categories` + `contract_templates` | +| **功能** | 获取分类并统计每个分类的模板数量 | +| **调用位置** | `contract-template.list._index.tsx`, `contract-template.search._index.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现:多次查询 +1. postgrestGet('contract_categories', ...) // 获取所有分类 +2. 对每个分类:postgrestGet('contract_templates', { filter: { category_id } }) +3. 前端统计数量 +``` + +**建议后端 API**: +``` +GET /api/contract-templates/categories-with-count +Response: { + categories: [ + { id, name, count: 10 } + ] +} +``` + +**优点**: +- ✅ 一次查询获取所有数据(使用 SQL JOIN + COUNT) +- ✅ 大幅提升性能 + +--- + +### 13.3 获取合同模板列表 - `getContractTemplates()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getContractTemplates()` | +| **行号** | 170-311 | +| **PostgREST 操作** | `postgrestGet` × 2 | +| **表名** | `contract_categories` + `contract_templates` | +| **功能** | 获取合同模板列表(支持分页、筛选、关键词搜索) | +| **调用位置** | `contract-template.list._index.tsx`, `contract-template.search.results.tsx` | +| **建议** | 🔄 **改为后端 API** | + +**详细说明**: +```typescript +// 当前实现:复杂的 OR 条件查询 +1. 如果有关键词:postgrestGet('contract_categories', { filter: { name: 'ilike.*关键词*' } }) +2. postgrestGet('contract_templates', { + select: `..., contract_categories!fk_contract_templates_category(...)`, // 资源嵌入 + or: `(title.ilike.*关键词*,description.ilike.*关键词*,template_code.ilike.*关键词*)` // OR 查询 + }) +``` + +**建议后端 API**: +``` +GET /api/contract-templates?page={p}&pageSize={ps}&category={c}&format={f}&keyword={k}&featured={f} +Response: { + templates: [...], + total: 100 +} +``` + +**优点**: +- ✅ 简化复杂的 OR 条件查询 +- ✅ 后端优化全文搜索 +- ✅ 支持更高级的搜索功能 + +--- + +### 13.4 获取单个合同模板 - `getContractTemplate()` + +| 项目 | 内容 | +|------|------| +| **函数** | `getContractTemplate()` | +| **行号** | 312-346 | +| **PostgREST 操作** | `postgrestGet` | +| **表名** | `contract_templates` | +| **功能** | 获取单个合同模板详情 | +| **调用位置** | `contract-template.detail.$id.tsx` | +| **建议** | ✅ **保留**(简单查询) | + +--- + +### 13.5 搜索合同模板 - `searchContractTemplates()` + +| 项目 | 内容 | +|------|------| +| **函数** | `searchContractTemplates()` | +| **行号** | 380+ | +| **PostgREST 操作** | 内部调用 `getContractTemplates()` | +| **功能** | 搜索合同模板(封装函数) | +| **调用位置** | `contract-template.search.results.tsx` | +| **建议** | 🔄 **改为后端 API**(随 `getContractTemplates` 一起) | + +--- + +## 汇总统计 + +### 按建议分类 + +| 建议 | 数量 | 占比 | +|------|------|------| +| 🔄 **强烈建议改为后端 API** | 32 | 53% | +| 🔒 **必须保留**(评查点详情) | 17 | 28% | +| ✅ **保留** PostgREST | 8 | 13% | +| ⚠️ **建议评估** | 3 | 5% | +| **总计** | **60** | **100%** | + +--- + +### 按模块分类 + +| 模块 | 🔄 改为 API | 🔒 必须保留 | ✅ 保留 | ⚠️ 评估 | 小计 | +|------|-----------|-----------|---------|---------|------| +| 认证服务 | 2 | 0 | 0 | 0 | 2 | +| 首页与统计 | 1 | 0 | 0 | 0 | 1 | +| 文档管理 | 4 | 0 | 0 | 0 | 4 | +| 文件上传 | 2 | 0 | 1 | 1 | 4 | +| 评查点管理 | 1 | 9 | 0 | 0 | 10 | +| 评查点分组 | 0 | 7 | 0 | 0 | 7 | +| 评查文件审核 | 1 | 0 | 0 | 0 | 1 | +| 评审结果 | 3 | 0 | 0 | 0 | 3 | +| 文档类型 | 5 | 2 | 0 | 2 | 9 | +| 入口模块 | 4 | 0 | 1 | 0 | 5 | +| 交叉评查 | 3 | 0 | 0 | 0 | 3 | +| 提示词模板 | 4 | 0 | 2 | 0 | 6 | +| 合同模板 | 3 | 0 | 2 | 0 | 5 | +| **总计** | **32** | **17** | **8** | **3** | **60** | + +--- + +## 优先级建议 + +### 🔥 高优先级(建议立即改为后端 API) + +1. **评审结果模块** - `getReviewPoints()` + `updateReviewResult()` + - 理由:涉及 6 表关联查询,性能影响大 + +2. **文档管理模块** - `getDocument()` + `updateDocument()` + `deleteDocument()` + - 理由:核心业务,使用频繁 + +3. **文档状态查询** - `getDocumentsStatus()` + - 理由:轮询操作,频繁调用 + +4. **合同模板列表** - `getContractCategoriesWithCount()` + `getContractTemplates()` + - 理由:多次查询,性能优化空间大 + +5. **认证服务** - `saveUserInfo()` + `addDefaultRole()` + - 理由:安全性考虑,不应前端直接操作用户表 + +--- + +### ⚡ 中优先级 + +6. **评查点列表** - `getRulesList()` + - 理由:复杂的资源嵌入查询 + +7. **文档类型管理** - CRUD 操作 + - 理由:涉及关联数据处理 + +8. **入口模块管理** - CRUD 操作 + - 理由:涉及 JSONB 查询 + +9. **提示词模板管理** - CRUD 操作 + - 理由:资源嵌入查询 + +--- + +### 🔽 低优先级 + +10. **简单查询操作** + - 理由:性能影响小,可后续优化 + +--- + +## 建议的实施步骤 + +1. **Phase 1**: 高优先级模块(1-5) +2. **Phase 2**: 中优先级模块(6-9) +3. **Phase 3**: 低优先级模块(10) + +每个 Phase 预计耗时: +- Phase 1: 2-3 周 +- Phase 2: 2 周 +- Phase 3: 1 周 + +--- + +**注意**: 评查点详情相关的 17 个函数必须保留 PostgREST,不应改为后端 API。 diff --git a/docs/PostgREST实际使用清单.md b/docs/PostgREST实际使用清单.md new file mode 100644 index 0000000..904bcea --- /dev/null +++ b/docs/PostgREST实际使用清单.md @@ -0,0 +1,582 @@ +# PostgREST 实际使用清单 + +> **本文档记录项目中实际使用 PostgREST 的模块** +> **更新时间**: 2025-11-25 +> **PostgREST 客户端**: `app/api/postgrest-client.ts` + +--- + +## 📋 目录 + +- [实际使用的模块](#实际使用的模块) + - [1. 认证服务](#1-认证服务) + - [2. 首页与统计](#2-首页与统计) + - [3. 文档管理](#3-文档管理) + - [4. 文件上传](#4-文件上传) + - [5. 评查点管理](#5-评查点管理) + - [6. 评查点分组](#6-评查点分组) + - [7. 评查文件审核](#7-评查文件审核) + - [8. 评审结果](#8-评审结果) + - [9. 文档类型](#9-文档类型) + - [10. 入口模块](#10-入口模块) + - [11. 交叉评查](#11-交叉评查) + - [12. 提示词模板](#12-提示词模板) + - [13. 合同模板](#13-合同模板) + - [14. 评查点编辑页面](#14-评查点编辑页面) +- [排除列表](#排除列表) +- [统计数据](#统计数据) + +--- + +## 实际使用的模块 + +### 1. 认证服务 + +**文件路径**: `app/api/login/auth.server.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `saveUserInfo()` | 583 | `postgrestGet` | `sso_users` | 查询用户是否已存在 | +| `saveUserInfo()` | 625 | `postgrestPut` | `sso_users` | 更新已存在用户信息 | +| `saveUserInfo()` | 653 | `postgrestPost` | `sso_users` | 插入新用户记录 | +| `addDefaultRole()` | 696 | `postgrestGet` | `user_role` | 查询用户是否已有角色 | +| `addDefaultRole()` | 716 | `postgrestPost` | `user_role` | 为用户添加默认角色 | +| `getUserBySub()` | 750 | `postgrestGet` | `sso_users` | 根据 sub 查询用户信息 | + +#### 使用场景 + +- ✅ OAuth2.0 登录后保存用户信息到数据库 +- ✅ 自动为新用户添加默认角色(common 角色) +- ✅ 更新用户信息(如部门、手机号等) +- ✅ 查询用户信息用于会话管理 + +#### 被哪些路由使用 + +- `app/routes/callback.tsx` - OAuth 回调处理 +- `app/root.tsx` - 全局认证检查 +- 其他 17 个路由文件 + +--- + +### 2. 首页与统计 + +**文件路径**: `app/api/home/home.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getEntryModules()` | - | `postgrestGet` | `entry_modules` | 获取用户可访问的入口模块 | +| `getEntryModules()` | - | `postgrestGet` | `document_types` | 查询入口模块关联的文档类型 | + +#### 使用场景 + +- ✅ 根据用户角色和地区过滤可访问的入口模块 +- ✅ 查询入口模块关联的文档类型 +- ✅ 客户端地区启用状态过滤 + +#### 被哪些路由使用 + +- `app/routes/home.tsx` - 首页展示 + +--- + +### 3. 文档管理 + +**文件路径**: `app/api/files/documents.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getEvaluationResults()` | 147-159 | `postgrestGet` | `evaluation_results` | 获取文档评查结果 | +| `deleteDocument()` | 256 | `postgrestDelete` | `documents` | 删除文档 | +| `getDocument()` | 300 | `postgrestGet` | `documents` | 获取单个文档(带用户ID过滤) | +| `getDocumentWithNoUserId()` | 351 | `postgrestGet` | `documents` | 获取单个文档(无用户ID限制) | +| `updateDocument()` | 432 | `postgrestPut` | `documents` | 更新文档信息 | +| `getDocumentHistory()` | 685 | `postgrestPost` (RPC) | `rpc/documents_get_document_history` | 获取文档历史版本 | + +#### 权限控制 + +- ✅ `deleteDocument()` - 只能删除自己的文档 +- ✅ `getDocument()` - 只能查看自己的文档 +- ❌ `getDocumentWithNoUserId()` - 可跨用户查看(交叉评查场景) +- ✅ `updateDocument()` - 只能更新自己的文档 + +#### 被哪些路由使用 + +- `app/routes/home.tsx` - 首页文档展示 +- `app/routes/documents.list.tsx` - 文档列表 +- `app/routes/documents.edit.tsx` - 文档编辑 +- `app/api/evaluation_points/reviews.ts` - 评审结果查询 + +--- + +### 4. 文件上传 + +**文件路径**: `app/api/files/files-upload.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getTodayDocuments()` | 500 | `postgrestGet` | `documents` | 获取当天上传的文档列表 | +| `getDocumentTypes()` | 555 | `postgrestGet` | `document_types` | 获取文档类型列表 | +| `getDocumentsStatus()` | 603 | `postgrestGet` | `documents` | 查询主文档状态 | +| `getDocumentsStatus()` | 616 | `postgrestGet` | `contract_structure_comparison` | 查询合同附件状态 | + +#### 特性说明 + +- ✅ `getTodayDocuments()` - 支持从 sessionStorage 读取文档类型 ID 进行动态过滤 +- ✅ `getDocumentTypes()` - 支持按文档类型 ID 数组过滤 +- ✅ `getDocumentsStatus()` - 支持批量查询文档和合同附件的处理状态 + +#### 被哪些路由使用 + +- `app/routes/documents.list.tsx` - 文档列表 +- `app/routes/files.upload.tsx` - 文件上传页面 +- `app/components/reviews/ReviewTabs.tsx` - 评审标签页 + +--- + +### 5. 评查点管理 + +**文件路径**: `app/api/evaluation_points/rules.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getRulesList()` | - | `postgrestGet` | `evaluation_points` | 获取评查点列表 | +| `getRulesList()` | - | `postgrestGet` | `evaluation_point_groups` | 查询规则组(类型筛选) | +| `getRule()` | - | `postgrestGet` | `evaluation_points` | 获取单个评查点详情 | +| `getRule()` | - | `postgrestGet` | `evaluation_point_groups` | 获取评查点所属分组 | +| `createRule()` | - | `postgrestPost` | `evaluation_points` | 创建新评查点 | +| `updateRule()` | - | `postgrestPut` | `evaluation_points` | 更新评查点 | +| `deleteRule()` | - | `postgrestDelete` | `evaluation_points` | 删除评查点 | +| `getRuleTypes()` | - | `postgrestGet` | `document_types` | 获取文档类型 | +| `getRuleTypes()` | - | `postgrestGet` | `evaluation_point_groups` | 获取评查点类型 | +| `getRuleGroupsByType()` | - | `postgrestGet` | `evaluation_point_groups` | 根据类型获取规则组 | +| `getEvaluationPoint()` | - | `postgrestGet` | `evaluation_points` | 获取评查点数据(编辑用) | +| `getEvaluationPointGroups()` | - | `postgrestGet` | `evaluation_point_groups` | 获取所有评查点组 | +| `saveEvaluationPoint()` | - | `postgrestPut` / `postgrestPost` | `evaluation_points` | 保存评查点(新建或更新) | + +#### 高级特性 + +- ✅ 使用 PostgREST 双连接查询获取父子分组关系 +- ✅ 支持分页、排序、多条件筛选 +- ✅ 支持按地区过滤(省级管理员可见所有) +- ✅ 评查点编码清洗(移除地区后缀) + +#### 被哪些路由使用 + +- `app/routes/rules.list.tsx` - 评查点列表 + +--- + +### 6. 评查点分组 + +**文件路径**: `app/api/evaluation_points/rule-groups.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getRuleGroups()` | - | `postgrestGet` | `evaluation_point_groups` | 获取顶级评查点分组 | +| `getChildGroups()` | - | `postgrestGet` | `evaluation_point_groups` | 获取子分组列表 | +| `getChildGroups()` | - | `postgrestGet` | `evaluation_points` | 查询子分组的评查点数量 | +| `getAllRuleGroups()` | - | `postgrestGet` | `evaluation_point_groups` | 获取所有分组(树形) | +| `getAllRuleGroups()` | - | `postgrestGet` | `evaluation_points` | 查询每个子分组的评查点数量 | +| `getRuleGroup()` | - | `postgrestGet` | `evaluation_point_groups` | 获取单个分组详情 | +| `getRuleGroup()` | - | `postgrestGet` | `evaluation_points` | 查询分组的评查点数量 | +| `createRuleGroup()` | - | `postgrestPost` | `evaluation_point_groups` | 创建新分组 | +| `updateRuleGroup()` | - | `postgrestPut` | `evaluation_point_groups` | 更新分组 | +| `deleteRuleGroup()` | - | `postgrestDelete` | `evaluation_point_groups` | 删除分组 | +| `deleteEvaluationPointsByGroupId()` | - | `postgrestDelete` | `evaluation_points` | 级联删除评查点 | + +#### 特性说明 + +- ✅ 支持树形结构查询(一级分组 + 二级分组) +- ✅ 级联删除子分组和评查点 +- ✅ 查询分组关联的评查点数量 + +#### 被哪些路由使用 + +- `app/routes/rule-groups.new.tsx` - 创建/编辑分组 +- `app/routes/rule-groups._index.tsx` - 分组列表 +- `app/routes/document-types.new.tsx` - 文档类型关联分组 + +--- + +### 7. 评查文件审核 + +**文件路径**: `app/api/evaluation_points/rules-files.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `updateDocumentAuditStatus()` | 138 | `postgrestPut` | `documents` | 更新文档审核状态 | + +#### 审核状态说明 + +- `-1` - 不通过 +- `0` - 待审核 +- `1` - 通过 +- `2` - 警告 + +#### 权限控制 + +- ✅ 确保只能更新用户自己的文档(通过 `user_id` 过滤) + +#### 被哪些路由使用 + +- `app/routes/documents.list.tsx` - 文档列表审核操作 +- `app/routes/files.upload.tsx` - 文件上传后审核 + +--- + +### 8. 评审结果 + +**文件路径**: `app/api/evaluation_points/reviews.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getReviewPoints()` | - | `postgrestGet` | `contract_structure_comparison` | 获取文档附件数据 | +| `getReviewPoints()` | - | `postgrestGet` | `evaluation_results` | 获取评查结果 | +| `getReviewPoints()` | - | `postgrestGet` | `evaluation_points` | 获取评查点详情 | +| `getReviewPoints()` | - | `postgrestGet` | `evaluation_point_groups` | 获取评查点组信息 | +| `getReviewPoints()` | - | `postgrestGet` | `audit_status` | 获取人工审核状态 | +| `getReviewPoints()` | - | `postgrestGet` | `cross_scoring_proposals` | 获取交叉评分提案 | +| `updateReviewResult()` | - | `postgrestGet` | `evaluation_results` | 获取当前评查结果 | +| `updateReviewResult()` | - | `postgrestPut` | `evaluation_results` | 更新评查结果 | +| `updateReviewResult()` | - | `postgrestPut` | `audit_status` | 更新审核状态 | +| `updateReviewResult()` | - | `postgrestPost` | `audit_status` | 创建新审核状态记录 | +| `confirmReviewResults()` | - | `postgrestPut` | `documents` | 确认评查并更新文档状态 | + +#### 数据关联复杂度 + +- ✅ 跨 6 个表查询完整的评查结果 +- ✅ 关联评查点、分组、审核状态、交叉提案等 + +#### 被哪些路由使用 + +- `app/routes/reviews.tsx` - 文档评审页面 +- `app/routes/cross-checking.result.tsx` - 交叉评查结果 + +--- + +### 9. 文档类型 + +**文件路径**: `app/api/document-types/document-types.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getDocumentTypes()` | - | `postgrestGet` | `document_types` | 获取文档类型列表 | +| `getDocumentType()` | - | `postgrestGet` | `document_types` | 获取文档类型详情 | +| `createDocumentType()` | - | `postgrestPost` | `document_types` | 创建文档类型 | +| `updateDocumentType()` | - | `postgrestPut` | `document_types` | 更新文档类型 | +| `deleteDocumentType()` | - | `postgrestDelete` | `document_types` | 删除文档类型 | +| `getAllEvaluationPointGroups()` | - | `postgrestGet` | `evaluation_point_groups` | 获取所有评查点分组 | +| `getParentEvaluationPointGroups()` | - | `postgrestGet` | `evaluation_point_groups` | 获取父级分组 | +| `getEntryModules()` | - | `postgrestGet` | `entry_modules` | 获取入口模块列表 | +| `getEvaluationPointGroupsByIds()` | - | `postgrestGet` | `evaluation_point_groups` | 根据 ID 获取分组信息 | + +#### 特性说明 + +- ✅ 支持资源嵌入查询(关联入口模块) +- ✅ 支持按文档类型 ID 数组过滤 +- ✅ 文档类型关联评查点分组和提示词配置 + +#### 被哪些路由使用 + +- `app/routes/documents.list.tsx` - 文档类型筛选 +- `app/routes/document-types.new.tsx` - 创建/编辑文档类型 +- `app/routes/document-types._index.tsx` - 文档类型列表 +- `app/api/files/documents.ts` - 文档类型查询 +- `app/routes/documents.edit.tsx` - 文档编辑 + +--- + +### 10. 入口模块 + +**文件路径**: `app/api/entry-modules/entry-modules.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getEntryModules()` | 85 | `postgrestGet` | `entry_modules` | 获取入口模块列表 | +| `getEntryModuleById()` | 131 | `postgrestGet` | `entry_modules` | 根据 ID 获取入口模块 | +| `createEntryModule()` | 163 | `postgrestPost` | `entry_modules` | 创建入口模块 | +| `updateEntryModule()` | 194 | `postgrestPut` | `entry_modules` | 更新入口模块 | +| `deleteEntryModule()` | 224 | `postgrestDelete` | `entry_modules` | 删除入口模块 | + +#### 高级特性 + +- ✅ 支持 JSONB 数组查询(`areas` 字段) + ```typescript + filter: { 'areas': 'cs.{"梅州"}' } // cs = contains + ``` +- ✅ 支持分页、排序、按名称和地区筛选 +- ✅ 返回 Content-Range 头获取总数 + +#### 被哪些路由使用 + +- `app/routes/entry-modules._index.tsx` - 入口模块列表 +- `app/routes/entry-modules.new.tsx` - 创建/编辑入口模块 + +--- + +### 11. 交叉评查 + +**文件路径**: `app/api/cross-checking/` + +#### 11.1 cross-files.ts + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `updateDocumentAuditStatus()` | 486 | `postgrestPut` | `documents` | 更新文档审核状态 | + +#### 11.2 cross-file-result.ts + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `findIsProposer()` | 93 | `postgrestGet` | `cross_examination_tasks` | 查找是否是任务发起人 | +| `confirmReviewResults()` | 365 | `postgrestPut` | `documents` | 完成评查并更新文档状态 | + +#### 混合使用说明 + +- ✅ PostgREST 用于文档状态更新和权限判断 +- ✅ 后端 API 用于任务、意见、投票管理 +- ⚠️ 无用户 ID 过滤(交叉评查需要跨用户操作) + +#### 被哪些路由使用 + +- `app/routes/cross-checking._index.tsx` - 交叉评查任务列表 +- `app/routes/cross-checking.result.tsx` - 评查结果页面 +- `app/components/cross-checking/DocumentListModal.tsx` - 文档列表弹窗 +- `app/components/cross-checking/ReviewPointsList.tsx` - 评查点列表 + +--- + +### 12. 提示词模板 + +**文件路径**: `app/api/prompts/prompts.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getPromptTemplates()` | - | `postgrestGet` | `prompt_templates` | 获取提示词模板列表 | +| `getPromptTemplate()` | - | `postgrestGet` | `prompt_templates` | 获取模板详情 | +| `createPromptTemplate()` | - | `postgrestPost` | `prompt_templates` | 创建提示词模板 | +| `updatePromptTemplate()` | - | `postgrestPut` | `prompt_templates` | 更新提示词模板 | +| `deletePromptTemplate()` | - | `postgrestDelete` | `prompt_templates` | 删除提示词模板 | +| `getPromptTemplateOptions()` | - | `postgrestGet` | `prompt_templates` | 获取模板选项列表 | + +#### 资源嵌入查询 + +```typescript +select: ` + id, template_name, template_type, + sso_users!created_by(username) +` +``` + +#### 模板类型 + +- `LLM_Extraction` - LLM 抽取 +- `VLM_Extraction` - VLM 抽取 +- `Evaluation` - 评查 +- `Summary` - 总结 +- `Common` - 通用 + +#### 被哪些路由使用 + +- `app/routes/prompts.new.tsx` - 创建/编辑提示词 +- `app/routes/prompts._index.tsx` - 提示词列表 +- `app/routes/document-types.new.tsx` - 文档类型关联提示词 +- `app/routes/rules.new.tsx` - 评查点关联提示词 + +--- + +### 13. 合同模板 + +**文件路径**: `app/api/contract-template/templates.ts` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `getContractCategories()` | - | `postgrestGet` | `contract_categories` | 获取合同分类列表 | +| `getContractCategoriesWithCount()` | - | `postgrestGet` | `contract_categories` | 获取分类及模板数量 | +| `getContractCategoriesWithCount()` | - | `postgrestGet` | `contract_templates` | 统计每个分类的模板数量 | +| `getContractTemplates()` | - | `postgrestGet` | `contract_categories` | 查询分类(关键词搜索) | +| `getContractTemplates()` | - | `postgrestGet` | `contract_templates` | 获取合同模板列表 | +| `getContractTemplate()` | - | `postgrestGet` | `contract_templates` | 获取单个模板详情 | +| `getFeaturedTemplates()` | - | `postgrestGet` | `contract_templates` | 获取推荐模板 | + +#### 高级特性 + +- ✅ 支持 OR 条件查询(多字段模糊搜索) + ```typescript + or: [ + { title: 'ilike.*关键词*' }, + { description: 'ilike.*关键词*' }, + { template_code: 'ilike.*关键词*' } + ] + ``` +- ✅ 使用资源嵌入查询分类信息 + +#### 被哪些路由使用 + +- `app/routes/contract-template.detail.$id.tsx` - 模板详情 +- `app/routes/contract-template.search._index.tsx` - 模板搜索 +- `app/routes/contract-template.search.results.tsx` - 搜索结果 +- `app/routes/contract-template.list._index.tsx` - 模板列表 + +--- + +### 14. 评查点编辑页面 + +**文件路径**: `app/routes/rules.new.tsx` + +#### PostgREST 函数使用情况 + +| 函数名 | 行号 | 操作 | 表名 | 功能说明 | +|--------|------|------|------|---------| +| `fetchEvaluationPoint()` | - | `postgrestGet` | `evaluation_points` | 获取评查点数据(编辑模式) | +| `fetchEvaluationPointGroups()` | - | `postgrestGet` | `evaluation_point_groups` | 获取评查点组数据 | +| `handleSave()` | - | `postgrestPut` | `evaluation_points` | 更新评查点(编辑模式) | +| `handleSave()` | - | `postgrestPost` | `evaluation_points` | 创建评查点(新建模式) | + +#### 特性说明 + +- ✅ 支持评查点创建、编辑、复制模式 +- ✅ 评查点编码清洗(移除地区后缀) +- ✅ 表单验证(必填字段、规则完整性) + +--- + +## 排除列表 + +### ❌ 已删除或未使用的模块 + +| 模块名 | 路径 | 状态 | 原因 | +|--------|------|------|------| +| `config-lists.ts` | `app/api/system_setting/config-lists.ts` | ✅ 已删除 | 不再使用 | + +--- + +## 统计数据 + +### 模块统计 + +| 类型 | 数量 | +|------|------| +| API 模块 | 13 | +| 路由模块 | 1 | +| **总计** | **14** | + +### 数据库表使用频率 + +| 表名 | 使用次数 | 主要操作 | +|------|---------|---------| +| `evaluation_points` | 🔥🔥🔥🔥🔥 | GET, POST, PUT, DELETE(最高频) | +| `evaluation_point_groups` | 🔥🔥🔥🔥 | GET, POST, PUT, DELETE | +| `documents` | 🔥🔥🔥🔥 | GET, PUT, DELETE | +| `sso_users` | 🔥🔥🔥 | GET, PUT, POST | +| `evaluation_results` | 🔥🔥🔥 | GET, PUT | +| `document_types` | 🔥🔥🔥 | GET, POST, PUT, DELETE | +| `prompt_templates` | 🔥🔥🔥 | GET, POST, PUT, DELETE | +| `entry_modules` | 🔥🔥 | GET, POST, PUT, DELETE | +| `contract_templates` | 🔥🔥 | GET | +| `contract_categories` | 🔥🔥 | GET | +| `user_role` | 🔥 | GET, POST | +| `audit_status` | 🔥 | GET, PUT, POST | +| `cross_examination_tasks` | 🔥 | GET | +| `cross_scoring_proposals` | 🔥 | GET | +| `contract_structure_comparison` | 🔥 | GET | + +### PostgREST 操作统计 + +| 操作类型 | 使用频率 | +|---------|---------| +| `postgrestGet` | 🔥🔥🔥🔥🔥 | +| `postgrestPut` | 🔥🔥🔥🔥 | +| `postgrestPost` | 🔥🔥🔥 | +| `postgrestDelete` | 🔥🔥 | + +### PostgREST 高级特性使用 + +| 特性 | 使用示例 | +|------|---------| +| **资源嵌入查询** | 文档类型关联入口模块、提示词关联创建者 | +| **JSONB 数组查询** | 入口模块地区过滤 (`areas cs.{"梅州"}`) | +| **OR 条件查询** | 合同模板多字段搜索 | +| **分页与排序** | 所有列表查询 | +| **RPC 函数调用** | 文档历史版本查询 | +| **批量查询** | 文档状态轮询 (`id in.(1,2,3)`) | +| **总数统计** | Content-Range 头获取 total | + +--- + +## 🔧 PostgREST 客户端核心函数 + +| 函数名 | 功能 | +|--------|------| +| `postgrestGet()` | GET 请求,查询数据 | +| `postgrestPost()` | POST 请求,创建数据或调用 RPC | +| `postgrestPut()` | PUT 请求,更新数据 | +| `postgrestDelete()` | DELETE 请求,删除数据 | + +--- + +## ⚠️ 重要说明 + +### 权限控制差异 + +1. **严格用户权限控制**(通过 `user_id` 过滤): + - `documents.ts` 中的 CRUD 操作 + - `rules-files.ts` 中的审核状态更新 + +2. **跨用户访问**(无 `user_id` 过滤): + - `cross-checking` 模块(交叉评查需要) + - `getDocumentWithNoUserId()` 函数 + +### 数据提取统一方式 + +所有模块使用统一的 `extractApiData()` 函数处理响应: + +```typescript +function extractApiData(responseData: unknown): T | null { + // 格式1: { code: number, msg: string, data: T } + if (typeof responseData === 'object' && 'data' in responseData) { + return (responseData as { data: T }).data; + } + // 格式2: 直接是数据对象 + return responseData as T; +} +``` + +### JWT 认证 + +所有 PostgREST 请求都支持 JWT token 参数: + +```typescript +const response = await postgrestGet('table_name', { + filter: { ... }, + token: frontendJWT // JWT 认证 +}); +``` + +--- + +**文档维护**: 添加或删除 PostgREST 模块时,请及时更新此文档。 diff --git a/docs/PostgREST未使用函数清单.md b/docs/PostgREST未使用函数清单.md new file mode 100644 index 0000000..1af98e7 --- /dev/null +++ b/docs/PostgREST未使用函数清单.md @@ -0,0 +1,348 @@ +# PostgREST 未使用函数清单 + +> **本文档记录所有定义了但未被实际引用的 PostgREST 相关函数** +> **更新时间**: 2025-11-25 + +--- + +## 📋 目录 + +- [完全未使用的函数](#完全未使用的函数) +- [仅内部使用的函数](#仅内部使用的函数) +- [建议的清理操作](#建议的清理操作) + +--- + +## 完全未使用的函数 + +这些函数被导出但在整个项目中没有任何地方调用。 + +### 1. ❌ `getUserBySub()` + +**文件**: `app/api/login/auth.server.ts` +**行号**: 746 +**PostgREST 操作**: `postgrestGet` +**表名**: `sso_users` + +```typescript +export async function getUserBySub(sub: string) { + const userResult = await postgrestGet("sso_users", { + filter: { sub: `eq.${sub}` } + }); + // ... +} +``` + +**搜索结果**: 只在定义文件中出现 1 次 +**建议**: 🗑️ **可以删除** + +--- + +### 2. ❌ `getDocumentHistory()` + +**文件**: `app/api/files/documents.ts` +**行号**: 665 +**PostgREST 操作**: `postgrestPost` (RPC) +**RPC 函数**: `rpc/documents_get_document_history` + +```typescript +export async function getDocumentHistory( + documentName: string, + userId: string, + excludeId: number, + token?: string +): Promise<{data?: DocumentVersionUI[]; error?: string; status?: number}> { + const response = await postgrestPost( + 'rpc/documents_get_document_history', + { p_document_name, p_user_id, p_exclude_id }, + token + ); + // ... +} +``` + +**搜索结果**: routes 和 components 中 0 次引用 +**建议**: 🗑️ **可以删除** (新API已改用 `/admin/versions/documents-list`) + +--- + +### 3. ❌ `duplicateRule()` + +**文件**: `app/api/evaluation_points/rules.ts` +**行号**: 740 +**PostgREST 操作**: `postgrestGet` + `postgrestPost` +**表名**: `evaluation_points` + +```typescript +export async function duplicateRule(id: string, token?: string): Promise<{ + data: Rule; + error?: never +} | { + data?: never; + error: string; + status?: number +}> { + // 1. 获取原规则 + const originalRule = await postgrestGet(...); + // 2. 创建副本 + const result = await postgrestPost(...); + // ... +} +``` + +**搜索结果**: 只在定义文件中出现 1 次 +**建议**: 🔄 **保留但标记为未来功能** (复制功能可能有计划) + +--- + +### 4. ❌ `getEvaluationPointGroupsByIds()` + +**文件**: `app/api/document-types/document-types.ts` +**行号**: 245 +**PostgREST 操作**: `postgrestGet` +**表名**: `evaluation_point_groups` + +```typescript +export async function getEvaluationPointGroupsByIds( + ids: number[] | number, + token?: string +): Promise<{ + data: EvaluationPointGroup[]; + error?: never +} | { + data?: never; + error: string; + status?: number +}> { + const response = await postgrestGet( + "evaluation_point_groups", + { + filter: { id: `in.(${idsArray.join(',')})` }, + token + } + ); + // ... +} +``` + +**搜索结果**: 只在定义文件中出现 5 次(都是定义和类型导出) +**建议**: 🗑️ **可以删除** + +--- + +### 5. ❌ `createSimpleUserSession()` + +**文件**: `app/api/login/auth.server.ts` +**行号**: 412 +**PostgREST 操作**: 无(仅 session 管理) + +```typescript +export async function createSimpleUserSession( + isAuthenticated: boolean, + userRole: UserRole, + redirectTo: string +) { + const session = await sessionStorage.getSession(); + session.set("isAuthenticated", isAuthenticated); + session.set("userRole", userRole); + // ... +} +``` + +**搜索结果**: 只在定义文件中出现 1 次 +**建议**: 🗑️ **可以删除** (已统一使用 `createUserSession`) + +--- + +### 6. ❌ `getFeaturedTemplates()` + +**文件**: `app/api/contract-template/templates.ts` +**行号**: 347 +**PostgREST 操作**: `postgrestGet` +**表名**: `contract_templates` + +```typescript +export async function getFeaturedTemplates( + limit: number = 6, + jwt?: string +) { + const response = await postgrestGet( + 'contract_templates', + { + filter: { is_featured: 'eq.true' }, + order: 'created_at.desc', + limit: limit, + token: jwt + } + ); + // ... +} +``` + +**搜索结果**: 只在定义文件中出现 1 次 +**建议**: 🔄 **保留但标记为未来功能** (推荐模板功能可能有计划) + +--- + +## 仅内部使用的函数 + +这些函数虽然被导出,但只在同一个文件内部被调用,不被其他文件引用。 + +### 7. ⚠️ `getEvaluationResults()` + +**文件**: `app/api/files/documents.ts` +**行号**: 147-159 +**PostgREST 操作**: `postgrestGet` +**表名**: `evaluation_results` + +```typescript +async function getEvaluationResults(id: number, frontendJWT?: string) { + const response = await postgrestGet<[]>('evaluation_results', { + filter: { 'document_id': `eq.${id}` }, + token: frontendJWT + }); + // ... +} +``` + +**搜索结果**: 只在 `documents.ts` 内部被 `convertToUIDocument()` 调用 +**建议**: ✅ **改为内部函数**(去掉 export) + +--- + +### 8. ⚠️ `convertToUIDocument()` + +**文件**: `app/api/files/documents.ts` +**行号**: 165 +**PostgREST 操作**: 调用 `getEvaluationResults()` +**表名**: 间接查询 `evaluation_results` + +```typescript +async function convertToUIDocument( + doc: Document, + frontendJWT?: string +): Promise { + const evaluationResult = await getEvaluationResults(doc.id, frontendJWT); + // ... +} +``` + +**搜索结果**: 只在 `documents.ts` 内部被其他函数调用 +**建议**: ✅ **改为内部函数**(去掉 export) + +--- + +### 9. ⚠️ `convertApiRuleToFormData()` + +**文件**: `app/api/evaluation_points/rules.ts` +**行号**: 1079 +**PostgREST 操作**: 无(数据转换函数) + +```typescript +export function convertApiRuleToFormData( + apiRule: ApiRule +): FormattedEvaluationPoint { + // 数据格式转换 +} +``` + +**搜索结果**: 只在定义文件中出现 4 次(内部调用) +**建议**: ✅ **改为内部函数**(去掉 export) + +--- + +### 10. ⚠️ `convertToUITemplate()` + +**文件**: `app/api/prompts/prompts.ts` +**行号**: 102 +**PostgREST 操作**: 无(数据转换函数) + +```typescript +export function convertToUITemplate( + template: PromptTemplate & { sso_users?: { username: string } } +): PromptTemplateUI { + // 数据格式转换 +} +``` + +**搜索结果**: 只在定义文件中出现 5 次(内部调用) +**建议**: ✅ **改为内部函数**(去掉 export) + +--- + +## 建议的清理操作 + +### 🗑️ 立即删除(6 个函数) + +| 序号 | 函数名 | 文件 | 原因 | +|------|--------|------|------| +| 1 | `getUserBySub()` | `auth.server.ts` | 完全未使用 | +| 2 | `getDocumentHistory()` | `documents.ts` | 已被新 API 替代 | +| 3 | `getEvaluationPointGroupsByIds()` | `document-types.ts` | 完全未使用 | +| 4 | `createSimpleUserSession()` | `auth.server.ts` | 已统一使用 `createUserSession` | +| 5 | ~~`duplicateRule()`~~ | `rules.ts` | 保留(可能是未来功能) | +| 6 | ~~`getFeaturedTemplates()`~~ | `templates.ts` | 保留(可能是未来功能) | + +**实际建议删除**: **4 个函数** + +--- + +### ✅ 改为私有函数(4 个函数) + +将这些仅内部使用的函数改为非导出(去掉 `export` 关键字): + +| 序号 | 函数名 | 文件 | 操作 | +|------|--------|------|------| +| 1 | `getEvaluationResults()` | `documents.ts` | 去掉 export | +| 2 | `convertToUIDocument()` | `documents.ts` | 去掉 export | +| 3 | `convertApiRuleToFormData()` | `rules.ts` | 去掉 export | +| 4 | `convertToUITemplate()` | `prompts.ts` | 去掉 export | + +--- + +## 🔄 保留但标记的函数(2 个) + +这些函数虽然当前未使用,但可能是计划中的功能: + +| 序号 | 函数名 | 文件 | 建议 | +|------|--------|------|------| +| 1 | `duplicateRule()` | `rules.ts` | 添加 `@deprecated` 或 `@future` 注释 | +| 2 | `getFeaturedTemplates()` | `templates.ts` | 添加 `@deprecated` 或 `@future` 注释 | + +--- + +## 📊 统计总结 + +| 类别 | 数量 | +|------|------| +| ❌ 完全未使用(建议删除) | 4 | +| ⚠️ 仅内部使用(改为私有) | 4 | +| 🔄 保留但标记 | 2 | +| **总计** | **10** | + +--- + +## 🔍 检查方法 + +使用以下命令检查函数引用: + +```bash +# 检查函数是否被引用(在 routes 和 components 中) +grep -r "函数名" app/routes app/components --include="*.ts" --include="*.tsx" + +# 或使用 Grep 工具 +Grep: pattern="函数名", glob="app/**/*.{ts,tsx}", output_mode="count" +``` + +--- + +## ⚠️ 注意事项 + +1. **删除前再次确认**: 虽然这些函数当前未被引用,但可能在其他分支或未来功能中需要 +2. **Git 历史**: 删除前检查 Git 历史,看是否之前被使用过 +3. **API 兼容性**: 如果这些函数是 API 的一部分,删除可能影响其他项目 +4. **测试代码**: 检查测试文件中是否有引用(本次未扫描测试文件) + +--- + +**维护建议**: 定期运行此检查,避免积累过多死代码。 diff --git a/docs/PostgREST请求模块清单.md b/docs/PostgREST请求模块清单.md new file mode 100644 index 0000000..49f4eea --- /dev/null +++ b/docs/PostgREST请求模块清单.md @@ -0,0 +1,675 @@ +# PostgREST 请求模块完整清单 + +> 本文档记录了项目中所有直接使用 PostgREST 客户端发送请求的模块和函数。 +> +> **更新时间**: 2025-11-24 +> **PostgREST 客户端位置**: `app/api/postgrest-client.ts` + +--- + +## 📚 目录 + +- [API 模块](#api-模块) + - [首页与统计](#1-首页与统计) + - [认证服务](#2-认证服务) + - [文档管理](#3-文档管理) + - [文件上传](#4-文件上传) + - [评查点管理](#5-评查点管理) + - [评查点分组](#6-评查点分组) + - [评查文件审核](#7-评查文件审核) + - [评审结果](#8-评审结果) + - [文档类型](#9-文档类型) + - [入口模块](#10-入口模块) + - [交叉评查](#11-交叉评查) + - [提示词模板](#12-提示词模板) + - [系统配置](#13-系统配置) + - [合同模板](#14-合同模板) +- [路由模块](#路由模块) + - [评查点编辑页面](#15-评查点编辑页面) + +--- + +## API 模块 + +### 1. 首页与统计 + +**文件路径**: `app/api/home/home.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getEntryModules()` | `postgrestGet` | `entry_modules` | 获取用户可访问的入口模块 | +| `getEntryModules()` | `postgrestGet` | `document_types` | 查询入口模块关联的文档类型 | + +#### 主要功能 + +- ✅ 获取首页统计数据(通过后端 API,非 PostgREST) +- ✅ 获取高频错误评查点(通过后端 API) +- ✅ 获取高风险用户(通过后端 API) +- ✅ 获取用户可访问的入口模块(使用 PostgREST) + - 根据用户角色和地区过滤模块 + - 查询模块关联的文档类型 + - 在客户端进行地区启用状态过滤 + +--- + +### 2. 认证服务 + +**文件路径**: `app/api/login/auth.server.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| *待补充* | - | - | 用户会话管理相关功能 | + +#### 主要功能 + +- ✅ 用户身份验证 +- ✅ 会话管理 +- ✅ 登出功能 + +--- + +### 3. 文档管理 + +**文件路径**: `app/api/files/documents.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getDocument()` | `postgrestGet` | `documents` | 获取单个文档详情 | +| `getDocumentWithNoUserId()` | `postgrestGet` | `documents` | 获取文档(无用户ID限制) | +| `getEvaluationResults()` | `postgrestGet` | `evaluation_results` | 获取文档的评查结果 | +| `updateDocument()` | `postgrestPut` | `documents` | 更新文档信息 | +| `deleteDocument()` | `postgrestDelete` | `documents` | 删除文档 | +| `getDocumentHistory()` | `postgrestPost` | `rpc/documents_get_document_history` | 获取文档历史版本(RPC函数) | + +#### 主要功能 + +- ✅ 获取单个文档详情(包含评查结果统计) +- ✅ 获取文档列表(使用后端 API `/admin/versions/documents-list`) +- ✅ 更新文档信息(文档编号、审核状态、备注等) +- ✅ 删除文档(仅限用户自己的文档) +- ✅ 获取文档历史版本列表 +- ✅ 计算文档问题数量(基于评查结果) + +--- + +### 4. 文件上传 + +**文件路径**: `app/api/files/files-upload.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getTodayDocuments()` | `postgrestGet` | `documents` | 获取当天上传的文档列表 | +| `getDocumentTypes()` | `postgrestGet` | `document_types` | 获取文档类型列表 | +| `getDocumentsStatus()` | `postgrestGet` | `documents` | 获取文档状态 | +| `getDocumentsStatus()` | `postgrestGet` | `contract_structure_comparison` | 获取合同附件状态 | + +#### 主要功能 + +- ✅ 获取当天文档列表 + - 根据用户ID和文档类型过滤 + - 从 sessionStorage 读取文档类型 ID +- ✅ 获取文档类型列表(支持动态类型过滤) +- ✅ 获取指定文档的状态(支持主文档和合同附件) +- ✅ 上传文件到服务器(使用后端 API,非 PostgREST) +- ✅ 上传合同模板(使用后端 API) +- ✅ 追加合同附件(使用后端 API) + +--- + +### 5. 评查点管理 + +**文件路径**: `app/api/evaluation_points/rules.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getRulesList()` | `postgrestGet` | `evaluation_points` | 获取评查点列表 | +| `getRulesList()` | `postgrestGet` | `evaluation_point_groups` | 查询规则组(用于类型筛选) | +| `getRule()` | `postgrestGet` | `evaluation_points` | 获取单个评查点详情 | +| `getRule()` | `postgrestGet` | `evaluation_point_groups` | 获取评查点所属分组信息 | +| `createRule()` | `postgrestPost` | `evaluation_points` | 创建新评查点 | +| `updateRule()` | `postgrestPut` | `evaluation_points` | 更新评查点 | +| `deleteRule()` | `postgrestDelete` | `evaluation_points` | 删除评查点 | +| `getRuleTypes()` | `postgrestGet` | `document_types` | 获取文档类型 | +| `getRuleTypes()` | `postgrestGet` | `evaluation_point_groups` | 获取评查点类型 | +| `getRuleGroupsByType()` | `postgrestGet` | `evaluation_point_groups` | 根据类型获取规则组 | +| `getEvaluationPoint()` | `postgrestGet` | `evaluation_points` | 获取评查点数据(编辑用) | +| `getEvaluationPointGroups()` | `postgrestGet` | `evaluation_point_groups` | 获取所有评查点组 | +| `saveEvaluationPoint()` | `postgrestPut` / `postgrestPost` | `evaluation_points` | 保存评查点(新建或更新) | + +#### 主要功能 + +- ✅ 评查点列表查询 + - 支持分页、排序 + - 支持按类型、分组、状态、关键词筛选 + - 支持按地区过滤(省级管理员可见所有) + - 使用 PostgREST 双连接查询获取父子分组 +- ✅ 评查点 CRUD 操作 +- ✅ 评查点复制功能 +- ✅ 评查点编码清洗(移除地区后缀) +- ✅ 评查点分组查询(支持嵌套父子关系) + +--- + +### 6. 评查点分组 + +**文件路径**: `app/api/evaluation_points/rule-groups.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getRuleGroups()` | `postgrestGet` | `evaluation_point_groups` | 获取顶级评查点分组列表 | +| `getChildGroups()` | `postgrestGet` | `evaluation_point_groups` | 获取子分组列表 | +| `getChildGroups()` | `postgrestGet` | `evaluation_points` | 查询子分组的评查点数量 | +| `getAllRuleGroups()` | `postgrestGet` | `evaluation_point_groups` | 获取所有分组(树形结构) | +| `getAllRuleGroups()` | `postgrestGet` | `evaluation_points` | 查询每个子分组的评查点数量 | +| `getRuleGroup()` | `postgrestGet` | `evaluation_point_groups` | 获取单个分组详情 | +| `getRuleGroup()` | `postgrestGet` | `evaluation_points` | 查询分组的评查点数量 | +| `createRuleGroup()` | `postgrestPost` | `evaluation_point_groups` | 创建新分组 | +| `updateRuleGroup()` | `postgrestPut` | `evaluation_point_groups` | 更新分组 | +| `deleteRuleGroup()` | `postgrestDelete` | `evaluation_point_groups` | 删除分组 | +| `deleteEvaluationPointsByGroupId()` | `postgrestDelete` | `evaluation_points` | 删除分组下的所有评查点 | + +#### 主要功能 + +- ✅ 评查点分组 CRUD 操作 +- ✅ 分组树形结构查询(一级分组+二级分组) +- ✅ 查询分组关联的评查点数量 +- ✅ 删除分组时级联删除子分组和评查点 +- ✅ 支持父分组(pid=0)和子分组(pid>0) + +--- + +### 7. 评查文件审核 + +**文件路径**: `app/api/evaluation_points/rules-files.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `updateDocumentAuditStatus()` | `postgrestPut` | `documents` | 更新文档审核状态 | + +#### 主要功能 + +- ✅ 更新文件的审核状态 + - 确保只能更新用户自己的文档 + - 支持状态:待审核(0)、通过(1)、不通过(-1)、警告(-2) + +--- + +### 8. 评审结果 + +**文件路径**: `app/api/evaluation_points/reviews.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getReviewPoints()` | `postgrestGet` | `contract_structure_comparison` | 获取文档附件数据 | +| `getReviewPoints()` | `postgrestGet` | `evaluation_results` | 获取评查结果 | +| `getReviewPoints()` | `postgrestGet` | `evaluation_points` | 获取评查点详情 | +| `getReviewPoints()` | `postgrestGet` | `evaluation_point_groups` | 获取评查点组信息 | +| `getReviewPoints()` | `postgrestGet` | `audit_status` | 获取人工审核状态 | +| `getReviewPoints()` | `postgrestGet` | `cross_scoring_proposals` | 获取交叉评分提案 | +| `updateReviewResult()` | `postgrestGet` | `evaluation_results` | 获取当前评查结果 | +| `updateReviewResult()` | `postgrestPut` | `evaluation_results` | 更新评查结果 | +| `updateReviewResult()` | `postgrestPut` | `audit_status` | 更新审核状态 | +| `updateReviewResult()` | `postgrestPost` | `audit_status` | 创建新审核状态记录 | +| `confirmReviewResults()` | `postgrestPut` | `documents` | 确认评查并更新文档状态 | + +#### 主要功能 + +- ✅ 获取文档的完整评查结果 + - 查询评查点结果(evaluation_results) + - 关联评查点详情(evaluation_points) + - 关联评查点分组(evaluation_point_groups) + - 获取人工审核状态(audit_status) + - 获取合同附件比对结果(contract_structure_comparison) + - 获取交叉评分提案(cross_scoring_proposals) +- ✅ 更新评查结果 + - 修改评查意见和结果 + - 更新或创建人工审核状态 + - 支持重新审核操作 +- ✅ 确认评查结果(将文档审核状态设为通过) + +--- + +### 9. 文档类型 + +**文件路径**: `app/api/document-types/document-types.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getDocumentTypes()` | `postgrestGet` | `document_types` | 获取文档类型列表 | +| `getDocumentType()` | `postgrestGet` | `document_types` | 获取文档类型详情 | +| `createDocumentType()` | `postgrestPost` | `document_types` | 创建文档类型 | +| `updateDocumentType()` | `postgrestPut` | `document_types` | 更新文档类型 | +| `deleteDocumentType()` | `postgrestDelete` | `document_types` | 删除文档类型 | +| `getAllEvaluationPointGroups()` | `postgrestGet` | `evaluation_point_groups` | 获取所有评查点分组 | +| `getParentEvaluationPointGroups()` | `postgrestGet` | `evaluation_point_groups` | 获取父级分组 | +| `getEntryModules()` | `postgrestGet` | `entry_modules` | 获取入口模块列表 | +| `getEvaluationPointGroupsByIds()` | `postgrestGet` | `evaluation_point_groups` | 根据ID获取分组信息 | + +#### 主要功能 + +- ✅ 文档类型 CRUD 操作 +- ✅ 文档类型列表查询 + - 支持分页、排序 + - 支持按名称、分组筛选 + - 支持按文档类型 ID 数组过滤 + - 使用 PostgREST 外键关联查询入口模块 +- ✅ 文档类型关联评查点分组 +- ✅ 文档类型关联入口模块 +- ✅ 文档类型提示词配置(LLM抽取、VLM抽取、评查、总结) + +--- + +### 10. 入口模块 + +**文件路径**: `app/api/entry-modules/entry-modules.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getEntryModules()` | `postgrestGet` | `entry_modules` | 获取入口模块列表 | +| `getEntryModuleById()` | `postgrestGet` | `entry_modules` | 根据ID获取入口模块 | +| `createEntryModule()` | `postgrestPost` | `entry_modules` | 创建入口模块 | +| `updateEntryModule()` | `postgrestPut` | `entry_modules` | 更新入口模块 | +| `deleteEntryModule()` | `postgrestDelete` | `entry_modules` | 删除入口模块 | + +#### 主要功能 + +- ✅ 入口模块 CRUD 操作 +- ✅ 入口模块列表查询 + - 支持分页、排序 + - 支持按名称、地区筛选 + - 支持 JSONB 数组查询(areas字段) +- ✅ 入口模块地区配置管理 + +--- + +### 11. 交叉评查 + +**文件路径**: +- `app/api/cross-checking/cross-files.ts` +- `app/api/cross-checking/cross-file-result.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `updateDocumentAuditStatus()` | `postgrestPut` | `documents` | 更新文档审核状态 | +| `findIsProposer()` | `postgrestGet` | `cross_examination_tasks` | 查找是否是任务发起人 | +| `confirmReviewResults()` | `postgrestPut` | `documents` | 完成评查并更新文档状态 | + +#### 主要功能 + +**cross-files.ts**: +- ✅ 获取用户任务列表(使用后端 API) +- ✅ 获取任务文档列表(使用后端 API) +- ✅ 获取统计数据(使用后端 API) +- ✅ 更新文档审核状态(使用 PostgREST) + +**cross-file-result.ts**: +- ✅ 提交交叉评查意见(使用后端 API) +- ✅ 获取交叉评查意见列表(使用后端 API) +- ✅ 执行意见操作(赞同、反对、撤销,使用后端 API) +- ✅ 完成评查(使用 PostgREST 更新文档状态) +- ✅ 检查提案投票状态(使用后端 API) +- ✅ 查找是否是任务发起人(使用 PostgREST) + +--- + +### 12. 提示词模板 + +**文件路径**: `app/api/prompts/prompts.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getPromptTemplates()` | `postgrestGet` | `prompt_templates` | 获取提示词模板列表 | +| `getPromptTemplate()` | `postgrestGet` | `prompt_templates` | 获取模板详情 | +| `createPromptTemplate()` | `postgrestPost` | `prompt_templates` | 创建提示词模板 | +| `updatePromptTemplate()` | `postgrestPut` | `prompt_templates` | 更新提示词模板 | +| `deletePromptTemplate()` | `postgrestDelete` | `prompt_templates` | 删除提示词模板 | +| `getPromptTemplateOptions()` | `postgrestGet` | `prompt_templates` | 获取模板选项列表 | + +#### 主要功能 + +- ✅ 提示词模板 CRUD 操作 +- ✅ 提示词模板列表查询 + - 支持分页、排序 + - 支持按名称、类型、状态筛选 + - 使用 PostgREST 外键关联查询创建者信息(sso_users表) +- ✅ 提示词模板类型 + - LLM抽取(LLM_Extraction) + - VLM抽取(VLM_Extraction) + - 评查(Evaluation) + - 总结(Summary) + - 通用(Common) +- ✅ 获取指定类型的模板选项(用于下拉选择) + +--- + +### 13. 系统配置 + +**文件路径**: `app/api/system_setting/config-lists.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getConfigLists()` | `postgrestGet` | `configurations` | 获取配置列表 | +| `getConfigOptions()` | `postgrestGet` | `configurations` | 获取配置类型和环境选项 | +| `getConfigDetail()` | `postgrestGet` | `configurations` | 获取配置详情 | +| `createConfig()` | `postgrestPost` | `configurations` | 创建配置 | +| `updateConfig()` | `postgrestPut` | `configurations` | 更新配置 | +| `updateConfigStatus()` | `postgrestPut` | `configurations` | 更新配置状态 | + +#### 主要功能 + +- ✅ 系统配置 CRUD 操作 +- ✅ 配置列表查询 + - 支持分页、排序 + - 支持按名称、类型、环境、状态筛选 +- ✅ 配置类型和环境动态选项查询 +- ✅ 配置状态管理(启用/禁用) + +--- + +### 14. 合同模板 + +**文件路径**: `app/api/contract-template/templates.ts` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `getContractCategories()` | `postgrestGet` | `contract_categories` | 获取合同分类列表 | +| `getContractCategoriesWithCount()` | `postgrestGet` | `contract_categories` | 获取分类及模板数量 | +| `getContractCategoriesWithCount()` | `postgrestGet` | `contract_templates` | 统计每个分类的模板数量 | +| `getContractTemplates()` | `postgrestGet` | `contract_categories` | 查询分类(用于关键词搜索) | +| `getContractTemplates()` | `postgrestGet` | `contract_templates` | 获取合同模板列表 | +| `getContractTemplate()` | `postgrestGet` | `contract_templates` | 获取单个模板详情 | +| `getFeaturedTemplates()` | `postgrestGet` | `contract_templates` | 获取推荐模板 | + +#### 主要功能 + +- ✅ 合同分类管理 + - 获取所有分类 + - 统计每个分类的模板数量 +- ✅ 合同模板查询 + - 支持分页、排序 + - 支持按分类、格式、推荐状态筛选 + - 支持关键词搜索(标题、描述、模板编码、分类名) + - 使用 PostgREST 外键关联查询分类信息 +- ✅ 获取推荐模板列表 +- ✅ 智能搜索功能 + +--- + +## 路由模块 + +### 15. 评查点编辑页面 + +**文件路径**: `app/routes/rules.new.tsx` + +#### 使用的 PostgREST 函数 + +| 函数名 | 操作 | 表名 | 说明 | +|--------|------|------|------| +| `fetchEvaluationPoint()` | `postgrestGet` | `evaluation_points` | 获取评查点数据(编辑模式) | +| `fetchEvaluationPointGroups()` | `postgrestGet` | `evaluation_point_groups` | 获取评查点组数据 | +| `handleSave()` | `postgrestPut` | `evaluation_points` | 更新评查点(编辑模式) | +| `handleSave()` | `postgrestPost` | `evaluation_points` | 创建评查点(新建模式) | + +#### 主要功能 + +- ✅ 评查点创建/编辑/复制页面 +- ✅ 评查点数据加载(支持编辑和复制模式) +- ✅ 评查点分组数据加载(用于下拉选择) +- ✅ 评查点保存(新建或更新) + - 基本信息设置 + - 抽取设置(LLM、VLM、Regex) + - 评查设置(规则配置、消息配置) +- ✅ 评查点编码清洗(移除地区后缀) +- ✅ 表单验证(必填字段、规则完整性) + +--- + +## 📊 统计信息 + +### 模块统计 + +| 类型 | 数量 | +|------|------| +| API 模块 | 14 | +| 路由模块 | 1 | +| 总计 | 15 | + +### 数据库表统计 + +| 表名 | 操作频率 | 主要操作 | +|------|---------|---------| +| `evaluation_points` | 🔥🔥🔥🔥🔥 | GET, POST, PUT, DELETE | +| `evaluation_point_groups` | 🔥🔥🔥🔥 | GET, POST, PUT, DELETE | +| `documents` | 🔥🔥🔥🔥 | GET, PUT, DELETE | +| `document_types` | 🔥🔥🔥 | GET, POST, PUT, DELETE | +| `evaluation_results` | 🔥🔥🔥 | GET, PUT | +| `prompt_templates` | 🔥🔥🔥 | GET, POST, PUT, DELETE | +| `entry_modules` | 🔥🔥 | GET, POST, PUT, DELETE | +| `contract_templates` | 🔥🔥 | GET | +| `contract_categories` | 🔥🔥 | GET | +| `configurations` | 🔥 | GET, POST, PUT | +| `audit_status` | 🔥 | GET, PUT, POST | +| `cross_examination_tasks` | 🔥 | GET | +| `cross_scoring_proposals` | 🔥 | GET | +| `contract_structure_comparison` | 🔥 | GET | + +### PostgREST 操作统计 + +| 操作 | 使用次数 | +|------|---------| +| `postgrestGet` | 🔥🔥🔥🔥🔥 | +| `postgrestPost` | 🔥🔥🔥 | +| `postgrestPut` | 🔥🔥🔥🔥 | +| `postgrestDelete` | 🔥🔥 | + +--- + +## 🔧 PostgREST 使用特性 + +### 1. 资源嵌入(Resource Embedding) + +**使用示例**: +```typescript +// 查询文档类型并关联入口模块 +select: ` + id, name, description, + entry_modules!fk_document_types_entry_module(id, name) +` + +// 查询提示词模板并关联创建者 +select: ` + id, template_name, template_type, + sso_users!created_by(username) +` + +// 查询评查点并关联父子分组 +select: ` + id, code, name, + child_group:evaluation_point_groups!fk_evaluation_points_group(id,name), + parent_group:evaluation_point_groups!fk_evaluation_points_parent_group(id,name) +` +``` + +**使用场景**: +- 文档类型查询(关联入口模块) +- 提示词模板查询(关联创建者信息) +- 评查点查询(关联父子分组) +- 合同模板查询(关联分类信息) + +### 2. 过滤查询(Filtering) + +**使用示例**: +```typescript +// 精确匹配 +filter: { 'id': 'eq.123' } + +// 模糊搜索 +filter: { 'name': 'ilike.*关键词*' } + +// 数组包含(in) +filter: { 'id': 'in.(1,2,3)' } + +// JSONB 数组包含(cs) +filter: { 'areas': 'cs.{"梅州"}' } + +// 大于等于 +filter: { 'status': 'gte.0' } + +// NULL 判断 +filter: { 'deleted_at': 'is.null' } +``` + +### 3. OR 条件查询 + +**使用示例**: +```typescript +// 多字段模糊搜索 +or: [ + { name: 'ilike.*关键词*' }, + { code: 'ilike.*关键词*' } +] + +// 或者使用字符串格式 +or: `(title.ilike.*关键词*,description.ilike.*关键词*)` +``` + +### 4. 分页与排序 + +**使用示例**: +```typescript +// 分页 +limit: 10, +offset: (page - 1) * 10, + +// 排序 +order: 'created_at.desc', +order: 'sort_order.asc,name.asc', + +// 获取总数 +headers: { + 'Prefer': 'count=exact' +} +``` + +### 5. RPC 函数调用 + +**使用示例**: +```typescript +// 调用存储过程 +await postgrestPost( + 'rpc/documents_get_document_history', + { + p_document_name: documentName, + p_user_id: parseInt(userId, 10), + p_exclude_id: excludeId + }, + token +); +``` + +--- + +## ⚠️ 注意事项 + +### 1. 数据提取 + +所有模块都使用统一的 `extractApiData()` 函数处理 API 响应: +```typescript +function extractApiData(responseData: unknown): T | null { + if (!responseData) return null; + + // 格式1: { code: number, msg: string, data: T } + if (typeof responseData === 'object' && responseData !== null && + 'code' in responseData && 'data' in responseData) { + return (responseData as { data: T }).data; + } + + // 格式2: 直接是数据对象 + return responseData as T; +} +``` + +### 2. JWT 认证 + +所有 PostgREST 请求都支持 JWT token 参数: +```typescript +const params: PostgrestParams = { + // ... 其他参数 + token: frontendJWT +}; +``` + +### 3. 错误处理 + +统一的错误处理模式: +```typescript +const response = await postgrestGet(...); + +if (response.error) { + return { error: response.error, status: response.status }; +} + +const data = extractApiData(response.data); +if (!data) { + return { error: '获取数据失败', status: 500 }; +} +``` + +### 4. 用户权限控制 + +- 大多数更新/删除操作都会检查 `user_id` 确保用户只能操作自己的数据 +- 省级管理员(`provincial_admin`)可以查看所有地区的数据 +- 普通用户只能查看自己地区的数据 + +--- + +## 🔄 混合使用情况 + +部分模块同时使用了 PostgREST 和后端 API: + +| 模块 | PostgREST | 后端 API | +|------|-----------|---------| +| 文档管理 | ✅ 单个文档查询、更新、删除 | ✅ 文档列表查询 | +| 首页统计 | ✅ 入口模块查询 | ✅ 统计数据查询 | +| 文件上传 | ✅ 文档类型、状态查询 | ✅ 文件上传操作 | +| 交叉评查 | ✅ 文档状态更新 | ✅ 任务和意见管理 | + +--- + +## 📝 更新记录 + +| 日期 | 说明 | +|------|------| +| 2025-11-24 | 初始版本,整理完整的 PostgREST 使用清单 | + +--- + +**文档维护**: 当添加新的 PostgREST 请求时,请及时更新此文档。 diff --git a/docs/删除操作延迟确认功能实施文档.md b/docs/删除操作延迟确认功能实施文档.md new file mode 100644 index 0000000..bc9845d --- /dev/null +++ b/docs/删除操作延迟确认功能实施文档.md @@ -0,0 +1,557 @@ +# 删除操作延迟确认功能实施文档 + +> **实施时间**: 2025-11-25 +> **功能描述**: 为所有删除操作添加4秒延迟确认功能,防止误删除操作 + +--- + +## 📋 目录 + +- [功能概述](#功能概述) +- [技术实现](#技术实现) +- [已更新的文件](#已更新的文件) +- [使用示例](#使用示例) +- [测试验证](#测试验证) + +--- + +## 功能概述 + +### 需求背景 + +为了防止用户误操作导致数据被删除,所有删除操作都需要: +1. 显示确认弹窗提示 +2. 确认按钮在4秒倒计时结束后才能点击 +3. 倒计时期间按钮显示剩余秒数 + +### 核心功能 + +- **延迟确认**: 确认按钮在4秒倒计时后才可点击 +- **倒计时显示**: 按钮文本显示 "删除 (4s)" → "删除 (3s)" → ... → "删除" +- **视觉反馈**: 倒计时期间按钮呈半透明状态且鼠标样式为禁用 +- **统一体验**: 所有删除操作使用相同的确认流程 + +--- + +## 技术实现 + +### 1. MessageModal 组件增强 + +**文件**: `app/components/ui/MessageModal.tsx` + +#### 新增 Props + +```typescript +interface MessageModalProps { + // ... 现有属性 + // 确认按钮延迟时间(秒)- 用于危险操作(如删除) + confirmDelay?: number; +} +``` + +#### 状态管理 + +```typescript +const [remainingSeconds, setRemainingSeconds] = useState(confirmDelay); +``` + +#### 倒计时逻辑 + +```typescript +useEffect(() => { + if (isOpen && confirmDelay > 0) { + setRemainingSeconds(confirmDelay); + const timer = setInterval(() => { + setRemainingSeconds((prev) => { + if (prev <= 1) { + clearInterval(timer); + return 0; + } + return prev - 1; + }); + }, 1000); + return () => clearInterval(timer); + } +}, [isOpen, confirmDelay]); +``` + +#### 按钮渲染 + +```typescript + +``` + +--- + +## 已更新的文件 + +### 1. 文档管理模块 (documents.list.tsx) + +**文件路径**: `app/routes/documents.list.tsx` + +#### 更新位置 1: 单个文档删除 (Line 580-596) + +```typescript +messageService.show({ + title: "确认删除", + message: `确定要删除文档"${name}"吗?`, + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: () => { + // 删除逻辑 + } +}); +``` + +#### 更新位置 2: 批量删除文档 (Line 617-642) + +```typescript +messageService.show({ + title: "确认批量删除", + message: `确认删除选中的 ${selectedRowKeys.length} 个文档?`, + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: () => { + // 批量删除逻辑 + } +}); +``` + +--- + +### 2. 评查点管理模块 (rules.list.tsx) + +**文件路径**: `app/routes/rules.list.tsx` + +#### 更新位置 1: 单个评查点删除 (Line 526-542) + +```typescript +messageService.show({ + title: "确认删除", + message: `确认删除评查点【${rule.name}】吗?`, + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: () => { + // 删除逻辑 + } +}); +``` + +#### 更新位置 2: 批量删除评查点 (Line 603-634) + +```typescript +messageService.show({ + title: "确认批量删除", + message: `确定要删除选中的 ${selectedIds.length} 个评查点吗?此操作不可恢复。`, + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: async () => { + // 批量删除逻辑 + } +}); +``` + +--- + +### 3. 评查点分组管理模块 (rule-groups._index.tsx) + +**文件路径**: `app/routes/rule-groups._index.tsx` + +#### 导入更新 + +```typescript +// 原代码 +import { toastService } from "~/components/ui"; + +// 新代码 +import { toastService, messageService } from "~/components/ui"; +``` + +#### 更新位置 1: 单个分组删除 (Line 233-275) + +**原代码** (使用 `confirm()`): +```typescript +if (confirm("确定要删除该分组吗?此操作将同时删除该分组下的所有评查点,且不可恢复。")) { + // 删除逻辑 +} +``` + +**新代码** (使用 `messageService`): +```typescript +messageService.show({ + title: "确认删除", + message: "确定要删除该分组吗?此操作将同时删除该分组下的所有评查点,且不可恢复。", + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: async () => { + // 删除逻辑 + } +}); +``` + +#### 更新位置 2: 批量删除分组 (Line 307-328) + +**原代码** (使用 `confirm()`): +```typescript +if (!confirm(`确定要删除选中的 ${selectedIds.length} 个分组吗?此操作不可恢复。`)) { + return; +} +``` + +**新代码** (使用 `messageService`): +```typescript +messageService.show({ + title: "确认批量删除", + message: `确定要删除选中的 ${selectedIds.length} 个分组吗?此操作不可恢复。`, + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: async () => { + // 删除逻辑 + } +}); +``` + +--- + +### 4. 提示词模板管理模块 (prompts._index.tsx) + +**文件路径**: `app/routes/prompts._index.tsx` + +#### 导入更新 + +```typescript +// 原代码 +import { toastService } from "~/components/ui"; + +// 新代码 +import { toastService, messageService } from "~/components/ui"; +``` + +#### 更新位置: 删除模板 (Line 220-234) + +**原代码** (使用 `confirm()`): +```typescript +if (confirm('确定要删除该模板吗?删除后无法恢复。')) { + const formData = new FormData(); + formData.append('id', id); + formData.append('intent', 'delete'); + fetcher.submit(formData, { method: 'post' }); +} +``` + +**新代码** (使用 `messageService`): +```typescript +messageService.show({ + title: "确认删除", + message: "确定要删除该模板吗?删除后无法恢复。", + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: () => { + const formData = new FormData(); + formData.append('id', id); + formData.append('intent', 'delete'); + fetcher.submit(formData, { method: 'post' }); + } +}); +``` + +--- + +### 5. 入口模块管理模块 (entry-modules._index.tsx) + +**文件路径**: `app/routes/entry-modules._index.tsx` + +#### 导入更新 + +```typescript +// 原代码 +import { toastService } from "~/components/ui/Toast"; + +// 新代码 +import { toastService } from "~/components/ui/Toast"; +import { messageService } from "~/components/ui/MessageModal"; +``` + +#### 更新位置: 删除入口模块 (Line 215-250) + +**原代码** (使用 `confirm()`): +```typescript +if (confirm('确定要删除该入口模块吗?此操作不可撤销。')) { + setIsDeleting(true); + // 删除逻辑 +} +``` + +**新代码** (使用 `messageService`): +```typescript +messageService.show({ + title: "确认删除", + message: "确定要删除该入口模块吗?此操作不可撤销。", + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: async () => { + setIsDeleting(true); + // 删除逻辑 + } +}); +``` + +--- + +### 6. 文档类型管理模块 (document-types._index.tsx) + +**文件路径**: `app/routes/document-types._index.tsx` + +#### 导入更新 + +```typescript +// 原代码 +import { toastService } from "~/components/ui/Toast"; + +// 新代码 +import { toastService } from "~/components/ui/Toast"; +import { messageService } from "~/components/ui/MessageModal"; +``` + +#### 更新位置: 删除文档类型 (Line 204-239) + +**原代码** (使用 `confirm()` 和 `alert()`): +```typescript +if (confirm('确定要删除该文档类型吗?此操作不会影响关联的评查点分组,但可能会影响使用该类型的文档评查。')) { + setIsDeleting(true); + // 删除逻辑 + if (result.success) { + alert('删除成功!'); + } else { + alert(`删除失败: ${result.error || '未知错误'}`); + } +} +``` + +**新代码** (使用 `messageService` 和 `toastService`): +```typescript +messageService.show({ + title: "确认删除", + message: "确定要删除该文档类型吗?此操作不会影响关联的评查点分组,但可能会影响使用该类型的文档评查。", + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // ✅ 新增 + onConfirm: async () => { + setIsDeleting(true); + // 删除逻辑 + if (result.success) { + toastService.success('删除成功!'); + } else { + toastService.error(`删除失败: ${result.error || '未知错误'}`); + } + } +}); +``` + +--- + +## 使用示例 + +### 基本用法 + +```typescript +import { messageService } from "~/components/ui/MessageModal"; + +const handleDelete = (id: string, name: string) => { + messageService.show({ + title: "确认删除", + message: `确定要删除"${name}"吗?`, + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // 4秒延迟 + onConfirm: () => { + // 执行删除操作 + deleteItem(id); + } + }); +}; +``` + +### 批量删除示例 + +```typescript +const handleBatchDelete = () => { + if (selectedIds.length === 0) { + toastService.error('请至少选择一项'); + return; + } + + messageService.show({ + title: "确认批量删除", + message: `确定要删除选中的 ${selectedIds.length} 项吗?此操作不可恢复。`, + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, + onConfirm: async () => { + // 执行批量删除 + await batchDeleteItems(selectedIds); + } + }); +}; +``` + +--- + +## 测试验证 + +### 测试清单 + +#### 1. 单个删除操作测试 + +- [ ] 文档删除 (`/documents`) +- [ ] 评查点删除 (`/rules`) +- [ ] 评查点分组删除 (`/rule-groups`) +- [ ] 提示词模板删除 (`/prompts`) +- [ ] 入口模块删除 (`/entry-modules`) +- [ ] 文档类型删除 (`/document-types`) + +#### 2. 批量删除操作测试 + +- [ ] 批量删除文档 +- [ ] 批量删除评查点 +- [ ] 批量删除评查点分组 + +### 测试要点 + +1. **倒计时功能**: + - ✅ 弹窗打开后,确认按钮显示 "删除 (4s)" + - ✅ 每秒递减: "删除 (3s)" → "删除 (2s)" → "删除 (1s)" → "删除" + - ✅ 倒计时期间按钮不可点击 + +2. **视觉反馈**: + - ✅ 倒计时期间按钮半透明 (opacity: 0.5) + - ✅ 鼠标悬停显示禁用光标 (cursor: not-allowed) + - ✅ 倒计时结束后按钮恢复正常样式 + +3. **交互行为**: + - ✅ 点击取消按钮可以立即关闭弹窗 + - ✅ 点击遮罩层可以立即关闭弹窗 + - ✅ 按 ESC 键可以立即关闭弹窗 + - ✅ 倒计时结束后点击确认执行删除操作 + +4. **边界情况**: + - ✅ 快速打开/关闭弹窗不会导致计时器泄漏 + - ✅ 多次打开弹窗,倒计时每次都重新开始 + +### 预期行为 + +**正常流程**: +``` +用户点击删除 → 弹窗显示 → 确认按钮显示 "删除 (4s)" +→ 倒计时 3秒 → 倒计时 2秒 → 倒计时 1秒 → "删除" 可点击 +→ 用户点击确认 → 执行删除 → 显示成功提示 +``` + +**取消流程**: +``` +用户点击删除 → 弹窗显示 → 倒计时进行中 +→ 用户点击取消/遮罩层/ESC键 → 弹窗关闭 → 不执行删除 +``` + +--- + +## 📊 统计总结 + +### 更新统计 + +| 模块 | 文件名 | 删除操作数 | 导入变更 | 替换 confirm() | +|------|--------|------------|----------|----------------| +| 文档管理 | documents.list.tsx | 2 | - | - | +| 评查点管理 | rules.list.tsx | 2 | - | - | +| 评查点分组 | rule-groups._index.tsx | 2 | ✅ | ✅ | +| 提示词模板 | prompts._index.tsx | 1 | ✅ | ✅ | +| 入口模块 | entry-modules._index.tsx | 1 | ✅ | ✅ | +| 文档类型 | document-types._index.tsx | 1 | ✅ | ✅ | +| **总计** | **6 个文件** | **9 个操作** | **4 个文件** | **4 个文件** | + +### 代码改动 + +- **新增代码**: MessageModal 组件增强 (~50 行) +- **修改代码**: 9 个删除操作函数 (~200 行) +- **导入变更**: 4 个文件添加 messageService 导入 +- **替换操作**: 4 个文件从 `confirm()` 迁移到 `messageService.show()` + +--- + +## 🎯 后续维护 + +### 新增删除操作开发规范 + +当开发人员需要添加新的删除功能时,请遵循以下规范: + +```typescript +// ✅ 正确做法 +import { messageService } from "~/components/ui/MessageModal"; + +const handleDelete = (id: string) => { + messageService.show({ + title: "确认删除", + message: "确定要删除该项吗?", + type: "warning", + confirmText: "删除", + cancelText: "取消", + confirmDelay: 4, // 必须添加 + onConfirm: () => { + // 删除逻辑 + } + }); +}; + +// ❌ 错误做法 +const handleDelete = (id: string) => { + if (confirm("确定要删除吗?")) { // 不要使用原生 confirm + // 删除逻辑 + } +}; +``` + +### Code Review 检查点 + +在代码审查时,请确认: +1. ✅ 所有删除操作都使用 `messageService.show()` +2. ✅ 所有删除确认都包含 `confirmDelay: 4` +3. ✅ 没有使用原生 `confirm()` 或 `alert()` +4. ✅ 导入了正确的 `messageService` + +--- + +## 📞 联系支持 + +如遇到问题,请联系开发团队。 + +**文档维护人**: Claude Code +**最后更新**: 2025-11-25