feat: AI写作模块4项优化(20260419_2226)
- 修复 diff 颜色残留: confirmAiInjection 使用 cleanHtml 而非 newHtml - 更新默认快捷指令: 4条外科专用 -> 2条通用短语 - 新增发送按钮: 输入框旁显式发送按钮 - 导出AI日志: 快捷指令区域新增调试日志导出(JSON)
This commit is contained in:
@@ -69,7 +69,7 @@ export default function ReportEditor() {
|
|||||||
const [aiUploadedImages, setAiUploadedImages] = useState<{id: number, dataUrl: string}[]>([]);
|
const [aiUploadedImages, setAiUploadedImages] = useState<{id: number, dataUrl: string}[]>([]);
|
||||||
const speechRecognitionRef = useRef<any>(null);
|
const speechRecognitionRef = useRef<any>(null);
|
||||||
const [quickPrompts, setQuickPrompts] = useState<string[]>([
|
const [quickPrompts, setQuickPrompts] = useState<string[]>([
|
||||||
'请详细描述手术步骤', '提取术中关键病灶信息', '生成简短的术后总结', '根据截图描述游离过程'
|
'请完善报告内容', '请对内容做如下修改:'
|
||||||
]);
|
]);
|
||||||
const [isEditingPrompts, setIsEditingPrompts] = useState(false);
|
const [isEditingPrompts, setIsEditingPrompts] = useState(false);
|
||||||
const [diffModal, setDiffModal] = useState<{isOpen: boolean, originalHtml: string, newHtml: string, targetId: string} | null>(null);
|
const [diffModal, setDiffModal] = useState<{isOpen: boolean, originalHtml: string, newHtml: string, targetId: string} | null>(null);
|
||||||
@@ -1016,7 +1016,7 @@ export default function ReportEditor() {
|
|||||||
range.selectNodeContents(targetContent);
|
range.selectNodeContents(targetContent);
|
||||||
sel?.removeAllRanges();
|
sel?.removeAllRanges();
|
||||||
sel?.addRange(range);
|
sel?.addRange(range);
|
||||||
document.execCommand('insertHTML', false, newHtml);
|
document.execCommand('insertHTML', false, cleanHtml);
|
||||||
targetContent.style.transition = 'background-color 0.3s ease';
|
targetContent.style.transition = 'background-color 0.3s ease';
|
||||||
targetContent.style.backgroundColor = '#bfdbfe';
|
targetContent.style.backgroundColor = '#bfdbfe';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -2381,6 +2381,31 @@ export default function ReportEditor() {
|
|||||||
{isEditingPrompts ? '+ 添加' : '⚙️'}
|
{isEditingPrompts ? '+ 添加' : '⚙️'}
|
||||||
</button>
|
</button>
|
||||||
{isEditingPrompts && <button onClick={() => setIsEditingPrompts(false)} className="px-2 py-1 bg-blue-100 text-blue-600 text-[11px] rounded-full">完成</button>}
|
{isEditingPrompts && <button onClick={() => setIsEditingPrompts(false)} className="px-2 py-1 bg-blue-100 text-blue-600 text-[11px] rounded-full">完成</button>}
|
||||||
|
<button onClick={() => {
|
||||||
|
const data = {
|
||||||
|
exportAt: new Date().toISOString(),
|
||||||
|
url: window.location.href,
|
||||||
|
messages: chatMessages,
|
||||||
|
metadata: {
|
||||||
|
user: currentUser?.username || 'anonymous',
|
||||||
|
activeProvider: (() => { const s = storage.get<SystemSettings>('systemSettings', {} as SystemSettings); return s.activeAiProvider || 'kimi'; })(),
|
||||||
|
targetRegion: aiTargetRegion,
|
||||||
|
modifyEnabled: aiModifyEnabled,
|
||||||
|
chatInput,
|
||||||
|
uploadedImagesCount: aiUploadedImages.length,
|
||||||
|
selectedFramesCount: aiSelectedFrames.length
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = `ai-logs-${Date.now()}.json`;
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}} className="px-2 py-1 bg-slate-100 text-slate-500 text-[11px] rounded-full hover:bg-slate-200 ml-auto" title="导出 AI 日志(调试用)">
|
||||||
|
导出 AI 日志
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 沉浸式输入框 */}
|
{/* 沉浸式输入框 */}
|
||||||
@@ -2420,6 +2445,9 @@ export default function ReportEditor() {
|
|||||||
<button onClick={toggleListening} className={`p-1.5 rounded-lg transition-colors ${isListening ? 'text-red-500 bg-red-50 animate-pulse' : 'text-slate-400 hover:text-blue-600 bg-slate-50 hover:bg-blue-50'}`}>
|
<button onClick={toggleListening} className={`p-1.5 rounded-lg transition-colors ${isListening ? 'text-red-500 bg-red-50 animate-pulse' : 'text-slate-400 hover:text-blue-600 bg-slate-50 hover:bg-blue-50'}`}>
|
||||||
{isListening ? <Mic size={16} /> : <MicOff size={16} />}
|
{isListening ? <Mic size={16} /> : <MicOff size={16} />}
|
||||||
</button>
|
</button>
|
||||||
|
<button onClick={() => { if (!isGenerating && chatInput.trim()) handleAIGenerate(chatInput); }} disabled={isGenerating || !chatInput.trim()} className="p-1.5 rounded-lg transition-colors text-slate-400 hover:text-blue-600 bg-slate-50 hover:bg-blue-50 disabled:opacity-40 disabled:cursor-not-allowed" title="发送">
|
||||||
|
<Send size={16} />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
19
工程分析/20260419_2226/功能变更执行文档.md
Normal file
19
工程分析/20260419_2226/功能变更执行文档.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# 功能变更执行文档(20260419_2226)
|
||||||
|
|
||||||
|
## 变更摘要
|
||||||
|
本次实施 4 项优化:
|
||||||
|
|
||||||
|
| # | 变更项 | 目标效果 |
|
||||||
|
|---|---|---|
|
||||||
|
| 1 | 修复 diff 颜色残留 | `confirmAiInjection` 使用 `cleanHtml` 而非 `newHtml` |
|
||||||
|
| 2 | 更新默认快捷指令 | 4 条外科专用短语 → 2 条通用短语 |
|
||||||
|
| 3 | 新增发送按钮 | 在麦克风按钮旁添加显式发送按钮 |
|
||||||
|
| 4 | 导出 AI 日志 | 快捷指令区域新增「导出 AI 日志」按钮,下载 JSON |
|
||||||
|
|
||||||
|
## 变更文件
|
||||||
|
- `src/pages/ReportEditor.tsx`
|
||||||
|
|
||||||
|
## 技术要点
|
||||||
|
1. **Diff 颜色残留根因**:`confirmAiInjection` 中 `document.execCommand('insertHTML')` 传入的是未清理的 `newHtml`,而 `cleanHtml`(已去除 diff span)未被使用。
|
||||||
|
2. **Send 按钮复用**:`lucide-react` 的 `Send` 图标已在导入列表中,无需新增依赖。
|
||||||
|
3. **导出 AI 日志**:点击后组装 `{ exportAt, url, messages, metadata }` 为 JSON Blob 并触发浏览器下载。
|
||||||
Reference in New Issue
Block a user