fix: 1.接入ai_suggestion.

2. 接入合同起草功能。
This commit is contained in:
2025-12-05 00:04:45 +08:00
parent eca98fc540
commit 33f10896a0
29 changed files with 3184 additions and 981 deletions
+111 -79
View File
@@ -1251,8 +1251,9 @@ export function ReviewPointsList({
${res ? 'hover:bg-[rgba(0,128,0,0.1)]' : 'hover:bg-[rgba(255,255,0,0.1)]'} transition-colors flex flex-col`}
onClick={(e) => {
e.stopPropagation();
console.log('点击了短链1左', chain[0].data.char_positions, chain[0].data)
if (chain[0].data.page) {
console.log('点击了短链1左', chain[0].data.char_positions, chain[0].data)
// console.log('点击了短链1左', chain[0].data.char_positions, chain[0].data)
const reviewPointId = reviewPoint.id as string;
if (reviewPointId && typeof onReviewPointSelect === 'function') {
onReviewPointSelect(reviewPointId, chain[0].data.page, chain[0].data.char_positions, chain[0].data.value);
@@ -1504,7 +1505,26 @@ export function ReviewPointsList({
value: string;
char_positions?: CharPosition[];
}>;
ai_suggestion?: Record<string,string>;
ai_suggestion?: {
summary?: string;
analysis?: {
failure_reason?: string;
solution_approach?: string;
rule_understanding?: string;
};
suggestions?: Record<string, {
reason: string;
source: {
page: number | null;
type: string;
field: string | null;
};
priority: string;
confidence: number;
suggested_value: string | null;
}>;
generated_at?: string;
};
message?: string;
res?: boolean;
} | undefined;
@@ -1536,8 +1556,6 @@ export function ReviewPointsList({
// 遍历fields,获取每个字段的值并生成对应的JSX元素
if (config.fields) {
Object.entries(config.fields).forEach(([key, value], index) => {
if (key == '合同正文-附件序号、标题') {value.value = '签订', value.page = 1}
if (key == '合同附件-序号、标题') {value.value = '电话', value.page = 1}
const res = value.value.trim() !== '';
fieldElements.push(
<button
@@ -1648,85 +1666,99 @@ export function ReviewPointsList({
);
}
config.ai_suggestion = {
'合同正文-附件序号、标题': '签订-一致啊一致',
'合同附件-序号、标题': '电话-明确啊明确'
}
// 渲染AI建议(ai_suggestion
if (config.ai_suggestion) {
// 遍历ai_suggestion对象
Object.entries(config.ai_suggestion).forEach(([key, value], index) => {
// 只渲染value不为空的项
if (value && value.trim() !== '') {
// 判断是否为PDF文档(禁用替换按钮)
fileFormat = fileFormat?.replace(/\./g,'')
const isPDF = fileFormat?.toUpperCase() === 'PDF';
if (config.ai_suggestion?.suggestions && Object.keys(config.ai_suggestion.suggestions).length > 0) {
// 判断是否为PDF文档(禁用替换按钮)
fileFormat = fileFormat?.replace(/\./g,'')
const isPDF = fileFormat?.toUpperCase() === 'PDF';
fieldElements.push(
<div key={`ai-suggestion-${index}`} className="mb-3">
{/* 字段名称标签 */}
<div className="text-xs text-gray-600 mb-2 font-medium">
<i className="ri-lightbulb-line text-yellow-500 mr-1"></i>
AI建议修改 - {key}
</div>
// 遍历suggestions对象的key-value对
Object.entries(config.ai_suggestion.suggestions).forEach(([key, suggestionValue], index) => {
// 检查建议值是否存在(null 或有值都要渲染)
const hasSuggestedValue = suggestionValue.suggested_value !== null && suggestionValue.suggested_value.trim() !== '';
const isReplaceDisabled = !hasSuggestedValue || isPDF;
{/* 建议内容和替换按钮 */}
<div className="flex gap-2 items-center">
{/* 禁用编辑的文本输入框 */}
<textarea
value={value}
readOnly
className="flex-1 p-2 border border-gray-200 rounded text-xs bg-gray-50 text-gray-700 resize-none cursor-not-allowed overflow-y-auto"
aria-label={`${key}的AI建议内容`}
/>
{/* 意见替换按钮 */}
{ !isPDF &&
<button
type="button"
onClick={() => {
if (!isPDF && onAiSuggestionReplace && config.fields) {
// 从 config.fields[key] 中获取对应的字段信息
const fieldData = config.fields[key];
if (fieldData) {
// 调用回调函数,传递搜索文本、替换文本和页码
onAiSuggestionReplace(
fieldData.value || '', // 搜索文本(原文)
value || '', // 替换文本(AI建议)
Number(fieldData.page) || 1 // 页码
);
// toastService.success(`已触发替换操作: ${key}`);
} else {
toastService.error(`未找到字段 ${key} 的原始数据`);
}
}
}}
disabled={isPDF}
className={`px-3 py-2 text-xs rounded whitespace-nowrap transition-colors
${isPDF
? 'bg-gray-200 text-gray-400 cursor-not-allowed'
: 'bg-primary text-white hover:bg-primary-hover active:bg-primary'
}`}
title={isPDF ? 'PDF文档不支持替换' : '点击执行一键替换'}
aria-label={`替换${key}的内容`}
>
<i className="ri-exchange-line mr-1"></i>
</button>
}
</div>
{/* PDF禁用提示 */}
{/* {isPDF && (
<div className="mt-1 text-xs text-gray-500 flex items-center">
<i className="ri-information-line mr-1"></i>
PDF文档不支持替换功能
</div>
)} */}
fieldElements.push(
<div key={`ai-suggestion-${index}`} className="mb-3">
{/* 字段名称标签 */}
<div className="text-xs text-gray-600 mb-2 font-medium">
<i className="ri-lightbulb-line text-yellow-500 mr-1"></i>
AI建议修改 - {key}
</div>
);
}
{/* 原因说明 */}
<div className="mb-2 p-2 bg-amber-50 rounded border border-amber-200 text-xs text-gray-700">
<div className="flex items-center">
<i className="ri-information-line text-amber-600 mr-1 mt-0.5"></i>
<div>
<span>{suggestionValue.reason}</span>
{suggestionValue.source.page !== null && (
<span className="ml-2 text-gray-500">
(: {suggestionValue.source.page})
</span>
)}
</div>
</div>
</div>
{/* 建议内容和替换按钮 */}
<div className="flex gap-2 items-center">
{/* 文本输入框 */}
<textarea
value={suggestionValue.suggested_value || ''}
readOnly
disabled={!hasSuggestedValue}
className={`flex-1 p-2 border rounded text-xs resize-none overflow-y-auto ${
hasSuggestedValue
? 'border-gray-200 bg-gray-50 text-gray-700 cursor-not-allowed'
: 'border-gray-200 bg-gray-100 text-gray-400 cursor-not-allowed'
}`}
aria-label={`${key}的AI建议内容`}
placeholder={!hasSuggestedValue ? '暂无建议值' : ''}
/>
{/* 意见替换按钮 */}
{ !isPDF &&
<button
type="button"
onClick={() => {
if (!isReplaceDisabled && onAiSuggestionReplace && config.fields) {
// 从 config.fields[key] 中获取对应的字段信息
const fieldData = config.fields[key];
if (fieldData) {
// 调用回调函数,传递搜索文本(原文)、替换文本(AI建议)和页码
onAiSuggestionReplace(
key, // 搜索文本(使用 suggestions 的 key
suggestionValue.suggested_value || '', // 替换文本(AI建议的 suggested_value
Number(fieldData.page) || 1 // 页码
);
} else {
toastService.error(`未找到字段 ${key} 的原始数据`);
}
}
}}
disabled={isReplaceDisabled}
className={`px-3 py-2 text-xs rounded whitespace-nowrap transition-colors
${isReplaceDisabled
? 'bg-gray-200 text-gray-400 cursor-not-allowed'
: 'bg-primary text-white hover:bg-primary-hover active:bg-primary'
}`}
title={
isPDF
? 'PDF文档不支持替换'
: !hasSuggestedValue
? '暂无建议值,无法替换'
: '点击执行一键替换'
}
aria-label={`替换${key}的内容`}
>
<i className="ri-exchange-line mr-1"></i>
</button>
}
</div>
</div>
);
});
}