fix: cut reviewsTest over to new review detail apis
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { postgrestGet, type PostgrestParams, postgrestPut, postgrestPost } from "../postgrest-client";
|
||||
// import {getDocumentWithNoUserId} from "~/api/files/documents";
|
||||
import { getDocument } from "~/api/files/documents";
|
||||
import dayjs from "dayjs";
|
||||
import { getUserSession } from "~/api/login/auth.server";
|
||||
import { apiRequest } from "../axios-client";
|
||||
@@ -187,10 +187,10 @@ export async function getReviewPoints(fileId: string, request: Request) {
|
||||
return { error: '用户身份验证失败', status: 401 };
|
||||
}
|
||||
|
||||
// const userId = userInfo.user_id.toString();
|
||||
|
||||
// 首先先获取这个文档的数据
|
||||
const documentData = await getDocumentWithNoUserId(fileId, frontendJWT);
|
||||
const userId = userInfo.user_id.toString();
|
||||
|
||||
// 首先获取当前文档详情,优先走新后端接口
|
||||
const documentData = await getDocument(fileId, userId, frontendJWT);
|
||||
if (documentData.error) {
|
||||
console.error("获取文档数据错误:", documentData.error);
|
||||
return Response.json({ error: documentData.error }, { status: documentData.status || 500 });
|
||||
@@ -209,13 +209,13 @@ export async function getReviewPoints(fileId: string, request: Request) {
|
||||
const contractStructureComparisonResponse = await postgrestGet('/api/postgrest/proxy/contract_structure_comparison', contractStructureComparisonParams);
|
||||
// console.log('contract_structure_comparison', contractStructureComparisonResponse)
|
||||
|
||||
let contractStructureComparisonData: ContractStructureComparison[] | null = null;
|
||||
if (contractStructureComparisonResponse.error) {
|
||||
console.error("获取文档附件数据错误:", contractStructureComparisonResponse.error);
|
||||
return Response.json({ error: contractStructureComparisonResponse.error }, { status: contractStructureComparisonResponse.status || 500 });
|
||||
console.warn("获取文档附件数据失败,降级为空附件对比数据:", contractStructureComparisonResponse.error);
|
||||
} else {
|
||||
contractStructureComparisonData = extractApiData<ContractStructureComparison[]>(contractStructureComparisonResponse.data);
|
||||
}
|
||||
|
||||
const contractStructureComparisonData = extractApiData<ContractStructureComparison[]>(contractStructureComparisonResponse.data);
|
||||
|
||||
// console.log('文档附件的数据', JSON.stringify(contractStructureComparisonData, null, 2));
|
||||
|
||||
// 解析比对结果
|
||||
@@ -330,10 +330,12 @@ export async function getReviewPoints(fileId: string, request: Request) {
|
||||
token: frontendJWT
|
||||
};
|
||||
const manualReviewPointsResponse = await postgrestGet('/api/postgrest/proxy/audit_status', manualReviewPointsParams);
|
||||
let manualReviewPointsData: AuditStatus[] | null = null;
|
||||
if (manualReviewPointsResponse.error) {
|
||||
return { error: manualReviewPointsResponse.error, status: manualReviewPointsResponse.status };
|
||||
console.warn('获取人工审核状态失败,降级为空审核状态:', manualReviewPointsResponse.error);
|
||||
} else {
|
||||
manualReviewPointsData = extractApiData<AuditStatus[]>(manualReviewPointsResponse.data);
|
||||
}
|
||||
const manualReviewPointsData = extractApiData<AuditStatus[]>(manualReviewPointsResponse.data);
|
||||
|
||||
// 构建评查点ID到editAuditStatus的映射
|
||||
const editAuditStatusMap = new Map<string | number, {id: string | number, status: number, message: string}>();
|
||||
@@ -386,10 +388,12 @@ export async function getReviewPoints(fileId: string, request: Request) {
|
||||
};
|
||||
const scoringProposalsResponse = await postgrestGet('/api/postgrest/proxy/cross_scoring_proposals', scoringProposalsParams);
|
||||
|
||||
let scoringProposalsData: ScoringProposal[] = [];
|
||||
if (scoringProposalsResponse.error) {
|
||||
return { error: scoringProposalsResponse.error, status: scoringProposalsResponse.status };
|
||||
console.warn('获取评分提案失败,降级为空提案数据:', scoringProposalsResponse.error);
|
||||
} else {
|
||||
scoringProposalsData = extractApiData<ScoringProposal[]>(scoringProposalsResponse.data) || [];
|
||||
}
|
||||
const scoringProposalsData = extractApiData<ScoringProposal[]>(scoringProposalsResponse.data) || [];
|
||||
|
||||
|
||||
|
||||
@@ -838,174 +842,37 @@ export async function updateReviewResult(
|
||||
return { error: '评查结果ID不能为空', status: 400 };
|
||||
}
|
||||
|
||||
// 判断是否是重新审核操作
|
||||
const isReview = result === 'review';
|
||||
|
||||
// ============================================
|
||||
// 步骤1: 调用3.1接口更新评查结果(如果不是重新审核操作)
|
||||
// ============================================
|
||||
if (!isReview) {
|
||||
// 构建请求数据
|
||||
const updateResultData: {
|
||||
result?: 'true' | 'false';
|
||||
message?: string;
|
||||
} = {
|
||||
result: result === 'true' ? 'true' : 'false',
|
||||
message: message
|
||||
};
|
||||
|
||||
// 调用 3.1 接口: PATCH /admin/v2/evaluations/results/{result_id}
|
||||
const resultResponse = await apiRequest<{
|
||||
success: boolean;
|
||||
const response = await apiRequest<{
|
||||
code?: number;
|
||||
message?: string;
|
||||
data?: {
|
||||
reviewPointResultId: number;
|
||||
editAuditStatusId: number;
|
||||
editAuditStatus: number;
|
||||
overrideResult: boolean | null;
|
||||
message: string;
|
||||
};
|
||||
}>(
|
||||
`/api/v3/review-points/${resultId}/audit`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: {
|
||||
result_id: number;
|
||||
updated_fields: string[];
|
||||
};
|
||||
}>(
|
||||
`/admin/v2/evaluations/results/${resultId}`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: updateResultData
|
||||
result,
|
||||
message
|
||||
}
|
||||
);
|
||||
|
||||
if (resultResponse.error) {
|
||||
console.error('❌ [updateReviewResult] 3.1接口调用失败:', resultResponse.error);
|
||||
return { error: resultResponse.error, status: resultResponse.status || 500 };
|
||||
}
|
||||
);
|
||||
|
||||
if (!resultResponse.data?.success) {
|
||||
console.error('❌ [updateReviewResult] 3.1接口响应异常:', resultResponse.data);
|
||||
return { error: resultResponse.data?.message || '更新评查结果失败', status: 500 };
|
||||
}
|
||||
if (response.error) {
|
||||
console.error('❌ [updateReviewResult] 新接口调用失败:', response.error);
|
||||
return { error: response.error, status: response.status || 500 };
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 步骤2: 处理审核状态(创建或更新)
|
||||
// ============================================
|
||||
// 确定edit_audit_status的值:
|
||||
// 如果是重新审核操作,值为0;否则值为1
|
||||
const editAuditStatusValue = isReview ? 0 : 1;
|
||||
|
||||
if (editAuditStatusId && editAuditStatusId !== '') {
|
||||
// ============================================
|
||||
// 使用3.3接口更新现有审核状态记录
|
||||
// PATCH /admin/v2/evaluations/audit-status/{audit_status_id}
|
||||
// ============================================
|
||||
const updateAuditData: {
|
||||
edit_audit_status: number;
|
||||
message?: string;
|
||||
} = {
|
||||
edit_audit_status: editAuditStatusValue
|
||||
};
|
||||
|
||||
// 重新审核时不更新message
|
||||
if (!isReview) {
|
||||
updateAuditData.message = message;
|
||||
}
|
||||
|
||||
const auditStatusResponse = await apiRequest<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
data: {
|
||||
audit_status_id: number;
|
||||
updated_fields: string[];
|
||||
};
|
||||
}>(
|
||||
`/admin/v2/evaluations/audit-status/${editAuditStatusId}`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: updateAuditData
|
||||
}
|
||||
);
|
||||
|
||||
if (auditStatusResponse.error) {
|
||||
console.error('❌ [updateReviewResult] 3.3接口调用失败:', auditStatusResponse.error);
|
||||
return { error: auditStatusResponse.error, status: auditStatusResponse.status || 500 };
|
||||
}
|
||||
|
||||
if (!auditStatusResponse.data?.success) {
|
||||
console.error('❌ [updateReviewResult] 3.3接口响应异常:', auditStatusResponse.data);
|
||||
return { error: auditStatusResponse.data?.message || '更新审核状态失败', status: 500 };
|
||||
}
|
||||
|
||||
return { data: auditStatusResponse.data };
|
||||
} else {
|
||||
// ============================================
|
||||
// 使用3.2接口创建新审核状态记录
|
||||
// POST /admin/v2/evaluations/audit-status
|
||||
// ============================================
|
||||
|
||||
// 如果没有传入documentId和evaluationPointId,需要先获取
|
||||
if (!documentId || !evaluationPointId) {
|
||||
// 从评查结果中获取document_id和evaluation_point_id
|
||||
const currentResultResponse = await postgrestGet('/api/postgrest/proxy/evaluation_results', {
|
||||
select: 'document_id,evaluation_point_id',
|
||||
filter: { id: `eq.${resultId}` },
|
||||
token: frontendJWT
|
||||
});
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
documentId = currentResultData[0].document_id;
|
||||
evaluationPointId = currentResultData[0].evaluation_point_id;
|
||||
}
|
||||
|
||||
// 创建新的审核状态记录
|
||||
const newAuditStatusData = {
|
||||
document_id: Number(documentId),
|
||||
evaluation_point_id: Number(evaluationPointId),
|
||||
evaluation_result_id: Number(resultId),
|
||||
edit_audit_status: editAuditStatusValue,
|
||||
message: isReview ? '' : message
|
||||
};
|
||||
|
||||
const createAuditResponse = await apiRequest<{
|
||||
id: number;
|
||||
user_id: number;
|
||||
document_id: number;
|
||||
evaluation_point_id: number;
|
||||
evaluation_result_id: number;
|
||||
edit_audit_status: number;
|
||||
message: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}>(
|
||||
`/admin/v2/evaluations/audit-status`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: newAuditStatusData
|
||||
}
|
||||
);
|
||||
|
||||
if (createAuditResponse.error) {
|
||||
console.error('❌ [updateReviewResult] 3.2接口调用失败:', createAuditResponse.error);
|
||||
return { error: createAuditResponse.error, status: createAuditResponse.status || 500 };
|
||||
}
|
||||
|
||||
return { data: createAuditResponse.data };
|
||||
}
|
||||
return { data: response.data };
|
||||
} catch (error) {
|
||||
console.error('更新评查结果失败:', error);
|
||||
return {
|
||||
@@ -1042,25 +909,20 @@ export async function confirmReviewResults(documentId: string, request: Request)
|
||||
return { error: '文档ID不能为空', status: 400 };
|
||||
}
|
||||
|
||||
// 调用后端API确认文档审核完成
|
||||
// 接口: PATCH /admin/v2/evaluations/documents/{document_id}/confirm
|
||||
const response = await apiRequest<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
code?: number;
|
||||
message?: string;
|
||||
data: {
|
||||
document_id: number;
|
||||
audit_status: number;
|
||||
documentId?: number;
|
||||
auditStatus?: number;
|
||||
};
|
||||
}>(
|
||||
`/admin/v2/evaluations/documents/${documentId}/confirm`,
|
||||
`/api/v3/documents/${documentId}/confirm`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${frontendJWT}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: {
|
||||
audit_status: 1
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -1072,8 +934,8 @@ export async function confirmReviewResults(documentId: string, request: Request)
|
||||
}
|
||||
|
||||
// 成功响应
|
||||
if (response.data?.success) {
|
||||
return { data: { auditStatus: response.data.data?.audit_status || 1 } };
|
||||
if (response.data?.data) {
|
||||
return { data: { auditStatus: response.data.data?.auditStatus || 1 } };
|
||||
}
|
||||
|
||||
// 数据为空或格式不正确
|
||||
|
||||
@@ -29,8 +29,7 @@ import { type MetaFunction, type LoaderFunctionArgs, type ActionFunctionArgs } f
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { useNavigate, useLoaderData, useFetcher, useRevalidator } from "@remix-run/react";
|
||||
import reviewsStyles from "~/styles/reviews.css?url";
|
||||
import { getReviewPoints, getReviewPoints_fromApi, getUnifiedEvaluationResults, updateReviewResult, confirmReviewResults } from "~/api/evaluation_points/reviews";
|
||||
import { postgrestGet } from "~/api/postgrest-client";
|
||||
import { getReviewPoints_fromApi, getUnifiedEvaluationResults, updateReviewResult, confirmReviewResults } from "~/api/evaluation_points/reviews";
|
||||
import { toastService } from "~/components/ui/Toast";
|
||||
import { Modal } from "~/components/ui/Modal";
|
||||
import { UploadArea, type UploadAreaRef } from "~/components/ui/UploadArea";
|
||||
@@ -189,27 +188,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
return Response.json({ result: false, message: '文件ID不能为空' });
|
||||
}
|
||||
|
||||
// 补充 pointCode 到 reviewPoints(直接查 DB,不受 Vite tree-shake 影响)
|
||||
async function patchPointCodes(points: any[], jwt: string) {
|
||||
try {
|
||||
const pointIds = points.map((p: any) => p.pointId).filter(Boolean);
|
||||
if (pointIds.length === 0) return;
|
||||
const resp = await postgrestGet<any>('/api/postgrest/proxy/evaluation_points', {
|
||||
select: 'id,code',
|
||||
filter: { id: `in.(${[...new Set(pointIds)].join(',')})` },
|
||||
token: jwt,
|
||||
});
|
||||
// resp.data 可能是 {code:200, data:[...]} 或直接 [...]
|
||||
const raw = resp.data;
|
||||
const epList = Array.isArray(raw) ? raw : (raw?.data && Array.isArray(raw.data) ? raw.data : []);
|
||||
const codeMap: Record<string, string> = {};
|
||||
epList.forEach((ep: any) => { if (ep.code) codeMap[String(ep.id)] = ep.code; });
|
||||
points.forEach((p: any) => { p.pointCode = codeMap[String(p.pointId)] || ''; });
|
||||
} catch (e) {
|
||||
console.error('[Reviews Loader] patchPointCodes error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户会话信息
|
||||
const { getUserSession } = await import("~/api/login/auth.server");
|
||||
const { userInfo, frontendJWT } = await getUserSession(request);
|
||||
@@ -218,9 +196,9 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
// 先尝试新的统一评查接口
|
||||
const unifiedData = await getUnifiedEvaluationResults(id, request);
|
||||
|
||||
// 如果统一接口返回错误或flow_type为legacy,使用原有API
|
||||
// 如果统一接口返回错误或 flow_type 为 legacy,直接走新后端聚合接口
|
||||
if ('error' in unifiedData || !unifiedData.flow_type) {
|
||||
console.log("[Reviews Loader] 统一接口不可用,使用旧接口...");
|
||||
console.log("[Reviews Loader] 统一接口不可用,直接尝试 review-points 聚合接口...");
|
||||
const reviewData = await getReviewPoints_fromApi(id, request);
|
||||
|
||||
if ('error' in reviewData && reviewData.error) {
|
||||
@@ -229,7 +207,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
}
|
||||
|
||||
if ('document' in reviewData && 'data' in reviewData && 'reviewInfo' in reviewData && 'stats' in reviewData) {
|
||||
await patchPointCodes(reviewData.data as any[], frontendJWT);
|
||||
return Response.json({
|
||||
previousRoute: previousRoute,
|
||||
document: reviewData.document,
|
||||
@@ -277,7 +254,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
postAction: '',
|
||||
}));
|
||||
const allReviewPoints = [...existingPoints, ...notApplicablePoints];
|
||||
await patchPointCodes(allReviewPoints, frontendJWT);
|
||||
|
||||
return Response.json({
|
||||
previousRoute: previousRoute,
|
||||
@@ -300,7 +276,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
scoredSummary: unifiedData.summary
|
||||
});
|
||||
} else {
|
||||
// legacy 流程但统一接口可用,也走原有逻辑
|
||||
// legacy 流程但统一接口可用,也统一走 review-points 聚合接口
|
||||
const reviewData = await getReviewPoints_fromApi(id, request);
|
||||
if ('error' in reviewData && reviewData.error) {
|
||||
return Response.json({ result: false, message: reviewData.error });
|
||||
|
||||
Reference in New Issue
Block a user