修改评查点结果显示
This commit is contained in:
@@ -73,6 +73,7 @@ interface ReviewPointResult {
|
||||
suggestion: string;
|
||||
result?: boolean;
|
||||
score: number;
|
||||
evaluatedPointResultsLog?: Array<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
// 定义统计数据类型
|
||||
@@ -241,6 +242,11 @@ export async function getReviewPoints(fileId: string) {
|
||||
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_point_results_log中获取
|
||||
// const evaluatedPointResultsLog = result.evaluated_point_results_log;
|
||||
// console.log('evaluatedPointResultsLog-------', evaluatedPointResultsLog);
|
||||
|
||||
|
||||
// 从 evaluated_results 中提取数据
|
||||
let message = '';
|
||||
@@ -328,7 +334,121 @@ export async function getReviewPoints(fileId: string) {
|
||||
// }
|
||||
|
||||
// 评查配置: point.evaluation_config
|
||||
evaluationConfig: point.evaluation_config || {}
|
||||
evaluationConfig: point.evaluation_config || {},
|
||||
|
||||
// evaluatedPointResultsLog: evaluatedPointResultsLog || {}
|
||||
evaluatedPointResultsLog: [
|
||||
{
|
||||
"id": "1",
|
||||
"type": "consistency",
|
||||
"config": {
|
||||
"logic": "and",
|
||||
"pairs": [
|
||||
{
|
||||
"sourceField": {"现场笔录-被检查人名称":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-营业执照-名称":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"现场笔录-法定代表人(负责人)":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-营业执照-法定代表人":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"现场笔录-烟草专卖许可证号码":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-烟草专卖零售许可证-许可证号":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"证据复制(提取)单-烟草专卖零售许可证-企业名称":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-营业执照-名称":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"证据复制(提取)单-烟草专卖零售许可证-负责人姓名":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-营业执照-法定代表人":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"立案报告表-当事人-单位-名称":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-营业执照-名称":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"立案报告表-当事人-单位-法定代表人(负责人)":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-营业执照-法定代表人":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"立案报告表-当事人-单位-地址":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-营业执照-住所":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
}
|
||||
],
|
||||
"selectedFields": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"type": "consistency",
|
||||
"config": {
|
||||
"logic": "and",
|
||||
"pairs": [
|
||||
{
|
||||
"sourceField": {"现场笔录-被检查人姓名":{page: 1,value: '张三'}},
|
||||
"targetField": {"立案报告表-当事人-个人(个体工商户)-姓名":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"立案报告表-当事人-个人(个体工商户)-姓名":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-居民身份证-姓名":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"现场笔录-性别":{page: 1,value: '张三'}},
|
||||
"targetField": {"立案报告表-当事人-个人(个体工商户)-性别":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"立案报告表-当事人-个人(个体工商户)-性别":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-居民身份证-性别":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"现场笔录-证件类型及号码":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-居民身份证-公民身份号码":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"现场笔录-地址":{page: 1,value: '张三'}},
|
||||
"targetField": {"立案报告表-当事人-个人(个体工商户)-住址":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
},
|
||||
{
|
||||
"sourceField": {"立案报告表-当事人-个人(个体工商户)-住址":{page: 1,value: '张三'}},
|
||||
"targetField": {"证据复制(提取)单-居民身份证-住址":{page: 1,value: '张三'}},
|
||||
"compareMethod": "exact",
|
||||
"result": true
|
||||
}
|
||||
],
|
||||
"selectedFields": []
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ export interface ReviewPoint {
|
||||
};
|
||||
}>;
|
||||
};
|
||||
evaluatedPointResultsLog?: Array<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
// 统计数据类型
|
||||
@@ -200,11 +201,11 @@ export function ReviewPointsList({
|
||||
// 过滤"错误"状态
|
||||
matchesStatus = point.result === false && point.status === 'error';
|
||||
}
|
||||
console.log('筛选point', point);
|
||||
// console.log('筛选point', point);
|
||||
|
||||
return matchesSearch && matchesStatus;
|
||||
});
|
||||
console.log('筛选filteredReviewPoints', filteredReviewPoints);
|
||||
// console.log('筛选filteredReviewPoints', filteredReviewPoints);
|
||||
|
||||
/**
|
||||
* 处理一键替换操作
|
||||
@@ -501,7 +502,7 @@ export function ReviewPointsList({
|
||||
|
||||
// 将content按照规则分组
|
||||
contentEntries.forEach(entry => {
|
||||
const [key, value] = entry;
|
||||
const [key] = entry;
|
||||
|
||||
// 检查是否属于某个consistency规则
|
||||
let assigned = false;
|
||||
@@ -751,6 +752,292 @@ export function ReviewPointsList({
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 渲染评查点一致性的规则的样式
|
||||
* @param reviewPoint 评查点
|
||||
* @returns 评查点一致性的规则的样式
|
||||
*/
|
||||
const renderConsistencyRule = (singleReviewPoint: Record<string, unknown>) => {
|
||||
if (!singleReviewPoint || Object.keys(singleReviewPoint).length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 检查是否存在配置和pairs数组
|
||||
const config = singleReviewPoint.config as { logic?: string; pairs?: Array<{ sourceField: Record<string, { page: number; value: string }>; targetField: Record<string, { page: number; value: string }>; result: boolean }>; selectedFields?: string[] } | undefined;
|
||||
if (!config || !config.pairs || !Array.isArray(config.pairs) || config.pairs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 处理配对数据
|
||||
const pairs = config.pairs;
|
||||
|
||||
// 查找链条关系
|
||||
const findChains = () => {
|
||||
type ChainItem = {
|
||||
field: string;
|
||||
data: {
|
||||
key: string;
|
||||
page: number;
|
||||
value: string
|
||||
};
|
||||
result: boolean
|
||||
};
|
||||
|
||||
const chains: Array<Array<ChainItem>> = [];
|
||||
const visited = new Set<string>();
|
||||
|
||||
// 构建字段映射关系
|
||||
const fieldMap = new Map<string, Array<{
|
||||
targetField: string;
|
||||
data: {
|
||||
source: { key: string; page: number; value: string };
|
||||
target: { key: string; page: number; value: string };
|
||||
};
|
||||
result: boolean
|
||||
}>>();
|
||||
|
||||
pairs.forEach(pair => {
|
||||
// 提取源字段和目标字段的名称
|
||||
const sourceFieldKey = Object.keys(pair.sourceField)[0];
|
||||
const targetFieldKey = Object.keys(pair.targetField)[0];
|
||||
|
||||
if (!fieldMap.has(sourceFieldKey)) {
|
||||
fieldMap.set(sourceFieldKey, []);
|
||||
}
|
||||
|
||||
fieldMap.get(sourceFieldKey)?.push({
|
||||
targetField: targetFieldKey,
|
||||
data: {
|
||||
source: { key: sourceFieldKey, ...pair.sourceField[sourceFieldKey] },
|
||||
target: { key: targetFieldKey, ...pair.targetField[targetFieldKey] }
|
||||
},
|
||||
result: pair.result
|
||||
});
|
||||
});
|
||||
console.log('fieldMap-------', fieldMap);
|
||||
|
||||
// 查找链条的起始点(只作为源不作为目标的字段)
|
||||
const startPoints = new Set<string>();
|
||||
for (const [key] of fieldMap.entries()) {
|
||||
let isTarget = false;
|
||||
for (const pair of pairs) {
|
||||
const targetFieldKey = Object.keys(pair.targetField)[0];
|
||||
if (targetFieldKey === key) {
|
||||
isTarget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isTarget) {
|
||||
startPoints.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
// 从每个起始点开始构建链条
|
||||
for (const startPoint of startPoints) {
|
||||
if (visited.has(startPoint)) continue;
|
||||
|
||||
const chain: Array<ChainItem> = [];
|
||||
let currentField = startPoint;
|
||||
|
||||
// 向后构建链条
|
||||
while (fieldMap.has(currentField)) {
|
||||
const targets = fieldMap.get(currentField);
|
||||
if (!targets || targets.length === 0) break;
|
||||
|
||||
// 找到第一个未访问的目标
|
||||
let nextTarget = null;
|
||||
for (const target of targets) {
|
||||
if (!visited.has(target.targetField)) {
|
||||
nextTarget = target;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nextTarget) break;
|
||||
|
||||
// 添加源字段到链条
|
||||
if (chain.length === 0) {
|
||||
chain.push({
|
||||
field: currentField,
|
||||
data: nextTarget.data.source,
|
||||
result: nextTarget.result
|
||||
});
|
||||
}
|
||||
|
||||
// 添加目标字段到链条
|
||||
chain.push({
|
||||
field: nextTarget.targetField,
|
||||
data: nextTarget.data.target,
|
||||
result: nextTarget.result
|
||||
});
|
||||
|
||||
// 标记为已访问
|
||||
visited.add(currentField);
|
||||
visited.add(nextTarget.targetField);
|
||||
|
||||
// 移动到下一个字段
|
||||
currentField = nextTarget.targetField;
|
||||
}
|
||||
|
||||
if (chain.length > 0) {
|
||||
chains.push(chain);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理没有找到的孤立对
|
||||
for (const pair of pairs) {
|
||||
const sourceFieldKey = Object.keys(pair.sourceField)[0];
|
||||
const targetFieldKey = Object.keys(pair.targetField)[0];
|
||||
|
||||
if (!visited.has(sourceFieldKey) || !visited.has(targetFieldKey)) {
|
||||
const isolatedPair: Array<ChainItem> = [
|
||||
{
|
||||
field: sourceFieldKey,
|
||||
data: { key: sourceFieldKey, ...pair.sourceField[sourceFieldKey] },
|
||||
result: pair.result
|
||||
},
|
||||
{
|
||||
field: targetFieldKey,
|
||||
data: { key: targetFieldKey, ...pair.targetField[targetFieldKey] },
|
||||
result: pair.result
|
||||
}
|
||||
];
|
||||
|
||||
chains.push(isolatedPair);
|
||||
visited.add(sourceFieldKey);
|
||||
visited.add(targetFieldKey);
|
||||
}
|
||||
}
|
||||
|
||||
return chains;
|
||||
};
|
||||
|
||||
const chains = findChains();
|
||||
|
||||
return (
|
||||
<div className="mt-3">
|
||||
<div className="comparison-group">
|
||||
{chains.map((chain, chainIndex) => {
|
||||
const isLongChain = chain.length > 2;
|
||||
const result = chain[0].result;
|
||||
|
||||
// 确定样式类名
|
||||
const itemClassName = result
|
||||
? "comparison-item match"
|
||||
: "comparison-item mismatch";
|
||||
|
||||
// 如果是长链(3个或以上元素)
|
||||
if (isLongChain) {
|
||||
return (
|
||||
<div
|
||||
key={`chain_${chainIndex}`}
|
||||
className={`${itemClassName} border border-${result ? 'green' : 'yellow'}-200 rounded-md overflow-hidden mb-2 bg-${result ? 'green' : 'yellow'}-50`}
|
||||
>
|
||||
<div className="comparison-values flex flex-col w-full">
|
||||
<div className="value-box p-2 pb-1">
|
||||
<div className="value-source text-xs text-gray-500 mb-1">
|
||||
{chain.map((item, idx) => (
|
||||
<span key={idx} className="inline-block">
|
||||
{item.field}
|
||||
{idx < chain.length - 1 && (
|
||||
<i className="ri-arrow-left-right-line text-xs mx-1 text-primary"></i>
|
||||
)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex flex-col space-y-2">
|
||||
{chain.map((item, idx) => (
|
||||
<button
|
||||
key={`item_${idx}`}
|
||||
className="value-content p-1 text-xs border-b border-dashed border-gray-200 last:border-b-0 text-left hover:bg-white rounded transition-colors"
|
||||
onClick={() => {
|
||||
if (item.data.page) {
|
||||
// 假设onReviewPointSelect在作用域内可用
|
||||
const reviewPointId = singleReviewPoint.id as string;
|
||||
if (reviewPointId && typeof onReviewPointSelect === 'function') {
|
||||
onReviewPointSelect(reviewPointId, item.data.page);
|
||||
}
|
||||
}
|
||||
}}
|
||||
aria-label={`查看${item.field}内容详情`}
|
||||
>
|
||||
<div className="flex justify-between">
|
||||
<span className="font-medium">{item.field}:</span>
|
||||
<span>{item.data.value?.toString() || ''}</span>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="status-indicator w-8 flex items-center justify-center">
|
||||
{result ? (
|
||||
<i className="ri-check-line text-success text-base"></i>
|
||||
) : (
|
||||
<i className="ri-alert-line text-warning text-base"></i>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 如果是标准的成对比较(2个元素)
|
||||
return (
|
||||
<div
|
||||
key={`pair_${chainIndex}`}
|
||||
className={`${itemClassName} border border-${result ? 'green' : 'yellow'}-200 rounded-md overflow-hidden mb-2 bg-${result ? 'green' : 'yellow'}-50 flex`}
|
||||
>
|
||||
<div className="field-label bg-gray-50 p-2 text-xs font-medium text-gray-500 border-r border-gray-200 min-w-[70px] items-center hidden">
|
||||
{chain[0].field.split('-').pop()}
|
||||
</div>
|
||||
<div className="comparison-values flex flex-1">
|
||||
<button
|
||||
className="value-box flex-1 p-2 border-r border-gray-200 text-left hover:bg-white transition-colors"
|
||||
onClick={() => {
|
||||
if (chain[0].data.page) {
|
||||
const reviewPointId = singleReviewPoint.id as string;
|
||||
if (reviewPointId && typeof onReviewPointSelect === 'function') {
|
||||
onReviewPointSelect(reviewPointId, chain[0].data.page);
|
||||
}
|
||||
}
|
||||
}}
|
||||
aria-label={`查看${chain[0].field}内容详情`}
|
||||
>
|
||||
<div className="value-source text-xs text-gray-500 mb-1">{chain[0].field}</div>
|
||||
<div className="value-content text-xs">{chain[0].data.value?.toString() || ''}</div>
|
||||
</button>
|
||||
<button
|
||||
className="value-box flex-1 p-2 text-left hover:bg-white transition-colors"
|
||||
onClick={() => {
|
||||
if (chain[1].data.page) {
|
||||
const reviewPointId = singleReviewPoint.id as string;
|
||||
if (reviewPointId && typeof onReviewPointSelect === 'function') {
|
||||
onReviewPointSelect(reviewPointId, chain[1].data.page);
|
||||
}
|
||||
}
|
||||
}}
|
||||
aria-label={`查看${chain[1].field}内容详情`}
|
||||
>
|
||||
<div className="value-source text-xs text-gray-500 mb-1">{chain[1].field}</div>
|
||||
<div className="value-content text-xs">{chain[1].data.value?.toString() || ''}</div>
|
||||
</button>
|
||||
</div>
|
||||
<div className="status-indicator tooltip w-8 flex items-center justify-center">
|
||||
{result ? (
|
||||
<i className="ri-check-line text-success text-base"></i>
|
||||
) : (
|
||||
<i className="ri-alert-line text-warning text-base"></i>
|
||||
)}
|
||||
<span className="tooltiptext">{result ? '一致' : '不一致'}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 渲染评查点内容与建议
|
||||
* @param reviewPoint 评查点
|
||||
@@ -857,7 +1144,7 @@ export function ReviewPointsList({
|
||||
)}
|
||||
{/* 评查点内容显示区域 */}
|
||||
{reviewPoint.content && Object.entries(reviewPoint.content).length > 0 && (
|
||||
<div className="p-2 bg-white rounded border border-gray-200 text-xs mb-3 select-text">
|
||||
<div className="bg-white rounded border-gray-200 text-xs mb-3 select-text">
|
||||
{/* 修改评查结果的结构之后,显示新的结构 */}
|
||||
{renderContent(reviewPoint, true)}
|
||||
</div>
|
||||
@@ -1142,6 +1429,9 @@ export function ReviewPointsList({
|
||||
{/* 人工审核注释 */}
|
||||
{renderHumanReviewNote(reviewPoint)}
|
||||
|
||||
{/* 评查点一致性的规则的样式渲染 */}
|
||||
{renderConsistencyRule(reviewPoint.evaluatedPointResultsLog?.[0] || {})}
|
||||
|
||||
{/* 评查点内容和操作 */}
|
||||
{renderReviewPointContent(reviewPoint)}
|
||||
</div>
|
||||
|
||||
@@ -593,7 +593,7 @@ export default function ReviewDetails() {
|
||||
{activeTab === 'preview' && (
|
||||
<div className="flex flex-col lg:flex-row space-y-4 lg:space-y-0 lg:space-x-4">
|
||||
{/* 左侧:文件预览 */}
|
||||
<div className="w-full lg:w-2/3">
|
||||
<div className="w-full lg:w-3/5">
|
||||
<FilePreview
|
||||
fileContent={document}
|
||||
reviewPoints={reviewData.reviewPoints}
|
||||
@@ -603,7 +603,7 @@ export default function ReviewDetails() {
|
||||
</div>
|
||||
|
||||
{/* 右侧:评查结果 */}
|
||||
<div className="w-full lg:w-1/3">
|
||||
<div className="w-full lg:w-2/5">
|
||||
<ReviewPointsList
|
||||
reviewPoints={reviewData.reviewPoints}
|
||||
statistics={reviewData.statistics}
|
||||
|
||||
Reference in New Issue
Block a user