完善文档预览的效果修改

This commit is contained in:
2025-04-21 23:02:29 +08:00
parent 5c2c367856
commit cd2f060d87
15 changed files with 718 additions and 565 deletions
+127 -43
View File
@@ -1,21 +1,6 @@
import { postgrestGet, type PostgrestParams, postgrestPut } from "../postgrest-client";
import { postgrestGet, type PostgrestParams, postgrestPut, postgrestPost } from "../postgrest-client";
import {getDocument} from "~/api/files/documents";
import dayjs from 'dayjs';
/**
* 格式化日期
* @param dateString 日期字符串
* @returns 格式化后的日期字符串
*/
function formatDate(dateString: string): string {
if (!dateString) return '';
try {
return dayjs(dateString).format('YYYY-MM-DD HH:mm:ss');
} catch (error) {
console.error('日期格式化失败:', error);
return dateString;
}
}
import { formatDate } from "~/utils";
/**
* 从不同格式的 API 响应中提取数据
@@ -62,6 +47,15 @@ interface EvaluationPoint {
[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;
@@ -185,6 +179,47 @@ export async function getReviewPoints(fileId: string) {
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 => {
@@ -204,6 +239,7 @@ export async function getReviewPoints(fileId: string) {
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 = '';
@@ -268,6 +304,10 @@ export async function getReviewPoints(fileId: string) {
return {
id: result.id,
documentId: fileId,
pointId: point.id,
editAuditStatusId: editAuditStatus.id,
editAuditStatus: editAuditStatus.status,
title: message,
pointName: point.name || '',
groupName: group.name || '',
@@ -356,18 +396,19 @@ export async function getReviewPoints(fileId: string) {
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, result: boolean, message: string): Promise<{
export async function updateReviewResult(resultId: string, editAuditStatusId: string | number, result: string, message: string): Promise<{
data?: unknown;
error?: string;
status?: number;
@@ -396,29 +437,72 @@ export async function updateReviewResult(resultId: string, result: boolean, mess
const currentResult = currentResultData[0];
const currentEvaluatedResults = currentResult.evaluated_results || {};
// 构建要更新的数据,保留原有字段,只更新result和message
// 判断是否是重新审核操作
const isReview = result === 'review';
console.log('isReview-------', result);
// 构建要更新的数据,保留原有字段
const updatedEvaluatedResults = {
...currentEvaluatedResults,
result: result,
message: message
// 如果是重新审核操作,不更新result,只更新message
...(isReview ? { message } : { result: result === 'true' ? true : false, message }),
};
const updatedData = {
evaluated_results: updatedEvaluatedResults
};
// 调用 API 更新数据
const response = await postgrestPut<unknown, typeof updatedData>(
// 调用 API 更新评查点结果数据
const resultResponse = await postgrestPut<unknown, typeof updatedData>(
'evaluation_results',
updatedData,
{ id: resultId }
);
if (response.error) {
return { error: response.error, status: response.status };
if (resultResponse.error) {
return { error: resultResponse.error, status: resultResponse.status };
}
const extractedData = extractApiData<unknown>(response.data);
// 处理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 };
@@ -435,12 +519,12 @@ export async function updateReviewResult(resultId: string, result: boolean, mess
}
/**
* 确认评查结果并更新文档审核状态
* 确认评查结果并更新文档审核状态 只更新文档的审核状态为通过
* @param documentId 文档ID
* @returns 更新结果
*/
export async function confirmReviewResults(documentId: string): Promise<{
data?: { auditStatus: number; score: number };
data?: { auditStatus: number; };
error?: string;
status?: number;
}> {
@@ -450,26 +534,26 @@ export async function confirmReviewResults(documentId: string): Promise<{
}
// 获取该文档的所有评查点结果
const reviewPointsResponse = await getReviewPoints(documentId);
// const reviewPointsResponse = await getReviewPoints(documentId);
if ('error' in reviewPointsResponse && reviewPointsResponse.error) {
return { error: reviewPointsResponse.error, status: reviewPointsResponse.status };
}
// 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 };
}
// if (!('data' in reviewPointsResponse) || !reviewPointsResponse.data || !Array.isArray(reviewPointsResponse.data)) {
// return { error: '获取评查点数据失败', status: 500 };
// }
// 计算总分数
const totalScore = reviewPointsResponse.stats?.score || 0;
// // 计算总分数
// const totalScore = reviewPointsResponse.stats?.score || 0;
// 根据总分确定审核状态
// <80分:不通过(-1),>=80分:通过(1)
const auditStatus = totalScore < 80 ? -1 : 1;
// // 根据总分确定审核状态
// // <80分:不通过(-1),>=80分:通过(1)
// const auditStatus = totalScore < 80 ? -1 : 1;
// 更新文档的审核状态
const updateDocumentParams = {
audit_status: auditStatus
audit_status: 1
};
// 调用API更新文档审核状态
@@ -483,7 +567,7 @@ export async function confirmReviewResults(documentId: string): Promise<{
return { error: response.error, status: response.status };
}
return { data: { auditStatus, score: totalScore } };
return { data: { auditStatus: 1} };
} catch (error) {
console.error('确认评查结果失败:', error);
return {
+80 -43
View File
@@ -69,6 +69,10 @@ export interface ReviewFileUI {
message: string;
}>;
createdBy: string;
passCount: number;
warningCount: number;
failCount: number;
manualCount: number;
}
// 文件列表搜索参数
@@ -109,6 +113,10 @@ interface EvaluationPoint {
interface DocumentReviewResult {
status: number;
issueCount: number;
passCount: number;
warningCount: number;
failCount: number;
manualCount: number;
}
/**
@@ -177,6 +185,7 @@ export function getFileExtension(fileName: string): string {
* @returns UI文件对象
*/
export function convertToReviewFileUI(document: Document, documentTypeName: string): ReviewFileUI {
// 将评查状态转换为UI状态(这个评查状态后续可能不需要,这里先预留)
const reviewStatus = mapReviewStatusToUI(document.evaluations_status);
const reviewFileUI: ReviewFileUI = {
@@ -195,7 +204,11 @@ export function convertToReviewFileUI(document: Document, documentTypeName: stri
score: 0,
auditStatus: document.audit_status,
issues: [],
createdBy: document.user_id?.toString() || '系统'
createdBy: document.user_id?.toString() || '系统',
passCount: 0,
warningCount: 0,
failCount: 0,
manualCount: 0
};
// console.log('reviewFileUI-----',reviewFileUI);
@@ -396,6 +409,9 @@ export async function getReviewFiles(searchParams: DocumentSearchParams = {}): P
let totalScore = 0;
let totalPoints = 0;
let totalPassPoints = 0;
let totalWarningPoints = 0;
let totalFailPoints = 0;
let totalManualPoints = 0;
// 存储该文档的问题消息
const issuesList: Array<{severity: 'info' | 'warning' | 'error' | 'critical', message: string}> = [];
@@ -406,9 +422,10 @@ export async function getReviewFiles(searchParams: DocumentSearchParams = {}): P
const pointId = result.evaluation_point_id;
const point = pointsMap.get(pointId);
// 检查是否需要人工审核
if (resultValue === false && point && point.post_action === 'manual') {
// 统计需要人工审核的评查点
if (point && point.post_action === 'manual') {
hasManualReviewPoint = true;
totalManualPoints++;
}
// 检查是否有不通过的结果
@@ -422,6 +439,14 @@ export async function getReviewFiles(searchParams: DocumentSearchParams = {}): P
message: evaluatedResults.message as string
});
}
// 统计不通过而且评查点是警告的评查点
if (point && point.suggestion_message_type === 'warning') {
totalWarningPoints++;
}else if (point && point.suggestion_message_type === 'error') {
totalFailPoints++;
}
}else{
totalPassPoints++;
}
@@ -464,14 +489,20 @@ export async function getReviewFiles(searchParams: DocumentSearchParams = {}): P
documentStatusMap.set(docId, {
status,
passCount: totalPassPoints,
warningCount: totalWarningPoints,
failCount: totalFailPoints,
manualCount: totalManualPoints,
issueCount: results.filter(r => r.evaluated_results?.result === false).length
});
});
// console.log("documentStatusMap-----",documentStatusMap);
// 将文档数据转换为UI文件对象,同时应用评查状态
const reviewFiles = extractedDocuments.map(doc => {
const typeName = typeNameMap[doc.type_id] || '未知类型';
const reviewResult = documentStatusMap.get(doc.id) || { status: doc.evaluations_status || 0, issueCount: 0 };
const reviewResult = documentStatusMap.get(doc.id) || { status: doc.evaluations_status || 0, issueCount: 0, passCount: 0, warningCount: 0, failCount: 0, manualCount: 0 };
const issues = documentIssuesMap.get(doc.id) || [];
const score = documentScoreMap.get(doc.id) || 100; // 获取计算后的分数,默认为100
@@ -490,14 +521,20 @@ export async function getReviewFiles(searchParams: DocumentSearchParams = {}): P
reviewFile.reviewStatusCode = reviewResult.status;
reviewFile.reviewStatus = mapReviewStatusToUI(reviewResult.status);
reviewFile.issueCount = reviewResult.issueCount;
reviewFile.passCount = reviewResult.passCount;
reviewFile.warningCount = reviewResult.warningCount;
reviewFile.failCount = reviewResult.failCount;
reviewFile.manualCount = reviewResult.manualCount;
reviewFile.score = score; // 添加分数
// 添加问题列表
reviewFile.issues = issues;
return reviewFile;
});
console.log('reviewFiles-----',reviewFiles);
// console.log('reviewFiles-----',reviewFiles);
return {
data: {
files: reviewFiles,
@@ -519,51 +556,51 @@ export async function getReviewFiles(searchParams: DocumentSearchParams = {}): P
* @param status 评查状态
* @returns 更新后的文件信息
*/
export async function updateReviewStatus(id: string, status: string): Promise<{
data?: ReviewFileUI;
error?: string;
status?: number;
}> {
try {
if (!id) {
return { error: '文件ID不能为空', status: 400 };
}
// export async function updateReviewStatus(id: string, status: string): Promise<{
// data?: ReviewFileUI;
// error?: string;
// status?: number;
// }> {
// try {
// if (!id) {
// return { error: '文件ID不能为空', status: 400 };
// }
const statusValue = mapUIToReviewStatus(status);
// const statusValue = mapUIToReviewStatus(status);
const response = await postgrestPut<Document, Partial<Document>>(
'documents',
{ evaluations_status: statusValue },
{ id: parseInt(id) }
);
// const response = await postgrestPut<Document, Partial<Document>>(
// 'documents',
// { evaluations_status: statusValue },
// { id: parseInt(id) }
// );
if (response.error) {
return { error: response.error, status: response.status };
}
// if (response.error) {
// return { error: response.error, status: response.status };
// }
const extractedData = extractApiData<Document>(response.data);
// const extractedData = extractApiData<Document>(response.data);
if (!extractedData) {
return { error: '更新评查状态失败', status: 500 };
}
// if (!extractedData) {
// return { error: '更新评查状态失败', status: 500 };
// }
// 获取文档类型,用于查找文档类型名称
const documentTypesResponse = await getDocumentTypes({pageSize: 500});
const documentTypes = documentTypesResponse.data?.types || [];
// // 获取文档类型,用于查找文档类型名称
// const documentTypesResponse = await getDocumentTypes({pageSize: 500});
// const documentTypes = documentTypesResponse.data?.types || [];
// 查找文档类型名称
const docType = documentTypes.find((type: DocumentTypeUI) => type.id === extractedData.type_id);
const typeName = docType ? docType.name : '未知类型';
// // 查找文档类型名称
// const docType = documentTypes.find((type: DocumentTypeUI) => type.id === extractedData.type_id);
// const typeName = docType ? docType.name : '未知类型';
return { data: convertToReviewFileUI(extractedData, typeName) };
} catch (error) {
console.error('更新评查状态失败:', error);
return {
error: error instanceof Error ? error.message : '更新评查状态失败',
status: 500
};
}
}
// return { data: convertToReviewFileUI(extractedData, typeName) };
// } catch (error) {
// console.error('更新评查状态失败:', error);
// return {
// error: error instanceof Error ? error.message : '更新评查状态失败',
// status: 500
// };
// }
// }
/**
* 更新文件的审核状态
+3 -4
View File
@@ -1,5 +1,4 @@
import { postgrestGet, postgrestDelete, postgrestPut, type PostgrestParams } from '../postgrest-client';
import dayjs from 'dayjs';
import { getDocumentTypes } from '../document-types/document-types';
import { formatDate } from '../../utils';
@@ -433,9 +432,9 @@ export async function updateDocument(id: string, document: Partial<DocumentUI> &
apiDocument.document_number = document.documentNumber;
}
if (document.type !== undefined) {
apiDocument.type_id = parseInt(document.type);
}
// if (document.type !== undefined) {
// apiDocument.type_id = parseInt(document.type);
// }
if (document.auditStatus !== undefined) {
apiDocument.audit_status = document.auditStatus;
+3 -114
View File
@@ -42,123 +42,12 @@ function logPostgrestQuery(endpoint: string, params?: QueryParams, method: strin
// 以可读格式单独打印每个参数
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined) {
if (key === 'select' && typeof value === 'string') {
// 美化 select 参数,使其看起来像 SQL 查询
console.log(` - ${key}:`);
const fields = value.replace(/\s+/g, ' ').trim().split(',');
fields.forEach(field => {
console.log(` ${field.trim()}`);
});
} else if (key === 'order' && typeof value === 'string') {
// 格式化排序参数
console.log(` - ${key}: ${value.replace(/\./g, ' ')}`); // 例如:created_at desc
} else if (key === 'or' && typeof value === 'string') {
// 格式化OR条件
console.log(` - ${key}: ${value.replace(/\./g, ' -> ').replace(/,/g, ' 或 ')}`);
} else {
console.log(` - ${key}: ${JSON.stringify(value)}`);
}
console.log(` - ${key}: ${JSON.stringify(value)}`);
}
});
// 构建人类可读的简化URL
const readableQueryString = Object.entries(params)
.filter(([, value]) => value !== undefined)
.map(([key, value]) => {
if (key === 'select' && typeof value === 'string') {
// 简化select查询
return `${key}=...`;
}
return `${key}=${value}`;
})
.join('&');
console.log(`\n📦 可读URL: ${baseUrl}/${normalizedEndpoint}${readableQueryString ? '?' + readableQueryString : ''}`);
// 格式化查询为 PostgreSQL 风格的查询
let postgrestQuery = `${method.toUpperCase()} `;
if (params.select && typeof params.select === 'string') {
postgrestQuery += params.select.replace(/\s+/g, ' ').trim();
} else {
postgrestQuery += '*';
}
postgrestQuery += ` FROM ${normalizedEndpoint}`;
const conditions: string[] = [];
// 添加过滤条件
if (params.filter) {
Object.entries(params.filter).forEach(([key, value]) => {
if (value !== undefined && typeof value === 'string') {
// 解析 eq.X, neq.X, gt.X 等
const parts = value.toString().split('.');
if (parts.length >= 2) {
const operator = parts[0];
const operatorMap: Record<string, string> = {
'eq': '=',
'neq': '!=',
'gt': '>',
'gte': '>=',
'lt': '<',
'lte': '<=',
'like': 'LIKE',
'ilike': 'ILIKE'
};
const sqlOperator = operatorMap[operator] || operator;
const value = parts.slice(1).join('.');
conditions.push(`${key} ${sqlOperator} '${value}'`);
}
}
});
}
// 添加 OR 条件
if (params.or) {
if (typeof params.or === 'string') {
if (params.or.startsWith('(') && params.or.endsWith(')')) {
// 处理 or=(cond1,cond2) 格式
const orConditions = params.or.slice(1, -1).split(',').map(cond => {
const [field, operator] = cond.split('.');
return `${field} ${operator.replace(/ilike/i, 'ILIKE')}`;
});
if (orConditions.length > 0) {
conditions.push(`(${orConditions.join(' OR ')})`);
}
} else {
// 简单 or 条件
conditions.push(params.or);
}
}
}
// 添加WHERE子句
if (conditions.length > 0) {
postgrestQuery += ` WHERE ${conditions.join(' AND ')}`;
}
// 添加ORDER BY
if (params.order && typeof params.order === 'string') {
const [field, direction] = params.order.split('.');
postgrestQuery += ` ORDER BY ${field} ${direction.toUpperCase()}`;
}
// 添加LIMIT和OFFSET
if (params.limit !== undefined) {
postgrestQuery += ` LIMIT ${params.limit}`;
}
if (params.offset !== undefined) {
postgrestQuery += ` OFFSET ${params.offset}`;
}
console.log('\n📦 等效SQL查询:');
console.log(postgrestQuery);
console.log('=========================================\n');
}
console.log('=========================================\n');
}
}