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 { 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 dayjs from "dayjs";
|
||||||
import { getUserSession } from "~/api/login/auth.server";
|
import { getUserSession } from "~/api/login/auth.server";
|
||||||
import { apiRequest } from "../axios-client";
|
import { apiRequest } from "../axios-client";
|
||||||
@@ -187,10 +187,10 @@ export async function getReviewPoints(fileId: string, request: Request) {
|
|||||||
return { error: '用户身份验证失败', status: 401 };
|
return { error: '用户身份验证失败', status: 401 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// const userId = userInfo.user_id.toString();
|
const userId = userInfo.user_id.toString();
|
||||||
|
|
||||||
// 首先先获取这个文档的数据
|
// 首先获取当前文档详情,优先走新后端接口
|
||||||
const documentData = await getDocumentWithNoUserId(fileId, frontendJWT);
|
const documentData = await getDocument(fileId, userId, frontendJWT);
|
||||||
if (documentData.error) {
|
if (documentData.error) {
|
||||||
console.error("获取文档数据错误:", documentData.error);
|
console.error("获取文档数据错误:", documentData.error);
|
||||||
return Response.json({ error: documentData.error }, { status: documentData.status || 500 });
|
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);
|
const contractStructureComparisonResponse = await postgrestGet('/api/postgrest/proxy/contract_structure_comparison', contractStructureComparisonParams);
|
||||||
// console.log('contract_structure_comparison', contractStructureComparisonResponse)
|
// console.log('contract_structure_comparison', contractStructureComparisonResponse)
|
||||||
|
|
||||||
|
let contractStructureComparisonData: ContractStructureComparison[] | null = null;
|
||||||
if (contractStructureComparisonResponse.error) {
|
if (contractStructureComparisonResponse.error) {
|
||||||
console.error("获取文档附件数据错误:", contractStructureComparisonResponse.error);
|
console.warn("获取文档附件数据失败,降级为空附件对比数据:", contractStructureComparisonResponse.error);
|
||||||
return Response.json({ error: contractStructureComparisonResponse.error }, { status: contractStructureComparisonResponse.status || 500 });
|
} else {
|
||||||
|
contractStructureComparisonData = extractApiData<ContractStructureComparison[]>(contractStructureComparisonResponse.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const contractStructureComparisonData = extractApiData<ContractStructureComparison[]>(contractStructureComparisonResponse.data);
|
|
||||||
|
|
||||||
// console.log('文档附件的数据', JSON.stringify(contractStructureComparisonData, null, 2));
|
// console.log('文档附件的数据', JSON.stringify(contractStructureComparisonData, null, 2));
|
||||||
|
|
||||||
// 解析比对结果
|
// 解析比对结果
|
||||||
@@ -330,10 +330,12 @@ export async function getReviewPoints(fileId: string, request: Request) {
|
|||||||
token: frontendJWT
|
token: frontendJWT
|
||||||
};
|
};
|
||||||
const manualReviewPointsResponse = await postgrestGet('/api/postgrest/proxy/audit_status', manualReviewPointsParams);
|
const manualReviewPointsResponse = await postgrestGet('/api/postgrest/proxy/audit_status', manualReviewPointsParams);
|
||||||
|
let manualReviewPointsData: AuditStatus[] | null = null;
|
||||||
if (manualReviewPointsResponse.error) {
|
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的映射
|
// 构建评查点ID到editAuditStatus的映射
|
||||||
const editAuditStatusMap = new Map<string | number, {id: string | number, status: number, message: string}>();
|
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);
|
const scoringProposalsResponse = await postgrestGet('/api/postgrest/proxy/cross_scoring_proposals', scoringProposalsParams);
|
||||||
|
|
||||||
|
let scoringProposalsData: ScoringProposal[] = [];
|
||||||
if (scoringProposalsResponse.error) {
|
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 };
|
return { error: '评查结果ID不能为空', status: 400 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否是重新审核操作
|
const response = await apiRequest<{
|
||||||
const isReview = result === 'review';
|
code?: number;
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// 步骤1: 调用3.1接口更新评查结果(如果不是重新审核操作)
|
|
||||||
// ============================================
|
|
||||||
if (!isReview) {
|
|
||||||
// 构建请求数据
|
|
||||||
const updateResultData: {
|
|
||||||
result?: 'true' | 'false';
|
|
||||||
message?: string;
|
message?: string;
|
||||||
} = {
|
data?: {
|
||||||
result: result === 'true' ? 'true' : 'false',
|
reviewPointResultId: number;
|
||||||
message: message
|
editAuditStatusId: number;
|
||||||
};
|
editAuditStatus: number;
|
||||||
|
overrideResult: boolean | null;
|
||||||
// 调用 3.1 接口: PATCH /admin/v2/evaluations/results/{result_id}
|
|
||||||
const resultResponse = await apiRequest<{
|
|
||||||
success: boolean;
|
|
||||||
message: string;
|
message: string;
|
||||||
data: {
|
|
||||||
result_id: number;
|
|
||||||
updated_fields: string[];
|
|
||||||
};
|
};
|
||||||
}>(
|
}>(
|
||||||
`/admin/v2/evaluations/results/${resultId}`,
|
`/api/v3/review-points/${resultId}/audit`,
|
||||||
{
|
{
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${frontendJWT}`,
|
'Authorization': `Bearer ${frontendJWT}`,
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
data: updateResultData
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
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 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================
|
|
||||||
// 步骤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: {
|
data: {
|
||||||
audit_status_id: number;
|
result,
|
||||||
updated_fields: string[];
|
message
|
||||||
};
|
}
|
||||||
}>(
|
|
||||||
`/admin/v2/evaluations/audit-status/${editAuditStatusId}`,
|
|
||||||
{
|
|
||||||
method: 'PATCH',
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${frontendJWT}`,
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
data: updateAuditData
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (auditStatusResponse.error) {
|
if (response.error) {
|
||||||
console.error('❌ [updateReviewResult] 3.3接口调用失败:', auditStatusResponse.error);
|
console.error('❌ [updateReviewResult] 新接口调用失败:', response.error);
|
||||||
return { error: auditStatusResponse.error, status: auditStatusResponse.status || 500 };
|
return { error: response.error, status: response.status || 500 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!auditStatusResponse.data?.success) {
|
return { data: response.data };
|
||||||
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 };
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新评查结果失败:', error);
|
console.error('更新评查结果失败:', error);
|
||||||
return {
|
return {
|
||||||
@@ -1042,25 +909,20 @@ export async function confirmReviewResults(documentId: string, request: Request)
|
|||||||
return { error: '文档ID不能为空', status: 400 };
|
return { error: '文档ID不能为空', status: 400 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用后端API确认文档审核完成
|
|
||||||
// 接口: PATCH /admin/v2/evaluations/documents/{document_id}/confirm
|
|
||||||
const response = await apiRequest<{
|
const response = await apiRequest<{
|
||||||
success: boolean;
|
code?: number;
|
||||||
message: string;
|
message?: string;
|
||||||
data: {
|
data: {
|
||||||
document_id: number;
|
documentId?: number;
|
||||||
audit_status: number;
|
auditStatus?: number;
|
||||||
};
|
};
|
||||||
}>(
|
}>(
|
||||||
`/admin/v2/evaluations/documents/${documentId}/confirm`,
|
`/api/v3/documents/${documentId}/confirm`,
|
||||||
{
|
{
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${frontendJWT}`,
|
'Authorization': `Bearer ${frontendJWT}`,
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
|
||||||
data: {
|
|
||||||
audit_status: 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -1072,8 +934,8 @@ export async function confirmReviewResults(documentId: string, request: Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 成功响应
|
// 成功响应
|
||||||
if (response.data?.success) {
|
if (response.data?.data) {
|
||||||
return { data: { auditStatus: response.data.data?.audit_status || 1 } };
|
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 { useState, useEffect, useCallback, useRef } from "react";
|
||||||
import { useNavigate, useLoaderData, useFetcher, useRevalidator } from "@remix-run/react";
|
import { useNavigate, useLoaderData, useFetcher, useRevalidator } from "@remix-run/react";
|
||||||
import reviewsStyles from "~/styles/reviews.css?url";
|
import reviewsStyles from "~/styles/reviews.css?url";
|
||||||
import { getReviewPoints, getReviewPoints_fromApi, getUnifiedEvaluationResults, updateReviewResult, confirmReviewResults } from "~/api/evaluation_points/reviews";
|
import { getReviewPoints_fromApi, getUnifiedEvaluationResults, updateReviewResult, confirmReviewResults } from "~/api/evaluation_points/reviews";
|
||||||
import { postgrestGet } from "~/api/postgrest-client";
|
|
||||||
import { toastService } from "~/components/ui/Toast";
|
import { toastService } from "~/components/ui/Toast";
|
||||||
import { Modal } from "~/components/ui/Modal";
|
import { Modal } from "~/components/ui/Modal";
|
||||||
import { UploadArea, type UploadAreaRef } from "~/components/ui/UploadArea";
|
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不能为空' });
|
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 { getUserSession } = await import("~/api/login/auth.server");
|
||||||
const { userInfo, frontendJWT } = await getUserSession(request);
|
const { userInfo, frontendJWT } = await getUserSession(request);
|
||||||
@@ -218,9 +196,9 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
|||||||
// 先尝试新的统一评查接口
|
// 先尝试新的统一评查接口
|
||||||
const unifiedData = await getUnifiedEvaluationResults(id, request);
|
const unifiedData = await getUnifiedEvaluationResults(id, request);
|
||||||
|
|
||||||
// 如果统一接口返回错误或flow_type为legacy,使用原有API
|
// 如果统一接口返回错误或 flow_type 为 legacy,直接走新后端聚合接口
|
||||||
if ('error' in unifiedData || !unifiedData.flow_type) {
|
if ('error' in unifiedData || !unifiedData.flow_type) {
|
||||||
console.log("[Reviews Loader] 统一接口不可用,使用旧接口...");
|
console.log("[Reviews Loader] 统一接口不可用,直接尝试 review-points 聚合接口...");
|
||||||
const reviewData = await getReviewPoints_fromApi(id, request);
|
const reviewData = await getReviewPoints_fromApi(id, request);
|
||||||
|
|
||||||
if ('error' in reviewData && reviewData.error) {
|
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) {
|
if ('document' in reviewData && 'data' in reviewData && 'reviewInfo' in reviewData && 'stats' in reviewData) {
|
||||||
await patchPointCodes(reviewData.data as any[], frontendJWT);
|
|
||||||
return Response.json({
|
return Response.json({
|
||||||
previousRoute: previousRoute,
|
previousRoute: previousRoute,
|
||||||
document: reviewData.document,
|
document: reviewData.document,
|
||||||
@@ -277,7 +254,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
|||||||
postAction: '',
|
postAction: '',
|
||||||
}));
|
}));
|
||||||
const allReviewPoints = [...existingPoints, ...notApplicablePoints];
|
const allReviewPoints = [...existingPoints, ...notApplicablePoints];
|
||||||
await patchPointCodes(allReviewPoints, frontendJWT);
|
|
||||||
|
|
||||||
return Response.json({
|
return Response.json({
|
||||||
previousRoute: previousRoute,
|
previousRoute: previousRoute,
|
||||||
@@ -300,7 +276,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
|||||||
scoredSummary: unifiedData.summary
|
scoredSummary: unifiedData.summary
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// legacy 流程但统一接口可用,也走原有逻辑
|
// legacy 流程但统一接口可用,也统一走 review-points 聚合接口
|
||||||
const reviewData = await getReviewPoints_fromApi(id, request);
|
const reviewData = await getReviewPoints_fromApi(id, request);
|
||||||
if ('error' in reviewData && reviewData.error) {
|
if ('error' in reviewData && reviewData.error) {
|
||||||
return Response.json({ result: false, message: reviewData.error });
|
return Response.json({ result: false, message: reviewData.error });
|
||||||
|
|||||||
Reference in New Issue
Block a user