Files
leaudit-platform-frontend/app/api/evaluation_points/reviews.ts
T

589 lines
21 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { postgrestGet, type PostgrestParams, postgrestPut, postgrestPost } from "../postgrest-client";
import {getDocument} from "~/api/files/documents";
import { formatDate } from "~/utils";
/**
* 从不同格式的 API 响应中提取数据
* @param responseData API 响应数据
* @returns 提取后的数据或 null
*/
function extractApiData<T>(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;
}
// 定义评查结果类型
interface EvaluationResult {
id: string | number;
document_id: string | number;
evaluation_point_id: string | number;
evaluated_results?: {
result?: boolean;
message?: string;
data?: string;
[key: string]: unknown;
};
[key: string]: unknown;
}
// 定义评查点类型
interface EvaluationPoint {
id: string | number;
evaluation_point_groups_id: string | number;
suggestion_message_type?: string;
suggestion_message?: string;
score?: number;
updated_at?: string;
[key: string]: unknown;
}
// 定义审核状态类型
interface AuditStatus {
id: string | number;
document_id: string | number;
evaluation_point_id: string | number;
edit_audit_status: number;
[key: string]: unknown;
}
// 定义评查点组类型
interface EvaluationPointGroup {
id: string | number;
name?: string;
[key: string]: unknown;
}
// 定义前端使用的评查点结果类型
interface ReviewPointResult {
id: string | number;
title: string;
groupName: string;
status: string;
content: string;
suggestion: string;
result?: boolean;
score: number;
}
// 定义统计数据类型
interface StatsData {
total: number;
success: number;
warning: number;
error: number;
score: number;
}
// 在文件顶部添加的类型定义,在interface区块前添加
interface OcrDataResult {
pages?: number[];
[key: string]: unknown;
}
interface OcrData {
[key: string]: OcrDataResult | unknown;
ocr_result?: Record<string, OcrDataResult | unknown>;
}
/**
* 获取当前评查文件的所有评查点结果
* @param fileId 评查文件ID
* @returns 评查点结果列表和统计数据
*/
export async function getReviewPoints(fileId: string) {
// 首先先获取这个文档的数据
const documentData = await getDocument(fileId);
if (documentData.error) {
console.error("获取文档数据错误:", documentData.error);
return Response.json({ error: documentData.error }, { status: documentData.status || 500 });
}
// 步骤1:根据fileId查询evaluation_results表
const evaluationResultsParams: PostgrestParams = {
select: '*',
filter: {
'document_id': `eq.${fileId}`
}
};
const evaluationResultsResponse = await postgrestGet('evaluation_results', evaluationResultsParams);
if (evaluationResultsResponse.error) {
return { error: evaluationResultsResponse.error, status: evaluationResultsResponse.status };
}
const evaluationResultsData = extractApiData<EvaluationResult[]>(evaluationResultsResponse.data) || [];
if (Array.isArray(evaluationResultsData) && evaluationResultsData.length <= 0) {
return { data: [], stats: { total: 0, success: 0, warning: 0, error: 0, score: 0 },error: '获取评查结果数据失败' };
}
// 收集所有评查点ID,用于查询评查点详情
const evaluationPointIds = evaluationResultsData.map(item => item.evaluation_point_id).filter(Boolean);
if (evaluationPointIds.length === 0) {
return { data: [], stats: { total: 0, success: 0, warning: 0, error: 0, score: 0 },error: '获取评查点ID失败' };
}
// 步骤2:根据evaluation_point_id查询evaluation_points表
const evaluationPointsParams: PostgrestParams = {
select: '*',
filter: {
'id': `in.(${evaluationPointIds.join(',')})`
}
};
const evaluationPointsResponse = await postgrestGet('evaluation_points', evaluationPointsParams);
if (evaluationPointsResponse.error) {
return { error: evaluationPointsResponse.error, status: evaluationPointsResponse.status };
}
const evaluationPointsData = extractApiData<EvaluationPoint[]>(evaluationPointsResponse.data);
if (!evaluationPointsData || !Array.isArray(evaluationPointsData)) {
return { data: [], stats: { total: 0, success: 0, warning: 0, error: 0, score: 0 } };
}
// 收集所有评查点组ID,用于查询评查点组详情
const groupIds = evaluationPointsData.map(item => item.evaluation_point_groups_id).filter(Boolean);
if (groupIds.length === 0) {
return { data: [], stats: { total: 0, success: 0, warning: 0, error: 0, score: 0 } };
}
// 查询评查点组
const groupsParams: PostgrestParams = {
select: '*',
filter: {
'id': `in.(${groupIds.join(',')})`
}
};
const groupsResponse = await postgrestGet('evaluation_point_groups', groupsParams);
if (groupsResponse.error) {
return { error: groupsResponse.error, status: groupsResponse.status };
}
const groupsData = extractApiData<EvaluationPointGroup[]>(groupsResponse.data);
if (!groupsData || !Array.isArray(groupsData)) {
return { data: [], stats: { total: 0, success: 0, warning: 0, error: 0, score: 0 } };
}
// 从audit_status表中 获取 需人工审核 的那些评查点的数据
// console.log('evaluationPointsData1112------', evaluationPointsData.find(point => point.post_action === 'manual'));
const manualReviewPoints = evaluationPointsData.filter(point => point.post_action === 'manual');
const manualReviewPointsIds = manualReviewPoints.map(point => point.id);
const manualReviewPointsParams: PostgrestParams = {
select: '*',
filter: {
'document_id': `eq.${fileId}`,
'evaluation_point_id': `in.(${manualReviewPointsIds.join(',')})`
}
};
const manualReviewPointsResponse = await postgrestGet('audit_status', manualReviewPointsParams);
if (manualReviewPointsResponse.error) {
return { error: manualReviewPointsResponse.error, status: manualReviewPointsResponse.status };
}
const manualReviewPointsData = extractApiData<AuditStatus[]>(manualReviewPointsResponse.data);
// 构建评查点ID到editAuditStatus的映射
const editAuditStatusMap = new Map<string | number, {id: string | number, status: number}>();
// 如果有查询结果,则根据evaluation_point_id索引到对应数据
if (manualReviewPointsData && Array.isArray(manualReviewPointsData)) {
manualReviewPointsData.forEach(auditStatus => {
if (auditStatus.evaluation_point_id && auditStatus.edit_audit_status !== undefined) {
editAuditStatusMap.set(auditStatus.evaluation_point_id, {id: auditStatus.id, status: auditStatus.edit_audit_status});
}
});
}
// 为没有对应audit_status记录的manual类型评查点设置默认值0
if (manualReviewPointsIds.length > 0) {
manualReviewPointsIds.forEach(pointId => {
if (!editAuditStatusMap.has(pointId)) {
editAuditStatusMap.set(pointId, {id: '', status: 0});
}
});
}
// console.log('manualReviewPoints-------', manualReviewPoints);
// 创建映射关系以便快速查找
const pointsMap = new Map<string | number, EvaluationPoint>();
evaluationPointsData.forEach(point => {
pointsMap.set(point.id, point);
});
// console.log('pointsMap-------', pointsMap);
const groupsMap = new Map<string | number, EvaluationPointGroup>();
groupsData.forEach(group => {
groupsMap.set(group.id, group);
});
// console.log('groupsMap-------', groupsMap);
// 构建前端所需的数据格式
const resultData: ReviewPointResult[] = evaluationResultsData.map(result => {
const point = pointsMap.get(result.evaluation_point_id) || {} as EvaluationPoint;
const group = groupsMap.get(point.evaluation_point_groups_id || 0) || {} as EvaluationPointGroup;
const editAuditStatus = editAuditStatusMap.get(result.evaluation_point_id) || {id: '', status: 0};
// 从 evaluated_results 中提取数据
let message = '';
let data = '';
if (result.evaluated_results && typeof result.evaluated_results === 'object') {
message = result.evaluated_results.message || '';
data = result.evaluated_results.data || '';
}
// 提取页码数组
let contentPage: Record<string, string> = {};
// console.log('result-------', result.evaluated_results?.result);
// console.log('datacontent-------', data);
if (data && typeof data === 'object') {
// try {
// const dataObj = data as Record<string, string>;
// // 检查是否是预期的格式 {'立案报告表-完整性检查''缺失部分内容'}
// for (const key in dataObj) {
// if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
// // 使用'-'分割获取前缀(如'立案报告表')
// const prefix = key.split('-')[0];
// // console.log('prefix-------', prefix);
// // 检查document.data中的ocrResult是否存在这个key
// if (documentData.data?.ocrResult &&
// typeof documentData.data.ocrResult === 'object') {
// // ocrResult可能有嵌套的ocr_result属性
// let ocrData: OcrData = documentData.data.ocrResult as OcrData;
// // 检查是否有嵌套的ocr_result对象
// if ('ocr_result' in ocrData &&
// ocrData.ocr_result &&
// typeof ocrData.ocr_result === 'object') {
// ocrData = ocrData.ocr_result as OcrData;
// }
// for (const ocrKey in ocrData) {
// // 如果找到匹配的key
// if (ocrKey === prefix &&
// ocrData[ocrKey] &&
// typeof ocrData[ocrKey] === 'object' &&
// 'pages' in ocrData[ocrKey]) {
// // 获取pages数组
// const pages = ocrData[ocrKey].pages;
// if (Array.isArray(pages)) {
// // 存储每个key对应的页码数组
// contentPage[key] = pages;
// }
// break;
// }
// }
// }
// }
// }
// }
// 4-22 更改数据结构:通过拿到的data数据(每一个key对应一个object),将object中的page提取出来
try{
const dataObj = data as Record<string, {page: number | string,value: string}>;
for (const key in dataObj) {
if (Object.prototype.hasOwnProperty.call(dataObj, key)) {
contentPage[key] = dataObj[key].page.toString();
}
}
}
catch (e) {
console.error('解析评查点data失败:', e);
contentPage = {};
}
}
return {
id: result.id,
documentId: fileId,
pointId: point.id,
editAuditStatusId: editAuditStatus.id,
editAuditStatus: editAuditStatus.status,
title: message,
pointName: point.name || '',
groupName: group.name || '',
status: point.suggestion_message_type || '', //评查点的评查结果状态
// status: 'error', //评查点的评查结果状态
content: data,
contentPage: contentPage,
suggestion: point.suggestion_message || '',
// suggestion: '只是给建议的修改内容',
result: result.evaluated_results?.result, // 记录评查结果,用于统计
score: point.score || 0,
postAction: point.post_action || '',
// postAction: 'manual',
actionContent: point.action_config || '',
// actionContent: '用户提前在评查点输入过的修改内容',
legalBasis: point.references_laws || {}
// legalBasis: {
// name: '中华人民共和国食品安全法',
// content: '中华人民共和国食品安全法',
// article: [
// {
// name: '中华人民共和国食品安全法',
// content: '中华人民共和国食品安全法'
// }
// ]
// }
};
});
// 统计数据
const stats: StatsData = {
total: evaluationResultsData.length,
success: 0,
warning: 0,
error: 0,
score: 0
};
// 计算统计数据
resultData.forEach(item => {
// 成功数量统计
if (item.result === true) {
stats.success += 1;
} else if (item.result === false) {
// 警告和错误数量统计
if (item.status === 'warning') {
stats.warning += 1;
} else if (item.status === 'error') {
stats.error += 1;
}
}
// 分数统计
stats.score += item.score || 0;
});
// 构建文件信息-评查信息的数据
// 找出最新的评查时间
let latestUpdatedAt = '';
evaluationResultsData.forEach(result => {
if (result.updated_at && (!latestUpdatedAt || result.updated_at > latestUpdatedAt)) {
latestUpdatedAt = result.updated_at.toString();
}
});
// 提取不重复的规则组名称
const uniqueGroups = Array.from(new Set(resultData.map(item => item.groupName))).filter(Boolean);
// 计算问题数量
const issueCount = stats.warning + stats.error;
// 构建评查信息对象
const reviewInfo = {
reviewTime: formatDate(latestUpdatedAt),
reviewModel: 'DeepSeek',
ruleGroup: uniqueGroups.join('、'),
result: issueCount > 0 ? 'warning' : 'success',
issueCount: issueCount
};
// console.log("reviewInfo-------",JSON.stringify(reviewInfo,null,2));
// data->reviewPoints stats->statistics reviewInfo->reviewInfo document->document
return { data: resultData, stats, reviewInfo, document: documentData.data };
}
/**
* 更新评查结果
* @param resultId 评查结果ID
* @param editAuditStatusId 审核状态ID
* @param result 评查结果 (true/false)
* @param message 评查意见
* @returns 更新后的评查结果
*/
export async function updateReviewResult(resultId: string, editAuditStatusId: string | number, result: string, message: string): Promise<{
data?: unknown;
error?: string;
status?: number;
}> {
try {
if (!resultId) {
return { error: '评查结果ID不能为空', status: 400 };
}
// 首先获取当前评查结果数据
const currentResultResponse = await postgrestGet('evaluation_results', {
select: '*',
filter: { id: `eq.${resultId}` }
});
if (currentResultResponse.error) {
return { error: currentResultResponse.error, status: currentResultResponse.status };
}
const currentResultData = extractApiData<EvaluationResult[]>(currentResultResponse.data);
if (!currentResultData || !Array.isArray(currentResultData) || currentResultData.length === 0) {
return { error: '未找到评查结果数据', status: 404 };
}
const currentResult = currentResultData[0];
const currentEvaluatedResults = currentResult.evaluated_results || {};
// 判断是否是重新审核操作
const isReview = result === 'review';
console.log('isReview-------', result);
// 构建要更新的数据,保留原有字段
const updatedEvaluatedResults = {
...currentEvaluatedResults,
// 如果是重新审核操作,不更新result,只更新message
...(isReview ? { message } : { result: result === 'true' ? true : false, message }),
};
const updatedData = {
evaluated_results: updatedEvaluatedResults
};
// 调用 API 更新评查点结果数据
const resultResponse = await postgrestPut<unknown, typeof updatedData>(
'evaluation_results',
updatedData,
{ id: resultId }
);
if (resultResponse.error) {
return { error: resultResponse.error, status: resultResponse.status };
}
// 处理audit_status表的更新或新增
// 确定edit_audit_status的值:
// 如果是重新审核操作,值为0;否则值为1
const editAuditStatusValue = isReview ? 0 : 1;
console.log('editAuditStatusValue-------', editAuditStatusValue);
console.log('editAuditStatusId-------', editAuditStatusId);
if (editAuditStatusId && editAuditStatusId !== '') {
// 更新现有审核状态记录
const auditStatusResponse = await postgrestPut(
'audit_status',
{ edit_audit_status: editAuditStatusValue },
{ id: editAuditStatusId }
);
if (auditStatusResponse.error) {
return { error: auditStatusResponse.error, status: auditStatusResponse.status || 500 };
}
} else {
// 如果没有editAuditStatusId,则创建新记录
// 首先获取文档ID和评查点ID
const documentId = currentResult.document_id;
const evaluationPointId = currentResult.evaluation_point_id;
// 创建新的审核状态记录
const newAuditStatus = {
document_id: documentId,
evaluation_point_id: evaluationPointId,
evaluation_result_id: resultId,
edit_audit_status: editAuditStatusValue
};
// 使用postgrestPost创建新记录
const postResponse = await postgrestPost('audit_status', newAuditStatus);
if (postResponse.error) {
return { error: postResponse.error, status: postResponse.status || 500 };
}
}
const extractedData = extractApiData<unknown>(resultResponse.data);
if (!extractedData) {
return { error: '更新评查结果失败', status: 500 };
}
return { data: extractedData };
} catch (error) {
console.error('更新评查结果失败:', error);
return {
error: error instanceof Error ? error.message : '更新评查结果失败',
status: 500
};
}
}
/**
* 确认评查结果并更新文档审核状态 只更新文档的审核状态为通过
* @param documentId 文档ID
* @returns 更新结果
*/
export async function confirmReviewResults(documentId: string): Promise<{
data?: { auditStatus: number; };
error?: string;
status?: number;
}> {
try {
if (!documentId) {
return { error: '文档ID不能为空', status: 400 };
}
// 获取该文档的所有评查点结果
// const reviewPointsResponse = await getReviewPoints(documentId);
// if ('error' in reviewPointsResponse && reviewPointsResponse.error) {
// return { error: reviewPointsResponse.error, status: reviewPointsResponse.status };
// }
// if (!('data' in reviewPointsResponse) || !reviewPointsResponse.data || !Array.isArray(reviewPointsResponse.data)) {
// return { error: '获取评查点数据失败', status: 500 };
// }
// // 计算总分数
// const totalScore = reviewPointsResponse.stats?.score || 0;
// // 根据总分确定审核状态
// // <80分:不通过(-1),>=80分:通过(1)
// const auditStatus = totalScore < 80 ? -1 : 1;
// 更新文档的审核状态
const updateDocumentParams = {
audit_status: 1
};
// 调用API更新文档审核状态
const response = await postgrestPut<{ id: string }, typeof updateDocumentParams>(
'documents',
updateDocumentParams,
{ id: documentId }
);
if (response.error) {
return { error: response.error, status: response.status };
}
return { data: { auditStatus: 1} };
} catch (error) {
console.error('确认评查结果失败:', error);
return {
error: error instanceof Error ? error.message : '确认评查结果失败',
status: 500
};
}
}