import { postgrestGet, postgrestPost, postgrestPut, postgrestDelete, type PostgrestParams } from '../postgrest-client'; import dayjs from 'dayjs'; /** * 评查点列表查询参数 */ export interface RulesQueryParams { page?: number; pageSize?: number; ruleType?: string; groupId?: string; isActive?: boolean; keyword?: string; orderBy?: string; orderDirection?: 'asc' | 'desc'; } /** * 评查点列表响应数据 */ export interface RulesListResponse { rules: Rule[]; totalCount: number; } /** * API返回的评查点详情 */ export interface ApiRule { id: number; code: string; name: string; evaluation_point_groups_id: number; risk: string; description: string; is_enabled: boolean; evaluation_point_groups?: { name: string; }; 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' }; // 规则类型映射(这里根据实际业务逻辑设置一个默认值) const ruleType = 'essential'; // 实际应用中可能需要从其他字段推断 // 优先使用关联查询获取的分组名称,如果不存在则使用默认值 const groupName = apiRule.evaluation_point_groups?.name || `${apiRule.evaluation_point_groups_id}`; return { id: apiRule.id.toString(), code: apiRule.code, name: apiRule.name, ruleType: ruleType, groupId: apiRule.evaluation_point_groups_id.toString(), groupName: groupName, priority: priorityMap[apiRule.risk] || 'medium', description: apiRule.description, isActive: apiRule.is_enabled, createdAt: apiRule.created_at, updatedAt: apiRule.updated_at }; } // 格式化日期的辅助函数 function formatDate(dateString: string): string { return dayjs(dateString).format('YYYY-MM-DD HH:mm:ss'); } /** * 获取评查点列表 * @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, orderBy = 'created_at', orderDirection = 'desc' } = params; // 构建PostgrestParams参数 const postgrestParams: PostgrestParams = { // 使用PostgREST资源嵌入语法获取关联数据 // 这里使用外键关系自动关联evaluation_point_groups表 select: ` id, code, name, evaluation_point_groups_id, evaluation_point_groups(name), risk, description, is_enabled, created_at, updated_at `, // 设置分页 limit: pageSize, offset: (page - 1) * pageSize, // 设置排序 order: `${orderBy}.${orderDirection}`, // 构建过滤条件 filter: {}, // 添加额外头部,用于获取总记录数 headers: { 'Prefer': 'count=exact' } }; // 添加精确匹配过滤 if (groupId) { postgrestParams.filter!['evaluation_point_groups_id'] = `eq.${groupId}`; } if (isActive !== undefined) { postgrestParams.filter!['is_enabled'] = `eq.${isActive}`; } // 添加模糊搜索 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 }; } // 确保响应数据存在且符合预期格式 if (!response.data || !response.data.data || !Array.isArray(response.data.data)) { return { error: '接口返回数据格式不正确', status: 500 }; } // 获取API返回的所有评查点 const apiRules = response.data.data; // 从响应头中获取总记录数(如果存在) // 注意:这里假设总记录数会在接口响应的某个位置返回 // 实际使用时,需要根据 PostgREST 的响应格式进行调整 let totalCount = 0; // 尝试从响应中获取总数 if (response.headers && response.headers['content-range']) { // 例如 Content-Range: 0-9/42 表示总共有 42 条记录 const range = response.headers['content-range']; const total = range.split('/')[1]; if (total !== '*') { // '*' 表示未知总数 totalCount = parseInt(total, 10); } } else { // 如果没有响应头,则使用当前返回的数据长度作为默认值 // 这种情况下分页可能不准确 totalCount = apiRules.length; console.warn('未能从响应中获取总记录数,使用当前页数据长度作为默认值'); } // 打印第一个数据项来查看结构(仅用于调试) if (apiRules.length > 0) { console.log('评查点数据示例:', JSON.stringify(apiRules[0], null, 2)); } // 收集所有分组ID (多进行一步查找表的操作) const groupIds = [...new Set(apiRules.map(rule => rule.evaluation_point_groups_id))]; // 如果有分组ID,查询分组信息 const groupsMap: Record = {}; if (groupIds.length > 0) { try { // 构建查询参数 const groupsParams: PostgrestParams = { select: 'id,name', filter: { 'id': `in.(${groupIds.join(',')})` } }; // 查询评查点分组表 const groupsResponse = await postgrestGet<{code: number; msg: string; data: {id: number; name: string}[]}>('evaluation_point_groups', groupsParams); if (groupsResponse.data?.data) { // 创建ID到名称的映射 groupsResponse.data.data.forEach(group => { groupsMap[group.id.toString()] = group.name; }); // 打印分组数据(仅用于调试) console.log('分组数据:', groupsMap); } } catch (error) { console.error('获取分组数据失败:', error); // 失败不阻止主流程,使用默认分组名 } } // 应用本地过滤 - 只在API不支持的情况下使用 let filteredRules = [...apiRules]; // 如果有ruleType过滤(API暂不支持),在本地过滤 if (ruleType) { // 注意:这是本地过滤,实际情况下最好在API层面支持 filteredRules = filteredRules.filter(() => { // 实现一个映射逻辑,比如根据其他字段推导ruleType const derivedType = 'essential'; // 此处应为实际推导逻辑 return derivedType === ruleType; }); } // 如果进行了本地过滤,则需要调整总记录数 if (ruleType) { totalCount = filteredRules.length; } // 将API返回的数据映射到前端模型,并附加分组名称 const mappedRules = filteredRules.map(apiRule => { // 创建修改版的apiRule,添加从分组映射获取的名称 const enhancedApiRule = { ...apiRule, // 从映射中获取分组名称,如果不存在则使用默认值 evaluation_point_groups: { name: groupsMap[apiRule.evaluation_point_groups_id.toString()] || `${apiRule.evaluation_point_groups_id}` // name: apiRule.evaluation_point_groups?.name || `${apiRule.evaluation_point_groups_id}` } }; const rule = mapApiRuleToFrontendModel(enhancedApiRule); // 格式化日期字段 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 * @returns 评查点详情 */ export async function getRule(id: 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 ` }; // 获取评查点详情 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}` } }; // 查询评查点分组 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 = { 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 评查点数据 * @returns 创建的评查点 */ export async function createRule(ruleData: Omit): 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); // 检查是否有错误响应 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 评查点数据 * @returns 更新后的评查点 */ export async function updateRule(id: string, ruleData: Partial>): 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); // 检查是否有错误响应 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 * @returns 删除结果 */ export async function deleteRule(id: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> { try { // 使用postgrestDelete删除评查点 const response = await postgrestDelete<{code: number; msg: string; data: ApiRule}>(`evaluation_points/${id}`); // 检查是否有错误响应 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 * @returns 新创建的评查点 */ export async function duplicateRule(id: string): Promise<{data: Rule; error?: never} | {data?: never; error: string; status?: number}> { try { // 1. 获取原评查点详情 const ruleResponse = await getRule(id); 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); } catch (error) { console.error('复制评查点出错:', error); return { error: error instanceof Error ? error.message : '复制评查点失败', status: 500 }; } }