import { postgrestGet, postgrestPost, postgrestPut, postgrestDelete, type PostgrestParams } from '../postgrest-client'; import { apiRequest } from '../axios-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 (一级分组ID) groupId?: string; // 规则组ID (二级分组ID) risk?: '高' | '中' | '低'; // 风险等级 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; evaluation_point_groups_pid?: number | null; // 一级分组ID (评查点类型) 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, risk, isActive, keyword, area, userRole, token } = params; // 🔑 如果没有传递 userRole,尝试从 localStorage 中获取 let user_role = userRole || ''; if (!user_role && 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 || ''; } } catch (error) { console.error('❌ [getRulesList] 解析 localStorage 用户信息失败:', error); } } // 🆕 调用后端 FastAPI 接口: GET /api/v3/evaluation-points // 构建查询参数 const queryParams = new URLSearchParams(); queryParams.append('page', page.toString()); queryParams.append('page_size', pageSize.toString()); // 添加一级分组ID(评查点类型) if (ruleType) { queryParams.append('evaluation_point_groups_pid', ruleType); } // 添加二级分组ID(规则组) if (groupId) { queryParams.append('evaluation_point_groups_id', groupId); } // 添加风险等级筛选 if (risk) { queryParams.append('risk', risk); } // 添加启用状态筛选 if (isActive !== undefined) { queryParams.append('is_enabled', isActive.toString()); } // 🔑 添加地区过滤 if (user_role === 'provincial_admin') { queryParams.append('area', '省级'); } else if (area) { queryParams.append('area', area); } // 添加关键词搜索(后端会同时搜索 name 和 code) if (keyword) { queryParams.append('name', keyword); queryParams.append('code', keyword); } // 调用 FastAPI 接口 const response = await apiRequest<{ data: EvaluationPointData[]; total: number; page: number; page_size: number; }>( `/api/v3/evaluation-points?${queryParams.toString()}`, { method: 'GET', headers: { ...(token ? { 'Authorization': `Bearer ${token}` } : {}) } } ); if (response.error) { return { error: response.error, status: response.status }; } if (!response.data || !Array.isArray(response.data.data)) { return { error: '接口返回数据格式不正确', status: 500 }; } console.log('✅ [getRulesList] 成功获取评查点列表,共', response.data.total, '条'); // 🆕 直接映射后端返回的数据到前端 Rule 模型 // 后端已包含 ruleType、groupName、groupId 字段,无需额外处理 const mappedRules: Rule[] = response.data.data.map((point: EvaluationPointData) => { // 风险等级映射到优先级 const priorityMap: Record = { '高': 'high', '中': 'medium', '低': 'low', 'high': 'high', 'medium': 'medium', 'low': 'low' }; // 🔑 清洗评查点编码:移除最后一个 '--' 及其后面的字符 let cleanedCode = point.code || ''; const lastDoubleHyphenIndex = cleanedCode.lastIndexOf('--'); if (lastDoubleHyphenIndex !== -1) { cleanedCode = cleanedCode.substring(0, lastDoubleHyphenIndex); } return { id: point.id?.toString() || '', code: cleanedCode, name: point.name || '', ruleType: point.ruleType || '', // ✅ 后端直接返回 groupId: point.groupId || '', // ✅ 后端直接返回 groupName: point.groupName || '', // ✅ 后端直接返回 priority: priorityMap[point.risk] || 'medium', description: point.description || '', isActive: point.is_enabled, createdAt: formatDate(point.created_at || ''), updatedAt: formatDate(point.updated_at || '') }; }); return { data: { rules: mappedRules, totalCount: response.data.total } }; } 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查询参数语法 filter: { 'id': `eq.${id}` }, // 使用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 }; // 获取评查点详情 - 使用正确的PostgREST格式 const response = await postgrestGet<{code: number; msg: string; data: ApiRule} | ApiRule[]>('/api/postgrest/proxy/evaluation_points', postgrestParams); // 检查是否有错误响应 if (response.error) { return { error: response.error, status: response.status }; } // 处理响应数据(PostgREST可能返回数组或包装对象) let apiRule: ApiRule | null = null; if (response.data) { // 如果是数组格式(PostgREST标准响应) if (Array.isArray(response.data)) { apiRule = response.data.length > 0 ? response.data[0] : null; } // 如果是包装对象格式 else if ('data' in response.data && response.data.data) { apiRule = response.data.data as ApiRule; } } if (!apiRule) { return { error: '评查点不存在', status: 404 }; } // 获取分组信息 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}[]}>('/api/postgrest/proxy/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 id 评查点ID * @param token JWT token (可选) * @returns 删除结果 */ export async function deleteRule(id: string, token?: string): Promise<{data: {success: boolean; message: string}; error?: never} | {data?: never; error: string; status?: number}> { try { // 调用后端 FastAPI 接口: DELETE /api/v3/evaluation-points/{id} // 后端会处理所有验证逻辑(检查是否存在、是否有关联数据等) const response = await apiRequest<{success: boolean; message: string}>( `/api/v3/evaluation-points/${id}`, { method: 'DELETE', headers: { ...(token ? { 'Authorization': `Bearer ${token}` } : {}) } } ); if (response.error) { return { error: response.error, status: response.status }; } if (response.data && response.data.success) { console.log('✅ deleteRule 成功:', response.data.message); return { data: response.data }; } return { error: '删除评查点失败', status: 500 }; } 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 { // 🔑 如果没有传入 documentTypeIds,返回空数组 if (!documentTypeIds || documentTypeIds.length === 0) { console.warn('getRuleTypes: 未提供 documentTypeIds 参数'); return { data: [] }; } const documentTypesParams: PostgrestParams = { select: 'id, name, evaluation_point_groups_ids', filter: { // 🔑 只查询指定的文档类型 ID 'id': `in.(${documentTypeIds.join(',')})` }, token }; const documentTypesResponse = await postgrestGet<{ code: number; msg: string; data: Array<{ id: number; name: string; evaluation_point_groups_ids: number[]; }> }>('/api/postgrest/proxy/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; }> }>('/api/postgrest/proxy/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; }>; }>('/api/postgrest/proxy/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 || null, 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; } // 用于评查点输入的接口 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; } /** * 评查点统计信息 */ export interface RuleStatistics { total_count: number; // 总评查点数 enabled_count: number; // 已启用数量 disabled_count: number; // 已禁用数量 by_risk: { // 按风险等级分组 low: number; // 低风险数量 medium: number; // 中风险数量 high: number; // 高风险数量 }; by_group: Array<{ // 按规则组分组 group_id: number; group_name: string; count: number; }>; } /** * 批量更新评查点启用状态 * @param ids 评查点ID列表 * @param is_enabled 启用状态 * @param token JWT token (可选) * @returns 批量更新结果 */ export async function batchUpdateRuleStatus( ids: string[], is_enabled: boolean, token?: string ): Promise<{ success: boolean; updated_count: number; failed_ids: string[]; errors?: Array<{ id: string; error: string }>; }> { const failedIds: string[] = []; const errors: Array<{ id: string; error: string }> = []; let updatedCount = 0; // 逐个验证并更新 for (const id of ids) { try { // 执行更新 const updateResult = await updateRule(id, { isActive: is_enabled }, token); if (updateResult.error) { failedIds.push(id); errors.push({ id, error: updateResult.error }); } else { updatedCount++; } } catch (error) { failedIds.push(id); errors.push({ id, error: error instanceof Error ? error.message : '更新失败' }); } } return { success: failedIds.length === 0, updated_count: updatedCount, failed_ids: failedIds, errors: errors.length > 0 ? errors : undefined }; } /** * 批量删除评查点 * @param ids 评查点ID列表 * @param token JWT token (可选) * @returns 批量删除结果 */ export async function batchDeleteRules( ids: string[], token?: string ): Promise<{ success: boolean; deleted_count: number; failed_ids: string[]; errors?: Array<{ id: string; error: string }>; }> { const failedIds: string[] = []; const errors: Array<{ id: string; error: string }> = []; let deletedCount = 0; // 逐个验证并删除 for (const id of ids) { try { // 使用增强的 deleteRule 函数(包含关联检查) const deleteResult = await deleteRule(id, token); if (deleteResult.error) { failedIds.push(id); errors.push({ id, error: deleteResult.error }); } else { deletedCount++; } } catch (error) { failedIds.push(id); errors.push({ id, error: error instanceof Error ? error.message : '删除失败' }); } } return { success: failedIds.length === 0, deleted_count: deletedCount, failed_ids: failedIds, errors: errors.length > 0 ? errors : undefined }; } /** * 完整评查点数据结构(对应前端 EvaluationPoint 类型) */ export interface EvaluationPointData { id?: number; name: string; code: string; risk: string; is_enabled: boolean; description?: string; evaluation_point_groups_id: number | null; evaluation_point_groups_pid: number | null; // 🆕 后端新增的分组名称字段 ruleType?: string; // 评查点类型(一级分组名称) groupName?: string; // 所属规则组(二级分组名称) groupId?: string; // 规则组ID(二级分组ID的字符串形式) references_laws: { name: string; content: string; articles: string[]; }; 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; area?: string; created_at?: string; updated_at?: string; } /** * 创建完整评查点(调用后端 FastAPI 接口) * @param evaluationPointData 完整的评查点数据 * @param token JWT token (可选) * @returns 创建的评查点数据 */ export async function createEvaluationPoint( evaluationPointData: Omit, token?: string ): Promise<{data: EvaluationPointData; error?: never} | {data?: never; error: string; status?: number}> { try { // 调用后端 FastAPI 接口: POST /api/v3/evaluation-points const response = await apiRequest( '/api/v3/evaluation-points', { method: 'POST', body: JSON.stringify(evaluationPointData), headers: { 'Content-Type': 'application/json', ...(token ? { 'Authorization': `Bearer ${token}` } : {}) } } ); if (response.error) { return { error: response.error, status: response.status }; } if (response.data) { console.log('✅ createEvaluationPoint 成功:', response.data); return { data: response.data }; } return { error: '创建评查点失败:返回数据格式不正确', status: 500 }; } catch (error) { console.error('❌ 创建评查点出错:', error); return { error: error instanceof Error ? error.message : '创建评查点失败', status: 500 }; } } /** * 更新完整评查点(调用后端 FastAPI 接口) * @param id 评查点ID * @param evaluationPointData 完整的评查点数据(部分更新) * @param token JWT token (可选) * @returns 更新后的评查点数据 */ export async function updateEvaluationPoint( id: string, evaluationPointData: Partial>, token?: string ): Promise<{data: EvaluationPointData; error?: never} | {data?: never; error: string; status?: number}> { try { // 调用后端 FastAPI 接口: PUT /api/v3/evaluation-points/{id} const response = await apiRequest( `/api/v3/evaluation-points/${id}`, { method: 'PUT', body: JSON.stringify(evaluationPointData), headers: { 'Content-Type': 'application/json', ...(token ? { 'Authorization': `Bearer ${token}` } : {}) } } ); if (response.error) { return { error: response.error, status: response.status }; } if (response.data) { console.log('✅ updateEvaluationPoint 成功:', response.data); return { data: response.data }; } return { error: '更新评查点失败:返回数据格式不正确', status: 500 }; } 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 getEvaluationPoint( id: string, token?: string ): Promise<{data: EvaluationPointData; error?: never} | {data?: never; error: string; status?: number}> { try { // 调用后端 FastAPI 接口: GET /api/v3/evaluation-points/{id} const response = await apiRequest( `/api/v3/evaluation-points/${id}`, { method: 'GET', headers: { ...(token ? { 'Authorization': `Bearer ${token}` } : {}) } } ); if (response.error) { return { error: response.error, status: response.status }; } if (!response.data) { return { error: '评查点不存在', status: 404 }; } console.log('✅ getEvaluationPoint 成功:', response.data); return { data: response.data }; } catch (error) { console.error('❌ 获取评查点出错:', error); return { error: error instanceof Error ? error.message : '获取评查点失败', status: 500 }; } }