import { postgrestGet, postgrestPost, postgrestPut, postgrestDelete, type PostgrestParams } from '../postgrest-client'; import { formatDate } from '../../utils'; /** * 从不同格式的 API 响应中提取数据 * @param responseData API 响应数据 * @returns 提取后的数据或 null */ 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 && (responseData as { data: unknown }).data) { return (responseData as { data: T }).data; } // 格式2: 直接是数据对象 return responseData as T; } /** * 评查点列表查询参数 */ export interface RulesQueryParams { page?: number; pageSize?: number; ruleType?: string; // 评查点类型ID groupId?: string; // 规则组ID isActive?: boolean; keyword?: string; area?: string; // 地区过滤 orderBy?: string; orderDirection?: 'asc' | 'desc'; userRole?: string; // 用户角色 token?: string; // JWT token } /** * 评查点列表响应数据 */ export interface RulesListResponse { rules: Rule[]; totalCount: number; } /** * API返回的评查点详情 */ export interface ApiRule { id: number; code: string; name: string; area?: string; // 地区 evaluation_point_groups_id: number | null; risk: string; description: string; is_enabled: boolean; evaluation_point_groups?: { first_name: string; second_name: string; }; // 🆕 PostgREST 双连接查询返回的字段 child_group?: { id: number; name: string; } | null; parent_group?: { id: number; name: string; } | null; references_laws: Record; extraction_config: { type: string; fields: string[]; prompt_setting?: { type: string; template: string; }; }; evaluation_config: { rules: Array<{ id: string; type: string; config: Record; }>; logicType: string; }; pass_message: string; fail_message: string; suggestion_message: string; suggestion_message_type: string; post_action: string; action_config: string; created_at: string; updated_at: string; } /** * 评查点详情(前端模型) */ export interface Rule { id: string; code: string; name: string; ruleType: string; groupId: string; groupName: string; priority: string; description: string; isActive: boolean; createdAt: string; updatedAt: string; } /** * 映射API返回的评查点数据到前端模型 * @param apiRule API返回的评查点数据 * @returns 前端评查点模型 */ function mapApiRuleToFrontendModel(apiRule: ApiRule): Rule { // 风险等级映射到优先级 const priorityMap: Record = { '高': 'high', '中': 'medium', '低': 'low' }; // 🆕 优先使用 PostgREST 双连接查询返回的数据 let ruleType = ''; let groupName = ''; let groupId = ''; if (apiRule.child_group || apiRule.parent_group) { // 有 PostgREST 双连接查询数据(外键约束方式) groupId = apiRule.child_group?.id.toString() || ''; groupName = apiRule.child_group?.name || ''; ruleType = apiRule.parent_group?.name || ''; } else if (apiRule.evaluation_point_groups) { // 兼容旧的查询方式(RPC 函数或手动拼接) const isGroupIdEmpty = !apiRule.evaluation_point_groups_id; ruleType = isGroupIdEmpty ? '' : (apiRule.evaluation_point_groups.first_name || ''); groupName = isGroupIdEmpty ? '' : (apiRule.evaluation_point_groups.second_name || `${apiRule.evaluation_point_groups_id}`); groupId = isGroupIdEmpty ? '' : apiRule.evaluation_point_groups_id?.toString() || ''; } else { // 没有任何分组信息 const isGroupIdEmpty = !apiRule.evaluation_point_groups_id; groupId = isGroupIdEmpty ? '' : apiRule.evaluation_point_groups_id?.toString() || ''; } // 🔑 清洗评查点编码:移除最后一个 '--' 及其后面的字符 // 例如:'code-mis--mz' --> 'code-mis', 'code-mbs--alsi--gz' --> 'code-mbs--alsi' let cleanedCode = apiRule.code || ''; const lastDoubleHyphenIndex = cleanedCode.lastIndexOf('--'); if (lastDoubleHyphenIndex !== -1) { cleanedCode = cleanedCode.substring(0, lastDoubleHyphenIndex); } return { id: apiRule.id ? apiRule.id.toString() : '', code: cleanedCode, name: apiRule.name || '', ruleType: ruleType, groupId: groupId, groupName: groupName, priority: priorityMap[apiRule.risk] || 'medium', description: apiRule.description || '', isActive: apiRule.is_enabled === undefined ? false : apiRule.is_enabled, createdAt: apiRule.created_at, updatedAt: apiRule.updated_at }; } /** * 获取评查点列表 * @param params 查询参数 * @returns 评查点列表、总数和评查点组 */ export async function getRulesList(params: RulesQueryParams): Promise<{data: RulesListResponse; error?: never} | {data?: never; error: string; status?: number}> { try { // 解构并设置默认值 const { page = 1, pageSize = 10, ruleType, groupId, isActive, keyword, area, orderBy = 'created_at', orderDirection = 'desc', userRole, token } = params; // 🔑 如果没有传递 userRole,尝试从 localStorage 中获取 let user_role = '' if (!userRole && typeof window !== 'undefined' && window.localStorage) { try { const userInfoStr = localStorage.getItem('user_info'); if (userInfoStr) { const userInfo = JSON.parse(userInfoStr); user_role = userInfo.user_role || userInfo.userRole; // console.log('📋 [getRulesList] 从 localStorage 获取用户角色:', userRole); } } catch (error) { console.error('❌ [getRulesList] 解析 localStorage 用户信息失败:', error); } } // 构建PostgrestParams参数 const postgrestParams: PostgrestParams = { // 🆕 使用 PostgREST 双连接查询(直接连接父子分组) // child_group: 通过 evaluation_point_groups_id 获取子分组(所属规则组) // parent_group: 通过 evaluation_point_groups_pid 直接获取父分组(评查点类型) // ⚠️ 重要:使用 .replace() 移除换行符,PostgREST 的 select 参数不支持多行字符串 select: ` id, code, name, area, evaluation_point_groups_id, evaluation_point_groups_pid, risk, description, is_enabled, created_at, updated_at, child_group:evaluation_point_groups!fk_evaluation_points_group(id,name), parent_group:evaluation_point_groups!fk_evaluation_points_parent_group(id,name) `.replace(/\s+/g, ' ').trim(), // 设置分页 limit: pageSize, offset: (page - 1) * pageSize, // 设置排序 order: `${orderBy}.${orderDirection}`, // 构建过滤条件 filter: {}, // 添加额外头部,用于获取总记录数 headers: { 'Prefer': 'count=exact' }, token }; // 添加精确匹配过滤:规则组ID if (groupId) { postgrestParams.filter!['evaluation_point_groups_id'] = `eq.${groupId}`; } if (isActive !== undefined) { postgrestParams.filter!['is_enabled'] = `eq.${isActive}`; } // 🔑 添加地区过滤 if (user_role == 'provincial_admin') { postgrestParams.filter!['area'] = `eq.省级`; }else{ postgrestParams.filter!['area'] = `eq.${area}`; } // 如果指定了评查点类型ID,需要先查询该类型下的所有规则组ID if (ruleType) { try { // 🔑 检查是否为多个类型(逗号分隔) const isMultipleTypes = ruleType.includes(','); // 先获取该类型(或多个类型)下的所有规则组 const groupsParams: PostgrestParams = { select: 'id', filter: { // 如果是多个类型,使用 in.(type1,type2),否则使用 eq.type 'pid': isMultipleTypes ? `in.(${ruleType})` : `eq.${ruleType}` }, token }; const groupsResponse = await postgrestGet<{code: number; msg: string; data: Array<{id: number}>}>('evaluation_point_groups', groupsParams); if (groupsResponse.error) { console.error('获取规则组列表失败:', groupsResponse.error); } else { let groupIds: number[] = []; // 处理不同API响应格式 if (groupsResponse.data && 'code' in groupsResponse.data && groupsResponse.data.data) { if (Array.isArray(groupsResponse.data.data) && groupsResponse.data.data.length > 0) { groupIds = groupsResponse.data.data.map(group => group.id); } } else if (Array.isArray(groupsResponse.data) && groupsResponse.data.length > 0) { groupIds = groupsResponse.data.map(group => group.id); } // 使用in过滤条件,如果找到规则组 if (groupIds.length > 0) { postgrestParams.filter!['evaluation_point_groups_id'] = `in.(${groupIds.join(',')})`; } if (groupId) { postgrestParams.filter!['evaluation_point_groups_id'] = `eq.${groupId}`; } } } catch (error) { console.error('获取规则组ID出错:', error); // 错误不中断流程,继续使用其他筛选条件 } } // 添加模糊搜索 if (keyword) { // 使用PostgREST的or条件查询 // 同时搜索name和code字段 postgrestParams.or = [ { name: `ilike.*${keyword}*` }, { code: `ilike.*${keyword}*` } ]; } // 使用postgrestGet发送请求 const response = await postgrestGet<{code: number; msg: string; data: ApiRule[]}>('evaluation_points', postgrestParams); // 检查是否有错误响应 if (response.error) { return { error: response.error, status: response.status }; } // 处理不同的API响应格式 let apiRules: ApiRule[] = []; let totalCount = 0; // 9000端口格式 {code: number, msg: string, data: ApiRule[]} if (response.data && 'code' in response.data && response.data.data) { if (Array.isArray(response.data.data)) { apiRules = response.data.data; } else { return { error: '接口返回数据格式不正确', status: 500 }; } } // 3000端口格式 ApiRule[] else if (Array.isArray(response.data)) { apiRules = response.data; } // 不支持的格式 else { return { error: '接口返回数据格式不正确', status: 500 }; } // 尝试从响应中获取总数 let rangeHeader = ''; // 安全地检查头信息是否存在 if (response && 'headers' in response && response.headers && typeof response.headers === 'object') { rangeHeader = (response.headers as Record)['content-range'] || ''; } if (rangeHeader) { // 例如 Content-Range: 0-9/42 表示总共有 42 条记录 const total = rangeHeader.split('/')[1]; if (total !== '*') { // '*' 表示未知总数 totalCount = parseInt(total, 10); } } else { // 如果没有响应头,则使用当前返回的数据长度作为默认值 totalCount = apiRules.length; } // 🆕 使用嵌套查询后,不再需要手动查询分组信息 // PostgREST 的嵌套 select 已经自动关联了分组数据 console.log('📋 [getRulesList] 使用 PostgREST 嵌套查询获取评查点数据'); // 将API返回的数据映射到前端模型 const mappedRules = apiRules.map(apiRule => { const rule = mapApiRuleToFrontendModel(apiRule); // 格式化日期字段 rule.createdAt = formatDate(rule.createdAt); rule.updatedAt = formatDate(rule.updatedAt); return rule; }); // 返回结果 return { data: { rules: mappedRules, totalCount } }; } catch (error) { console.error('获取评查点列表出错:', error); return { error: error instanceof Error ? error.message : '获取评查点列表失败', status: 500 }; } } /** * 获取单个评查点详情 * @param id 评查点ID * @param token JWT token (可选) * @returns 评查点详情 */ export async function getRule(id: string, token?: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> { try { // 使用postgrestGet获取单个评查点数据 const postgrestParams: PostgrestParams = { // 使用PostgREST资源嵌入语法获取关联数据 select: ` id, code, name, evaluation_point_groups_id, risk, description, is_enabled, references_laws, extraction_config, evaluation_config, pass_message, fail_message, suggestion_message, suggestion_message_type, post_action, action_config, created_at, updated_at `, token }; // 获取评查点详情 const response = await postgrestGet<{code: number; msg: string; data: ApiRule}>(`evaluation_points/${id}`, postgrestParams); // 检查是否有错误响应 if (response.error) { return { error: response.error, status: response.status }; } // 确保响应数据存在且符合预期格式 if (!response.data || !response.data.data) { return { error: '接口返回数据格式不正确', status: 500 }; } const apiRule = response.data.data; // 获取分组信息 try { if (apiRule.evaluation_point_groups_id) { const groupParams: PostgrestParams = { select: 'id,name', filter: { 'id': `eq.${apiRule.evaluation_point_groups_id}` }, token }; // 查询评查点分组 const groupResponse = await postgrestGet<{code: number; msg: string; data: {id: number; name: string}[]}>('evaluation_point_groups', groupParams); if (groupResponse.data?.data && groupResponse.data.data.length > 0) { // 将分组信息添加到评查点数据中 const group = groupResponse.data.data[0]; apiRule.evaluation_point_groups = { first_name: group.name, second_name: group.name }; } } } catch (error) { console.error('获取分组信息失败:', error); // 忽略错误,使用默认分组名 } // 将API返回的数据映射到前端模型 const rule = mapApiRuleToFrontendModel(apiRule); // 格式化日期字段 rule.createdAt = formatDate(rule.createdAt); rule.updatedAt = formatDate(rule.updatedAt); return { data: rule }; } catch (error) { console.error('获取评查点详情出错:', error); return { error: error instanceof Error ? error.message : '获取评查点详情失败', status: 500 }; } } /** * 创建新评查点 * @param ruleData 评查点数据 * @param token JWT token (可选) * @returns 创建的评查点 */ export async function createRule(ruleData: Omit, token?: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> { try { // 将前端模型转换为API接受的格式 const apiRuleData = { code: ruleData.code, name: ruleData.name, evaluation_point_groups_id: parseInt(ruleData.groupId), risk: ruleData.priority === 'high' ? '高' : ruleData.priority === 'medium' ? '中' : '低', description: ruleData.description, is_enabled: ruleData.isActive, // 以下是默认值,实际应用中需要根据业务逻辑设置 references_laws: {}, extraction_config: { type: "OCR+LLM", fields: [] }, evaluation_config: { rules: [], logicType: "and" }, pass_message: "", fail_message: "", suggestion_message: "", suggestion_message_type: "warning", post_action: "none", action_config: "" }; // 使用postgrestPost创建评查点 const response = await postgrestPost<{code: number; msg: string; data: ApiRule}, typeof apiRuleData>('evaluation_points', apiRuleData, token); // 检查是否有错误响应 if (response.error) { return { error: response.error, status: response.status }; } // 确保响应数据存在且符合预期格式 if (!response.data || !response.data.data) { return { error: '接口返回数据格式不正确', status: 500 }; } // 将API返回的数据映射到前端模型 const rule = mapApiRuleToFrontendModel(response.data.data); return { data: rule }; } catch (error) { console.error('创建评查点出错:', error); return { error: error instanceof Error ? error.message : '创建评查点失败', status: 500 }; } } /** * 更新评查点 * @param id 评查点ID * @param ruleData 评查点数据 * @param token JWT token (可选) * @returns 更新后的评查点 */ export async function updateRule(id: string, ruleData: Partial>, token?: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> { try { // 构建API接受的更新数据 const apiRuleData: Record = {}; if (ruleData.code !== undefined) { apiRuleData.code = ruleData.code; } if (ruleData.name !== undefined) { apiRuleData.name = ruleData.name; } if (ruleData.groupId !== undefined) { apiRuleData.evaluation_point_groups_id = parseInt(ruleData.groupId); } if (ruleData.priority !== undefined) { apiRuleData.risk = ruleData.priority === 'high' ? '高' : ruleData.priority === 'medium' ? '中' : '低'; } if (ruleData.description !== undefined) { apiRuleData.description = ruleData.description; } if (ruleData.isActive !== undefined) { apiRuleData.is_enabled = ruleData.isActive; } // 使用postgrestPut更新评查点 const response = await postgrestPut<{code: number; msg: string; data: ApiRule}, typeof apiRuleData>(`evaluation_points/${id}`, apiRuleData, undefined, token); // 检查是否有错误响应 if (response.error) { return { error: response.error, status: response.status }; } // 确保响应数据存在且符合预期格式 if (!response.data || !response.data.data) { return { error: '接口返回数据格式不正确', status: 500 }; } // 将API返回的数据映射到前端模型 const rule = mapApiRuleToFrontendModel(response.data.data); return { data: rule }; } catch (error) { console.error('更新评查点出错:', error); return { error: error instanceof Error ? error.message : '更新评查点失败', status: 500 }; } } /** * 删除评查点 * @param id 评查点ID * @param token JWT token (可选) * @returns 删除结果 */ export async function deleteRule(id: string, token?: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> { try { // console.log(`开始删除评查点, ID: ${id}`); // 使用 PostgREST 语法,通过查询参数指定要删除的行 const postgrestParams: PostgrestParams = { filter: { 'id': `eq.${id}` }, headers: { 'Prefer': 'return=representation' // 请求返回被删除的记录 }, token }; // 使用postgrestDelete删除评查点 const response = await postgrestDelete('evaluation_points', postgrestParams); // console.log('删除请求响应:', JSON.stringify(response, null, 2)); // 检查是否有错误响应 if (response.error) { console.error('删除评查点API返回错误:', response.error); return { error: response.error, status: response.status }; } // 确保响应数据存在 if (!response.data) { console.error('API响应缺少数据字段'); return { error: 'API返回数据为空', status: 500 }; } // 创建一个模拟的成功删除结果 const createMockSuccessRule = (): Rule => { return { id: id, code: '', name: '', ruleType: '', groupId: '', groupName: '', priority: 'medium', description: '', isActive: false, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; }; // 处理9000端口响应格式 if (typeof response.data === 'object' && response.data !== null && 'code' in response.data) { const apiResponse = response.data as {code: number; msg: string; data?: ApiRule | ApiRule[]}; // 检查响应的code - 如果code为0则表示操作成功 if (apiResponse.code === 0) { // 如果data不存在或是空数组,返回模拟数据 if (!apiResponse.data || (Array.isArray(apiResponse.data) && apiResponse.data.length === 0)) { return { data: createMockSuccessRule() }; } // 处理存在的data let apiRule: ApiRule; if (Array.isArray(apiResponse.data)) { apiRule = apiResponse.data[0]; } else { apiRule = apiResponse.data; } // 将API返回的数据映射到前端模型 const rule = mapApiRuleToFrontendModel(apiRule); return { data: rule }; } // 如果code不为0,则返回错误信息 return { error: apiResponse.msg || '删除失败,服务器返回错误', status: 500 }; } // 处理3000端口响应格式 (直接返回数据) else { // 处理数组响应 if (Array.isArray(response.data)) { if (response.data.length === 0) { // 空数组表示成功但没有返回数据 return { data: createMockSuccessRule() }; } else { // 返回数组中的第一个元素 const apiRule = response.data[0] as ApiRule; const rule = mapApiRuleToFrontendModel(apiRule); return { data: rule }; } } // 处理单一对象响应 else { const apiRule = response.data as ApiRule; const rule = mapApiRuleToFrontendModel(apiRule); return { data: rule }; } } } catch (error) { console.error('删除评查点出错:', error); return { error: error instanceof Error ? error.message : '删除评查点失败', status: 500 }; } } /** * 复制评查点 * @param id 评查点ID * @param token JWT token (可选) * @returns 新创建的评查点 */ export async function duplicateRule(id: string, token?: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> { try { // 1. 获取原评查点详情 const ruleResponse = await getRule(id, token); if (ruleResponse.error || !ruleResponse.data) { return { error: ruleResponse.error || '获取评查点详情失败', status: 500 }; } // 2. 准备新评查点数据 const rule = ruleResponse.data; // 创建新评查点对象 const newRuleData = { code: `${rule.code}-COPY`, name: `${rule.name} (复制)`, ruleType: rule.ruleType, groupId: rule.groupId, groupName: rule.groupName, priority: rule.priority, description: rule.description, isActive: rule.isActive }; // 3. 创建新评查点 return createRule(newRuleData, token); } catch (error) { console.error('复制评查点出错:', error); return { error: error instanceof Error ? error.message : '复制评查点失败', status: 500 }; } } /** * 评查点类型 */ export interface RuleType { id: string; name: string; description?: string; isEnabled: boolean; } /** * 规则组 */ export interface RuleGroup { id: string; name: string; description?: string; isEnabled: boolean; typeId?: string; // 关联的评查点类型ID } /** * 获取评查点类型列表 * @param documentTypeIds 文档类型 ID 列表 * @param token JWT token (可选) * @returns 评查点类型列表 */ export async function getRuleTypes(documentTypeIds?: number[], token?: string): Promise<{data: RuleType[]; error?: never} | {data?: never; error: string; status?: number}> { try { const documentTypesParams: PostgrestParams = { select: 'id, name, evaluation_point_groups_ids', filter: {}, token }; const documentTypesResponse = await postgrestGet<{ code: number; msg: string; data: Array<{ id: number; name: string; evaluation_point_groups_ids: number[]; }> }>('document_types', documentTypesParams); if (documentTypesResponse.error) { return { error: documentTypesResponse.error, status: documentTypesResponse.status }; } // 提取 document_types 数据 let documentTypesData: Array<{ id: number; name: string; evaluation_point_groups_ids: number[]; }> = []; if (documentTypesResponse.data && 'code' in documentTypesResponse.data && documentTypesResponse.data.data) { if (Array.isArray(documentTypesResponse.data.data)) { documentTypesData = documentTypesResponse.data.data; } } else if (Array.isArray(documentTypesResponse.data)) { documentTypesData = documentTypesResponse.data as Array<{ id: number; name: string; evaluation_point_groups_ids: number[]; }>; } if (documentTypesData.length === 0) { console.warn('getRuleTypes: 未找到对应的文档类型数据'); return { data: [] }; } // 2️⃣ 提取并组合所有的 evaluation_point_groups_ids const allGroupIds = new Set(); documentTypesData.forEach(docType => { if (Array.isArray(docType.evaluation_point_groups_ids)) { docType.evaluation_point_groups_ids.forEach(id => allGroupIds.add(id)); } }); if (allGroupIds.size === 0) { console.warn('getRuleTypes: 未找到评查点组 ID'); return { data: [] }; } // console.log('📋 [getRuleTypes] 提取的评查点组 IDs:', Array.from(allGroupIds)); // 3️⃣ 根据组合后的 ID 查询 evaluation_point_groups 表 const groupIdsStr = Array.from(allGroupIds).join(','); const groupsParams: PostgrestParams = { select: ` id, pid, code, name, description, is_enabled `, filter: { 'id': `in.(${groupIdsStr})`, 'pid': 'eq.0' }, token }; const response = await postgrestGet<{ code: number; msg: string; data: Array<{ id: number; pid: number; code: string; name: string; description: string; is_enabled: boolean; }> }>('evaluation_point_groups', groupsParams); // 检查是否有错误响应 if (response.error) { return { error: response.error, status: response.status }; } // 处理响应数据 if (response.data && 'code' in response.data && response.data.data) { if (Array.isArray(response.data.data)) { const ruleTypes = response.data.data.map(item => ({ id: item.id.toString(), pid: item.pid.toString(), code: item.code, name: item.name, description: item.description, isEnabled: item.is_enabled })); // console.log('📋 [getRuleTypes] 返回评查点类型:', ruleTypes); return { data: ruleTypes }; } else { return { data: [] }; } } else if (Array.isArray(response.data)) { const ruleTypes = response.data.map(item => ({ id: item.id.toString(), pid: item.pid.toString(), code: item.code, name: item.name, description: item.description, isEnabled: item.is_enabled })); // console.log('📋 [getRuleTypes] 返回评查点类型:', ruleTypes); return { data: ruleTypes }; } else { return { data: [] }; } } catch (error) { console.error('获取评查点类型出错:', error); return { error: error instanceof Error ? error.message : '获取评查点类型失败', status: 500 }; } } /** * 根据评查点类型ID获取规则组列表 * @param typeId 评查点类型ID * @param token JWT token (可选) * @returns 规则组列表 */ export async function getRuleGroupsByType(typeId: string, token?: string): Promise<{data: RuleGroup[]; error?: never} | {data?: never; error: string; status?: number}> { try { // 如果typeId为空或为"全部",则返回空数组 if (!typeId || typeId === 'all') { return { data: [] }; } // 构建PostgrestParams参数 const postgrestParams: PostgrestParams = { select: ` id, pid, code, name, description, is_enabled `, // 查询指定类型ID的规则组 filter: { 'pid': `eq.${typeId}` }, token }; // 发送请求获取规则组列表 const response = await postgrestGet<{code: number; msg: string; data: Array<{ id: number; pid: number; code: string; name: string; description: string; is_enabled: boolean; }>; }>('evaluation_point_groups', postgrestParams); // 检查是否有错误响应 if (response.error) { return { error: response.error, status: response.status }; } // 确保响应数据存在且符合预期格式 if(response.data && 'code' in response.data && response.data.data){ if(Array.isArray(response.data.data) && response.data.data.length > 0){ // 将API返回的数据映射到前端模型 const ruleGroups = response.data.data.map(item => ({ id: item.id.toString(), name: item.name, description: item.description, isEnabled: item.is_enabled, code: item.code })); return { data: ruleGroups }; }else{ return { error: '9000接口返回数据格式不正确', status: 500 }; } }else if(Array.isArray(response.data) && response.data.length > 0){ // console.log("评查点类型列表",response.data); const ruleGroups = response.data.map(item => ({ id: item.id.toString(), name: item.name, description: item.description, isEnabled: item.is_enabled, code: item.code })); return { data: ruleGroups }; }else{ return { error: '3000接口返回数据格式不正确', status: 500 }; } } catch (error) { console.error('获取规则组出错:', error); return { error: error instanceof Error ? error.message : '获取规则组失败', status: 500 }; } } // 定义提取配置类型 interface ExtractionConfigType { llm: { fields: string[]; prompt_setting: { type: string; template: string; }; }; vlm: { fields: Array; prompt_setting: { type: string; template: string; }; }; regex: { fields: Array<{ field: string; pattern: string }>; }; } // 定义转换后的评查点数据类型 interface FormattedEvaluationPoint { id: number; // 修改为只接受 number 类型 name: string; code: string; risk: string; is_enabled: boolean; description: string; references_laws: Record | null; evaluation_point_groups_pid: number | null; evaluation_point_groups_id: number | null; extraction_config: ExtractionConfigType; evaluation_config: { logicType: string; customLogic: string; rules: Array<{ id: string; type: string; config: Record; }>; }; pass_message: string; fail_message: string; suggestion_message: string; suggestion_message_type: string; post_action: string; action_config: string; score: number; } /** * 将 API 返回的数据格式转换为前端需要的格式 * @param apiRule API 返回的评查点数据 * @returns 转换后的前端格式数据 */ export function convertApiRuleToFormData(apiRule: ApiRule): FormattedEvaluationPoint { // 提取旧格式的字段数据 const extractFields = (): ExtractionConfigType => { const fields: ExtractionConfigType = { llm: { fields: [], prompt_setting: { type: 'system', template: '' } }, vlm: { fields: [], prompt_setting: { type: 'system', template: '' } }, regex: { fields: [] } }; if (!apiRule.extraction_config) return fields; // 处理不同的字段类型 if (apiRule.extraction_config.type === 'OCR+LLM' || apiRule.extraction_config.type === 'LLM') { fields.llm.fields = apiRule.extraction_config.fields || []; if (apiRule.extraction_config.prompt_setting) { fields.llm.prompt_setting = { type: apiRule.extraction_config.prompt_setting.type || 'system', template: apiRule.extraction_config.prompt_setting.template || '' }; } } else if (apiRule.extraction_config.type === 'VLM') { fields.vlm.fields = apiRule.extraction_config.fields || []; if (apiRule.extraction_config.prompt_setting) { fields.vlm.prompt_setting = { type: apiRule.extraction_config.prompt_setting.type || 'system', template: apiRule.extraction_config.prompt_setting.template || '' }; } } else if (apiRule.extraction_config.type === 'REGEX') { // 将字符串字段转换为 regex 格式对象 fields.regex.fields = apiRule.extraction_config.fields.map(field => ({ field, pattern: '' })); } return fields; }; // 转换后的数据 const formattedData: FormattedEvaluationPoint = { id: typeof apiRule.id === 'string' ? parseInt(apiRule.id, 10) : apiRule.id, // 确保 id 是数字 name: apiRule.name, code: apiRule.code, risk: apiRule.risk, is_enabled: apiRule.is_enabled, description: apiRule.description, references_laws: apiRule.references_laws, evaluation_point_groups_pid: apiRule.evaluation_point_groups?.first_name ? null : null, evaluation_point_groups_id: apiRule.evaluation_point_groups_id, extraction_config: extractFields(), evaluation_config: { logicType: apiRule.evaluation_config?.logicType || 'and', customLogic: '', rules: apiRule.evaluation_config?.rules || [] }, pass_message: apiRule.pass_message || '', fail_message: apiRule.fail_message || '', suggestion_message: apiRule.suggestion_message || '', suggestion_message_type: apiRule.suggestion_message_type || 'warning', post_action: apiRule.post_action || 'none', action_config: apiRule.action_config || '', score: 0 }; return formattedData; } /** * 获取单个评查点数据 * @param id 评查点ID * @returns 评查点数据 */ export async function getEvaluationPoint(id: number): Promise<{ data?: FormattedEvaluationPoint; error?: string; status?: number; }> { try { // console.log(`获取评查点数据,ID: ${id}`); // 使用 postgrestGet 替代直接调用 fetch const postgrestParams: PostgrestParams = { select: `*`, filter: { 'id': `eq.${id}` } }; const response = await postgrestGet<{code: number; msg: string; data: ApiRule[]} | ApiRule[]>('evaluation_points', postgrestParams); if (response.error) { return { error: response.error, status: response.status }; } // 使用 extractApiData 统一处理响应数据 const extractedData = extractApiData(response.data); if (extractedData && Array.isArray(extractedData) && extractedData.length > 0) { // 转换数据为前端格式 const formattedData = convertApiRuleToFormData(extractedData[0]); return { data: formattedData }; } else { return { error: '获取数据失败: 返回数据为空', status: 404 }; } } catch (error) { console.error('获取评查点数据失败:', error); return { error: error instanceof Error ? error.message : '获取评查点数据失败', status: 500 }; } } /** * 获取评查点组数据 * @returns 评查点组列表 */ export async function getEvaluationPointGroups(): Promise<{ data?: Array<{ id: number; pid: number; code: string; name: string; description: string; is_enabled: boolean; created_at: string; updated_at: string; }>; error?: string; status?: number; }> { try { // console.log("获取评查点组数据"); // 使用 postgrestGet 替代直接调用 fetch const postgrestParams: PostgrestParams = { select: `*` }; // 定义评查点组类型 type EvaluationPointGroupType = { id: number; pid: number; code: string; name: string; description: string; is_enabled: boolean; created_at?: string; updated_at?: string; }; const response = await postgrestGet<{code: number; msg: string; data: EvaluationPointGroupType[]} | EvaluationPointGroupType[]>('evaluation_point_groups', postgrestParams); if (response.error) { return { error: response.error, status: response.status }; } // 使用 extractApiData 统一处理响应数据 const extractedData = extractApiData(response.data); if (extractedData) { // 确保每个组都有 created_at 和 updated_at 字段 const currentTime = new Date().toISOString(); const formattedGroups = extractedData.map(group => ({ ...group, created_at: group.created_at || currentTime, updated_at: group.updated_at || currentTime })); return { data: formattedGroups }; } else { return { error: '获取评查点组数据失败: 返回数据为空', status: 404 }; } } catch (error) { console.error('获取评查点组数据失败:', error); return { error: error instanceof Error ? error.message : '获取评查点组数据失败', status: 500 }; } } // 用于评查点输入的接口 interface EvaluationPointInput { id?: number | string; name?: string; code?: string; risk?: string; is_enabled?: boolean; description?: string; references_laws?: Record | null; evaluation_point_groups_pid?: number | null; evaluation_point_groups_id?: number | null; extraction_config?: { llm?: { fields?: string[]; prompt_setting?: { type?: string; template?: string; }; }; vlm?: { fields?: Array; prompt_setting?: { type?: string; template?: string; }; }; regex?: { fields?: Array<{ field: string, pattern: string }>; }; }; evaluation_config?: { logicType?: string; customLogic?: string; rules?: Array<{ id: string; type: string; config: Record; }>; }; pass_message?: string; fail_message?: string; suggestion_message?: string; suggestion_message_type?: string; post_action?: string; action_config?: string; score?: number; } /** * 保存评查点数据 * @param evaluationPoint 评查点数据 * @param isEditMode 是否为编辑模式 * @returns 保存结果 */ export async function saveEvaluationPoint(evaluationPoint: EvaluationPointInput, isEditMode: boolean): Promise<{ data?: FormattedEvaluationPoint[]; error?: string; status?: number; }> { try { // console.log(`${isEditMode ? '更新' : '创建'}评查点数据`); // 创建一个符合数据库模式的数据副本 const cleanedData = { id: evaluationPoint.id, name: evaluationPoint.name?.trim(), code: evaluationPoint.code?.trim(), risk: evaluationPoint.risk || 'low', is_enabled: evaluationPoint.is_enabled !== undefined ? evaluationPoint.is_enabled : true, description: evaluationPoint.description || '', references_laws: evaluationPoint.references_laws || null, evaluation_point_groups_pid: evaluationPoint.evaluation_point_groups_pid || null, evaluation_point_groups_id: evaluationPoint.evaluation_point_groups_id || null, extraction_config: { llm: { fields: Array.isArray(evaluationPoint.extraction_config?.llm?.fields) ? [...evaluationPoint.extraction_config.llm.fields] : [], prompt_setting: { type: evaluationPoint.extraction_config?.llm?.prompt_setting?.type || 'system', template: evaluationPoint.extraction_config?.llm?.prompt_setting?.template || '' } }, vlm: { fields: Array.isArray(evaluationPoint.extraction_config?.vlm?.fields) ? [...evaluationPoint.extraction_config.vlm.fields] : [], prompt_setting: { type: evaluationPoint.extraction_config?.vlm?.prompt_setting?.type || 'system', template: evaluationPoint.extraction_config?.vlm?.prompt_setting?.template || '' } }, regex: { fields: Array.isArray(evaluationPoint.extraction_config?.regex?.fields) ? [...evaluationPoint.extraction_config.regex.fields] : [] } }, evaluation_config: { logicType: evaluationPoint.evaluation_config?.logicType || 'and', customLogic: evaluationPoint.evaluation_config?.customLogic || '', rules: Array.isArray(evaluationPoint.evaluation_config?.rules) ? evaluationPoint.evaluation_config.rules.map((rule) => ({ id: rule.id || '1', type: rule.type || '', config: rule.config || {} })) : [] }, pass_message: evaluationPoint.pass_message || '文档检查通过,符合规范要求。', fail_message: evaluationPoint.fail_message || '文档存在以下问题,请修改后重新提交。', suggestion_message: evaluationPoint.suggestion_message || '', suggestion_message_type: evaluationPoint.suggestion_message_type || 'warning', post_action: evaluationPoint.post_action || 'none', action_config: evaluationPoint.action_config || '', score: evaluationPoint.score !== undefined ? Number(evaluationPoint.score) : 0 }; // 如果是新建模式,则删除id字段 if (!isEditMode) { delete cleanedData.id; } // 确保配置对象中的规则配置被正确处理 if (cleanedData.evaluation_config && Array.isArray(cleanedData.evaluation_config.rules)) { cleanedData.evaluation_config.rules = cleanedData.evaluation_config.rules .filter(rule => rule && rule.type) // 确保规则有类型 .map(rule => { // 根据规则类型确保config中有必要的字段 const config = { ...rule.config }; // 移除辅助字段(同rules.new.tsx中的逻辑) switch (rule.type) { case 'exists': if (!Array.isArray(config.fields)) config.fields = []; if (!config.logic) config.logic = 'and'; delete config.availableFields; delete config.selectedFields; delete config.existsLogic; break; case 'consistency': if (!Array.isArray(config.pairs)) config.pairs = []; if (!config.logic) config.logic = 'and'; delete config.availableFields; delete config.logicRelation; delete config.initialSourceField; delete config.initialTargetField; delete config.initialCompareMethod; break; case 'format': if (!config.field) config.field = ''; if (!config.formatType) config.formatType = 'date'; if (!config.parameters) config.parameters = ''; delete config.availableFields; delete config.checkField; delete config.formatParams; break; case 'logic': if (!Array.isArray(config.conditions)) config.conditions = []; if (!config.logic) config.logic = 'and'; delete config.availableFields; delete config.logicRelation; delete config.initialField; delete config.initialOperator; delete config.initialValue; break; case 'regex': if (!config.field) config.field = ''; if (!config.pattern) config.pattern = ''; if (!config.matchType) config.matchType = 'match'; delete config.availableFields; delete config.checkField; delete config.regexPattern; break; case 'ai': if (!config.model) config.model = 'qwen14b'; if (typeof config.temperature !== 'number') config.temperature = 0.1; if (!config.prompt) config.prompt = ''; delete config.availableFields; break; case 'code': if (!config.language) config.language = 'javascript'; if (!config.code) config.code = ''; delete config.availableFields; break; } return { id: rule.id, type: rule.type, config }; }); } // console.log("准备发送到API的数据大小:", JSON.stringify(cleanedData).length, "字节"); // 使用 postgrest-client 替代直接 fetch 调用 let response; if (isEditMode) { // 更新操作 response = await postgrestPut<{code: number; msg: string; data: ApiRule} | ApiRule, typeof cleanedData>( `evaluation_points`, cleanedData, {id: cleanedData.id!} ); } else { // 创建操作 response = await postgrestPost<{code: number; msg: string; data: ApiRule} | ApiRule, typeof cleanedData>( 'evaluation_points', cleanedData ); } // 处理错误响应 if (response.error) { return { error: response.error, status: response.status }; } // 使用 extractApiData 统一处理响应数据 const extractedData = extractApiData(response.data); if (extractedData) { // 转换数据格式后返回 if (Array.isArray(extractedData)) { return { data: extractedData.map(rule => convertApiRuleToFormData(rule)) }; } else { return { data: [convertApiRuleToFormData(extractedData)] }; } } else { return { error: `${isEditMode ? '更新' : '创建'}评查点数据失败: 返回数据为空`, status: 404 }; } } catch (error) { console.error("保存评查点失败:", error); return { error: error instanceof Error ? error.message : '保存评查点失败', status: 500 }; } }