在显示评查点结果中,如果评查点是通过的,只显示通过的那一部分的规则组。如果是不通过,则显示不通过的那部分规则组。

This commit is contained in:
2025-06-01 22:46:18 +08:00
parent 8f8893d111
commit 1f21c4c2d5
5 changed files with 90 additions and 75 deletions
+1
View File
@@ -478,6 +478,7 @@ export async function getReviewPoints(fileId: string) {
// "type": "logic", // "type": "logic",
// "config": { // "config": {
// "logic": "all", // "logic": "all",
// "res": true,
// "conditions": [ // "conditions": [
// { // {
// "field": { // "field": {
+6 -6
View File
@@ -20,6 +20,12 @@ export function Sidebar({ onToggle, collapsed }: SidebarProps) {
const [expandedMenus, setExpandedMenus] = useState<Record<string, boolean>>({}); const [expandedMenus, setExpandedMenus] = useState<Record<string, boolean>>({});
const menuItems: MenuItem[] = [ const menuItems: MenuItem[] = [
{
id: 'home',
title: '系统概览',
path: '/home',
icon: 'ri-home-line'
},
{ {
id: 'contract-template', id: 'contract-template',
title: '合同模板', title: '合同模板',
@@ -40,12 +46,6 @@ export function Sidebar({ onToggle, collapsed }: SidebarProps) {
} }
] ]
}, },
{
id: 'home',
title: '系统概览',
path: '/home',
icon: 'ri-home-line'
},
{ {
id: 'file-management', id: 'file-management',
title: '文件管理', title: '文件管理',
+1 -1
View File
@@ -179,7 +179,7 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
// 如果有目标页码,并且与上次相同,提示用户 // 如果有目标页码,并且与上次相同,提示用户
if(targetPage && numPages && targetPage <= numPages && targetPage === prevTargetPageRef.current){ if(targetPage && numPages && targetPage <= numPages && targetPage === prevTargetPageRef.current){
toastService.success(`已跳转至目标页码`); // toastService.success(`已跳转至目标页码`);
} }
// 如果有目标页码,并且与上次不同或activeReviewPointId变化了,则执行跳转 // 如果有目标页码,并且与上次不同或activeReviewPointId变化了,则执行跳转
if (targetPage && numPages && targetPage <= numPages && (targetPage !== prevTargetPageRef.current || activeReviewPointResultId)) { if (targetPage && numPages && targetPage <= numPages && (targetPage !== prevTargetPageRef.current || activeReviewPointResultId)) {
+33 -20
View File
@@ -577,7 +577,7 @@ export function ReviewPointsList({
<div className="relative"> <div className="relative">
<input <input
type="text" type="text"
className="w-full border border-gray-200 rounded-md pl-8 pr-2 py-1 text-xs className="w-full border border-gray-200 rounded-md pl-8 pr-2 py-1 text-xs h-7
focus:outline-none focus:ring-1 focus:ring-green-800" focus:outline-none focus:ring-1 focus:ring-green-800"
placeholder="搜索评查点..." placeholder="搜索评查点..."
value={searchText} value={searchText}
@@ -726,13 +726,15 @@ export function ReviewPointsList({
{/* 渲染各个一致性的规则分组 */} {/* 渲染各个一致性的规则分组 */}
{reviewPoint.evaluatedPointResultsLog?.rules?.map((rule, index) => { {reviewPoint.evaluatedPointResultsLog?.rules?.map((rule, index) => {
// console.log('rule-------', rule); // console.log('rule-------', rule);
// if (rule.type === 'consistency' && rule.res === true) {
if (rule.type === 'consistency') { if (rule.type === 'consistency') {
// console.log('rule-------', rule); // if (rule.res === true && reviewPoint.result === true) {
return <div key={`rule-${index}`}> return <div key={`rule-${index}`}>
<div key="line" className=" bg-gray-50 rounded border border-gray-200 text-xs mb-3"></div> <div key="line" className=" bg-gray-50 rounded border border-gray-200 text-xs mb-3"></div>
{renderConsistencyRule(rule, reviewPoint)} {renderConsistencyRule(rule, reviewPoint)}
</div>; </div>;
// }else {
// return null;
// }
} }
if (rule.type === 'ai') { if (rule.type === 'ai') {
@@ -839,9 +841,15 @@ export function ReviewPointsList({
* @returns 评查点一致性的规则的样式 * @returns 评查点一致性的规则的样式
*/ */
const renderConsistencyRule = (singleReviewPoint: Record<string, unknown>,reviewPoint: ReviewPoint) => { const renderConsistencyRule = (singleReviewPoint: Record<string, unknown>,reviewPoint: ReviewPoint) => {
// 如果评查点结果为false,则判断单个规则是否通过,如果一致,则渲染
if (reviewPoint.result !== singleReviewPoint.res) {
return null;
}
if (!singleReviewPoint || Object.keys(singleReviewPoint).length === 0) { if (!singleReviewPoint || Object.keys(singleReviewPoint).length === 0) {
return null; return null;
} }
// console.log('singleReviewPoint-------', singleReviewPoint); // console.log('singleReviewPoint-------', singleReviewPoint);
// 检查是否存在配置和pairs数组 // 检查是否存在配置和pairs数组
const config = singleReviewPoint.config as { const config = singleReviewPoint.config as {
@@ -1126,6 +1134,7 @@ export function ReviewPointsList({
> >
<div className="comparison-values flex w-full"> <div className="comparison-values flex w-full">
<div className="value-box p-2 pb-1 flex-1"> <div className="value-box p-2 pb-1 flex-1">
{/* 展示链条 */}
<div className="value-source text-xs text-gray-500 mb-1"> <div className="value-source text-xs text-gray-500 mb-1">
{chain.map((item, idx) => ( {chain.map((item, idx) => (
<span key={idx} className="inline-block"> <span key={idx} className="inline-block">
@@ -1141,18 +1150,19 @@ export function ReviewPointsList({
</span> </span>
))} ))}
</div> </div>
{/* 展示链条的每个元素的内容 */}
<div className="flex flex-col"> <div className="flex flex-col">
{chain.map((item, idx) => ( {chain.map((item, idx) => (
<button <button
key={`item_${idx}`} key={`item_${idx}`}
className="value-content p-1 cursor-text text-xs border-b border-dashed border-gray-200 last:border-b-0 text-left w-full rounded transition-colors" className="value-content p-1 cursor-text text-xs border-b border-dashed border-gray-200 last:border-b-0 text-left w-full rounded transition-colors"
onClick={(e) => { onClick={(e) => {
e.stopPropagation();
if (item.data.page) { if (item.data.page) {
// console.log('currentitem-------', reviewPoint); // console.log('currentitem-------', reviewPoint);
// 假设onReviewPointSelect在作用域内可用 // 假设onReviewPointSelect在作用域内可用
const reviewPointId = reviewPoint.id as string; const reviewPointId = reviewPoint.id as string;
if (reviewPointId && typeof onReviewPointSelect === 'function') { if (reviewPointId && typeof onReviewPointSelect === 'function') {
e.stopPropagation();
onReviewPointSelect(reviewPointId, Number(item.data.page)); onReviewPointSelect(reviewPointId, Number(item.data.page));
} }
}else{ }else{
@@ -1162,13 +1172,6 @@ export function ReviewPointsList({
aria-label={`查看${item.field}内容详情`} aria-label={`查看${item.field}内容详情`}
> >
<div className="flex justify-between w-full"> <div className="flex justify-between w-full">
{/* <span className="font-medium">{item.field}:</span> */}
{/* <span className="w-full overflow-hidden line-clamp-2 hover:line-clamp-none
hover: z-10 hover:overflow-auto rounded max-h-96">{item.data.value?.toString() || ''}
{!item.data.page && !item.data.value && (
<i className="ri-information-line text-red-500 text-xs"></i>
)}
</span> */}
<ReactTableTooltip content={item.data.value?.toString() || ''} /> <ReactTableTooltip content={item.data.value?.toString() || ''} />
{!item.data.page && !item.data.value && ( {!item.data.page && !item.data.value && (
<i className="ri-information-line text-red-500 text-xs" title="没有找到对应的文书内容"></i> <i className="ri-information-line text-red-500 text-xs" title="没有找到对应的文书内容"></i>
@@ -1235,10 +1238,10 @@ export function ReviewPointsList({
flex-1 p-2 border-r-2 ${res ? 'border-green-200' : 'border-yellow-200'} text-left flex-1 p-2 border-r-2 ${res ? 'border-green-200' : 'border-yellow-200'} text-left
${res ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'} transition-colors flex flex-col`} ${res ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'} transition-colors flex flex-col`}
onClick={(e) => { onClick={(e) => {
e.stopPropagation();
if (chain[0].data.page) { if (chain[0].data.page) {
const reviewPointId = reviewPoint.id as string; const reviewPointId = reviewPoint.id as string;
if (reviewPointId && typeof onReviewPointSelect === 'function') { if (reviewPointId && typeof onReviewPointSelect === 'function') {
e.stopPropagation();
onReviewPointSelect(reviewPointId, chain[0].data.page); onReviewPointSelect(reviewPointId, chain[0].data.page);
} }
}else{ }else{
@@ -1257,10 +1260,10 @@ export function ReviewPointsList({
<button <button
className={`value-box flex flex-col flex-1 p-2 text-left ${res ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'} transition-colors hover:shadow-[0_0_10px_rgba(0,0,0,0.1)]`} className={`value-box flex flex-col flex-1 p-2 text-left ${res ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'} transition-colors hover:shadow-[0_0_10px_rgba(0,0,0,0.1)]`}
onClick={(e) => { onClick={(e) => {
e.stopPropagation();
if (chain[1].data.page) { if (chain[1].data.page) {
const reviewPointId = reviewPoint.id as string; const reviewPointId = reviewPoint.id as string;
if (reviewPointId && typeof onReviewPointSelect === 'function') { if (reviewPointId && typeof onReviewPointSelect === 'function') {
e.stopPropagation();
onReviewPointSelect(reviewPointId, chain[1].data.page); onReviewPointSelect(reviewPointId, chain[1].data.page);
} }
}else{ }else{
@@ -1394,8 +1397,8 @@ export function ReviewPointsList({
className={`border border-gray rounded-md overflow-hidden mb-2 ${overallResult ? 'bg-[rgba(246,255,237,1)]' : 'bg-[rgba(255,251,230,1)]'} flex w-full text-left className={`border border-gray rounded-md overflow-hidden mb-2 ${overallResult ? 'bg-[rgba(246,255,237,1)]' : 'bg-[rgba(255,251,230,1)]'} flex w-full text-left
hover:shadow-[0_0_10px_rgba(0,0,0,0.1)] ${overallResult ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'}`} hover:shadow-[0_0_10px_rgba(0,0,0,0.1)] ${overallResult ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'}`}
onClick={(e) => { onClick={(e) => {
e.stopPropagation();
if (mainTypeValue.page && typeof onReviewPointSelect === 'function') { if (mainTypeValue.page && typeof onReviewPointSelect === 'function') {
e.stopPropagation();
onReviewPointSelect(reviewPoint.id, Number(mainTypeValue.page)); onReviewPointSelect(reviewPoint.id, Number(mainTypeValue.page));
}else{ }else{
toastService.error(`没有找到${fieldKey}对应的索引内容`); toastService.error(`没有找到${fieldKey}对应的索引内容`);
@@ -1466,6 +1469,7 @@ export function ReviewPointsList({
* @returns React组件,用于显示AI模型评估结果 * @returns React组件,用于显示AI模型评估结果
*/ */
const renderModelRule = (aiRule: Record<string, unknown>, reviewPoint: ReviewPoint) => { const renderModelRule = (aiRule: Record<string, unknown>, reviewPoint: ReviewPoint) => {
// 从aiRule中提取配置信息 // 从aiRule中提取配置信息
const config = aiRule.config as { const config = aiRule.config as {
model?: string; model?: string;
@@ -1476,7 +1480,12 @@ export function ReviewPointsList({
message?: string; message?: string;
res?: boolean; res?: boolean;
} | undefined; } | undefined;
// 如果评查点评查结果和规则的结果不一致,则不渲染,跳过
if(config?.res !== reviewPoint.result){
return null;
}
// 如果配置不存在,不渲染任何内容 // 如果配置不存在,不渲染任何内容
if (!config) return null; if (!config) return null;
@@ -1494,8 +1503,8 @@ export function ReviewPointsList({
rounded-md overflow-hidden mb-2 ${res ? 'bg-[rgba(246,255,237,1)]' : 'bg-[rgba(255,251,230,1)]'} flex rounded-md overflow-hidden mb-2 ${res ? 'bg-[rgba(246,255,237,1)]' : 'bg-[rgba(255,251,230,1)]'} flex
hover:shadow-[0_0_10px_rgba(0,0,0,0.1)] ${res ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'}`} hover:shadow-[0_0_10px_rgba(0,0,0,0.1)] ${res ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'}`}
onClick={(e) => { onClick={(e) => {
e.stopPropagation();
if (value.page && typeof onReviewPointSelect === 'function') { if (value.page && typeof onReviewPointSelect === 'function') {
e.stopPropagation();
onReviewPointSelect(reviewPoint.id, Number(value.page)); onReviewPointSelect(reviewPoint.id, Number(value.page));
}else{ }else{
toastService.error(`没有找到${key}对应的索引内容`); toastService.error(`没有找到${key}对应的索引内容`);
@@ -1506,7 +1515,6 @@ export function ReviewPointsList({
if (e.key === 'Enter' || e.key === ' ') { if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault(); e.preventDefault();
if (value.page && typeof onReviewPointSelect === 'function') { if (value.page && typeof onReviewPointSelect === 'function') {
e.preventDefault();
onReviewPointSelect(reviewPoint.id, Number(value.page)); onReviewPointSelect(reviewPoint.id, Number(value.page));
}else{ }else{
toastService.error(`没有找到${key}对应的索引内容`); toastService.error(`没有找到${key}对应的索引内容`);
@@ -1629,6 +1637,10 @@ export function ReviewPointsList({
}> = []; }> = [];
for (const rule of reviewPoint.evaluatedPointResultsLog?.rules || []) { for (const rule of reviewPoint.evaluatedPointResultsLog?.rules || []) {
// 如果评查点评查结果和规则的结果不一致,则不渲染,跳过
if(rule.config.res !== reviewPoint.result){
continue;
}
// 处理"有无判断"类型的规则 // 处理"有无判断"类型的规则
if (rule.type === 'exists') { if (rule.type === 'exists') {
// 使用类型断言获取config对象的具体结构 // 使用类型断言获取config对象的具体结构
@@ -1713,6 +1725,7 @@ export function ReviewPointsList({
// 使用类型断言获取config对象的具体结构 // 使用类型断言获取config对象的具体结构
const config = rule.config as { const config = rule.config as {
logic: string; logic: string;
res: boolean;
conditions: Array<{ conditions: Array<{
field: Record<string, { page: number | string; value: string }>; field: Record<string, { page: number | string; value: string }>;
value: string; value: string;
+49 -48
View File
@@ -1559,7 +1559,7 @@ export default function FilesUpload() {
{/* 自定义标题栏 */} {/* 自定义标题栏 */}
<div className="w-full flex justify-between items-center mb-4"> <div className="w-full flex justify-between items-center mb-4">
<h3 className="text-lg font-medium"></h3> <h3 className="text-lg font-medium"></h3>
{isContractType && uploadStage === "idle" && ( {/* {isContractType && uploadStage === "idle" && (
<Button <Button
type="primary" type="primary"
icon="ri-upload-cloud-line" icon="ri-upload-cloud-line"
@@ -1567,14 +1567,15 @@ export default function FilesUpload() {
> >
开始上传 开始上传
</Button> </Button>
)} )} */}
</div> </div>
{/* 初始上传区域 */} {/* 初始上传区域 */}
{uploadStage === "idle" && ( {uploadStage === "idle" && (
<> <>
{!isContractType ? ( {/* {!isContractType ? ( */}
// 标准上传区域 - 非合同类型 {/* {true ? ( */}
{/* // 标准上传区域 - 非合同类型 */}
<UploadArea <UploadArea
ref={uploadAreaRef} ref={uploadAreaRef}
onFilesSelected={handleFilesSelected} onFilesSelected={handleFilesSelected}
@@ -1583,53 +1584,53 @@ export default function FilesUpload() {
tipText="支持单个或多个pdf文件上传,文件格式:PDF" tipText="支持单个或多个pdf文件上传,文件格式:PDF"
shouldPreventFileSelect={!fileType} shouldPreventFileSelect={!fileType}
/> />
) : ( {/* ) : ( */}
// 合同文件上传区域 - 双区域并排 {/* 合同文件上传区域 - 双区域并排 */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> {/* <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div> <div>
<h4 className="font-medium mb-2">合同主文件</h4> <h4 className="font-medium mb-2">合同主文件</h4>
<UploadArea <UploadArea
onFilesSelected={handleContractMainFilesSelected} // onFilesSelected={handleContractMainFilesSelected}
ref={contractMainFileRef} // ref={contractMainFileRef}
multiple={false} // multiple={false}
accept=".pdf" // accept=".pdf"
tipText="请上传合同主文件,格式:PDF" // tipText="请上传合同主文件,格式:PDF"
mainText="上传合同主文件" // mainText="上传合同主文件"
buttonText="选择主文件" // buttonText="选择主文件"
icon="ri-file-text-line" // icon="ri-file-text-line"
shouldPreventFileSelect={!fileType} // shouldPreventFileSelect={!fileType}
/> // />
{contractMainFiles.length > 0 && ( // {contractMainFiles.length > 0 && (
<div className="mt-2 text-sm text-green-600"> // <div className="mt-2 text-sm text-green-600">
<i className="ri-checkbox-circle-line"></i> // <i className="ri-checkbox-circle-line"></i>
: <span className="font-medium">{contractMainFiles[0].name}</span> // 已选择主文件: <span className="font-medium">{contractMainFiles[0].name}</span>
</div> // </div>
)} // )}
</div> // </div>
<div> // <div>
<h4 className="font-medium mb-2"></h4> // <h4 className="font-medium mb-2">合同附件</h4>
<UploadArea // <UploadArea
onFilesSelected={handleContractAttachmentFilesSelected} // onFilesSelected={handleContractAttachmentFilesSelected}
ref={contractAttachmentFileRef} // ref={contractAttachmentFileRef}
multiple={false} // multiple={false}
accept=".pdf" // accept=".pdf"
tipText="请上传合同附件,格式:PDF" // tipText="请上传合同附件,格式:PDF"
mainText="上传合同附件" // mainText="上传合同附件"
buttonText="选择附件" // buttonText="选择附件"
icon="ri-file-copy-line" // icon="ri-file-copy-line"
shouldPreventFileSelect={!fileType} // shouldPreventFileSelect={!fileType}
/> // />
{contractAttachmentFiles.length > 0 && ( // {contractAttachmentFiles.length > 0 && (
<div className="mt-2 text-sm text-green-600"> // <div className="mt-2 text-sm text-green-600">
<i className="ri-checkbox-circle-line"></i> // <i className="ri-checkbox-circle-line"></i>
: {contractAttachmentFiles.map((file, index) => ( // 已选择附件: {contractAttachmentFiles.map((file, index) => (
<span key={index} className="font-medium">{file.name}</span> // <span key={index} className="font-medium">{file.name}</span>
))} // ))}
</div> // </div>
)} // )}
</div> // </div>
</div> // </div>
)} // )}
{/* 测试文档标记 */} {/* 测试文档标记 */}
<div className="switch-container mb-4"> <div className="switch-container mb-4">