一致性规则渲染效果

This commit is contained in:
2025-05-29 18:31:33 +08:00
parent 2ff60421aa
commit 099d92f9ed
2 changed files with 134 additions and 31 deletions
+32 -2
View File
@@ -344,12 +344,42 @@ export async function getReviewPoints(fileId: string) {
"config": {
"logic": "and",
"pairs": [
{
"sourceField": {"a":{page: 1,value: '张三'}},
"targetField": {"b":{page: 1,value: '张三'}},
"compareMethod": "exact",
"result": true
},
{
"sourceField": {"b":{page: 1,value: '张三'}},
"targetField": {"c":{page: 1,value: '张三'}},
"compareMethod": "exact",
"result": false
},
{
"sourceField": {"c":{page: 1,value: '张三'}},
"targetField": {"d":{page: 1,value: '张三'}},
"compareMethod": "exact",
"result": true
},
{
"sourceField": {"d":{page: 1,value: '张三'}},
"targetField": {"e":{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: '张三'}},
@@ -364,9 +394,9 @@ export async function getReviewPoints(fileId: string) {
},
{
"sourceField": {"证据复制(提取)单-烟草专卖零售许可证-企业名称":{page: 1,value: '张三'}},
"targetField": {"证据复制(提取)单-营业执照-名称":{page: 1,value: '张三'}},
"targetField": {"证据复制(提取)单-营业执照-名称":{page: 1,value: '张三拉萨看得见佛i啊是觉得离开房间啊善良的是的链接发了上帝就发垃圾袋的时间佛爱上立刻就阿拉山口大家分厘卡即使灯笼裤飞机啊顺利打开解放拉萨酱豆腐立刻阿萨到了经历多空双方叫阿里的肌肤垃圾收到了看见螺丝钉解放了啊撒旦解放垃圾的等级分类教师劳动纠纷爱丽丝的开发教师的肌肤啊撒旦解放考虑进来阿斯兰的看法骄傲'}},
"compareMethod": "exact",
"result": true
"result": false
},
{
"sourceField": {"证据复制(提取)单-烟草专卖零售许可证-负责人姓名":{page: 1,value: '张三'}},
+102 -29
View File
@@ -733,7 +733,8 @@ export function ReviewPointsList({
<div className="relative text-container max-h-96 group-hover:overflow-auto overflow-hidden">
<p
className="text-xs text-left select-text block overflow-hidden !line-clamp-2
group-hover:!line-clamp-none group-hover:bg-white group-hover:shadow-md group-hover:z-10 group-hover:relative px-1 rounded transition-all duration-300 ease-in-out cursor-text"
group-hover:!line-clamp-none group-hover:bg-white group-hover:shadow-md
group-hover:z-10 group-hover:relative px-1 rounded transition-all duration-300 ease-in-out cursor-text"
// title={value.value?.toString() || ''}
// style={{ userSelect: 'all' }}
>
@@ -763,7 +764,17 @@ export function ReviewPointsList({
}
// 检查是否存在配置和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;
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;
compareMethod?: string;
}>;
selectedFields?: string[]
} | undefined;
if (!config || !config.pairs || !Array.isArray(config.pairs) || config.pairs.length === 0) {
return null;
}
@@ -793,7 +804,8 @@ export function ReviewPointsList({
source: { key: string; page: number; value: string };
target: { key: string; page: number; value: string };
};
result: boolean
result: boolean;
compareMethod?: string;
}>>();
pairs.forEach(pair => {
@@ -811,10 +823,11 @@ export function ReviewPointsList({
source: { key: sourceFieldKey, ...pair.sourceField[sourceFieldKey] },
target: { key: targetFieldKey, ...pair.targetField[targetFieldKey] }
},
result: pair.result
result: pair.result,
compareMethod: pair.compareMethod
});
});
console.log('fieldMap-------', fieldMap);
// console.log('fieldMap-------', fieldMap);
// 查找链条的起始点(只作为源不作为目标的字段)
const startPoints = new Set<string>();
@@ -831,12 +844,13 @@ export function ReviewPointsList({
startPoints.add(key);
}
}
// console.log('startPoints-------', startPoints);
// 从每个起始点开始构建链条
for (const startPoint of startPoints) {
if (visited.has(startPoint)) continue;
const chain: Array<ChainItem> = [];
const tempChain: Array<ChainItem> = [];
let currentField = startPoint;
// 向后构建链条
@@ -856,8 +870,8 @@ export function ReviewPointsList({
if (!nextTarget) break;
// 添加源字段到链条
if (chain.length === 0) {
chain.push({
if (tempChain.length === 0) {
tempChain.push({
field: currentField,
data: nextTarget.data.source,
result: nextTarget.result
@@ -865,7 +879,7 @@ export function ReviewPointsList({
}
// 添加目标字段到链条
chain.push({
tempChain.push({
field: nextTarget.targetField,
data: nextTarget.data.target,
result: nextTarget.result
@@ -879,12 +893,69 @@ export function ReviewPointsList({
currentField = nextTarget.targetField;
}
if (chain.length > 0) {
chains.push(chain);
// console.log('tempChain-------', tempChain);
// 检查是否有链条,并处理链条断点
if (tempChain.length > 0) {
// 如果链条长度大于1
if (tempChain.length > 1) {
// 存储所有拆分后的链条
const splittedChains: Array<Array<ChainItem>> = [];
// 从后往前遍历,检查每个相邻元素之间的连接
let endIndex = tempChain.length - 1;
// 从倒数第一个元素开始往前遍历
for (let i = tempChain.length - 1; i > 0; i--) {
// 检查当前元素与前一个元素的连接是否为false
// 当前元素为tempChain[i],前一个元素为tempChain[i-1]
// 连接结果存储在当前元素(tempChain[i])的result中
const connectionResult = tempChain[i].result;
// 如果连接为false,或已到达起始位置,拆分链条
if (!connectionResult) {
// 从当前断点到结束索引构建一个新链条
const newChain = tempChain.slice(i, endIndex + 1);
if (newChain.length > 1) {
splittedChains.push(newChain);
// 将当前断点的前一个元素和后一个元素组成一个新链条
const newChain_before = tempChain.slice(i-1, i+1);
console.log('newChain_before-------', newChain_before);
splittedChains.push(newChain_before);
}
// 更新结束索引为当前位置的前一个
endIndex = i - 1;
}
// 当到达第一个元素前一个位置时,需要处理剩余的链条
if (i === 1) {
// 处理剩余部分 (0 到 endIndex)
const remainingChain = tempChain.slice(0, endIndex + 1);
if (remainingChain.length > 1) {
splittedChains.push(remainingChain);
}
}
}
// 如果没有任何断点,添加整个链条
if (splittedChains.length === 0) {
splittedChains.push([...tempChain]);
}
// 将拆分的链条添加到结果中
splittedChains.reverse().forEach(chain => {
chains.push(chain);
});
} else {
// 如果链条长度为1,直接添加
chains.push([...tempChain]);
}
}
}
// console.log('chains-------', chains);
// 处理没有找到的孤立对
// 处理没有找到的孤立对(这种情况只要规则配置是没问题的,就一定不会存在孤立的情况)
for (const pair of pairs) {
const sourceFieldKey = Object.keys(pair.sourceField)[0];
const targetFieldKey = Object.keys(pair.targetField)[0];
@@ -919,7 +990,7 @@ export function ReviewPointsList({
<div className="comparison-group">
{chains.map((chain, chainIndex) => {
const isLongChain = chain.length > 2;
const result = chain[0].result;
const result = chain[1].result;
// 确定样式类名
const itemClassName = result
@@ -933,19 +1004,19 @@ export function ReviewPointsList({
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="comparison-values flex w-full">
<div className="value-box p-2 pb-1 flex-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>
<i className="ri-arrow-right-fill text-xs mx-1 text-primary"></i>
)}
</span>
))}
</div>
<div className="flex flex-col space-y-2">
<div className="flex flex-col">
{chain.map((item, idx) => (
<button
key={`item_${idx}`}
@@ -962,20 +1033,20 @@ export function ReviewPointsList({
aria-label={`查看${item.field}内容详情`}
>
<div className="flex justify-between">
<span className="font-medium">{item.field}:</span>
{/* <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 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>
</div>
);
@@ -993,10 +1064,11 @@ export function ReviewPointsList({
<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={() => {
onClick={(e) => {
if (chain[0].data.page) {
const reviewPointId = singleReviewPoint.id as string;
if (reviewPointId && typeof onReviewPointSelect === 'function') {
e.stopPropagation();
onReviewPointSelect(reviewPointId, chain[0].data.page);
}
}
@@ -1008,10 +1080,11 @@ export function ReviewPointsList({
</button>
<button
className="value-box flex-1 p-2 text-left hover:bg-white transition-colors"
onClick={() => {
onClick={(e) => {
if (chain[1].data.page) {
const reviewPointId = singleReviewPoint.id as string;
if (reviewPointId && typeof onReviewPointSelect === 'function') {
e.stopPropagation();
onReviewPointSelect(reviewPointId, chain[1].data.page);
}
}
@@ -1019,7 +1092,8 @@ export function ReviewPointsList({
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>
<div className="value-content text-xs overflow-hidden line-clamp-2 hover:line-clamp-none hover:shadow-[0_0_10px_rgba(0,0,0,0.1)]
hover: z-10 hover:overflow-auto rounded transition-all duration-300 ease-in-out cursor-text max-h-96">{chain[1].data.value?.toString() || ''}</div>
</button>
</div>
<div className="status-indicator tooltip w-8 flex items-center justify-center">
@@ -1028,7 +1102,6 @@ export function ReviewPointsList({
) : (
<i className="ri-alert-line text-warning text-base"></i>
)}
<span className="tooltiptext">{result ? '一致' : '不一致'}</span>
</div>
</div>
);