修复起草合同的销毁保存下载和删除的逻辑
This commit is contained in:
@@ -55,6 +55,8 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
|
|||||||
const [showSearchReplacePanel, setShowSearchReplacePanel] = useState(false);
|
const [showSearchReplacePanel, setShowSearchReplacePanel] = useState(false);
|
||||||
// 标记是否应该自动执行搜索
|
// 标记是否应该自动执行搜索
|
||||||
const shouldAutoSearchRef = useRef(false);
|
const shouldAutoSearchRef = useRef(false);
|
||||||
|
// 标记是否应该自动执行替换(静默模式)
|
||||||
|
const shouldAutoReplaceRef = useRef(false);
|
||||||
|
|
||||||
// 高亮测试面板状态
|
// 高亮测试面板状态
|
||||||
const [highlightTextInput, setHighlightTextInput] = useState('');
|
const [highlightTextInput, setHighlightTextInput] = useState('');
|
||||||
@@ -131,7 +133,7 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
|
|||||||
// 3. UNO 命令封装
|
// 3. UNO 命令封装
|
||||||
const unoCommands = useCollaboraUnoCommands(iframeRef);
|
const unoCommands = useCollaboraUnoCommands(iframeRef);
|
||||||
|
|
||||||
// 4. 暴露接口给父组件(包括清除高亮方法)
|
// 4. 暴露接口给父组件(包括清除高亮方法和保存方法)
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
unoCommands,
|
unoCommands,
|
||||||
isReady: isDocumentLoaded,
|
isReady: isDocumentLoaded,
|
||||||
@@ -150,6 +152,35 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
|
|||||||
console.warn('[CollaboraViewer] ⚠️ 无法清除高亮:iframe window 不可用');
|
console.warn('[CollaboraViewer] ⚠️ 无法清除高亮:iframe window 不可用');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
saveDocument: async () => {
|
||||||
|
const savedWindow = iframeWindowRef.current || iframeRef.current?.contentWindow;
|
||||||
|
if (savedWindow) {
|
||||||
|
console.log('[CollaboraViewer] 💾 父组件调用保存文档');
|
||||||
|
try {
|
||||||
|
// 步骤1:发送保存命令
|
||||||
|
sendUnoCommand(savedWindow, '.uno:Save', {});
|
||||||
|
// console.log('[CollaboraViewer] ✓ 保存命令已发送');
|
||||||
|
|
||||||
|
// 步骤2:等待 WOPI PutFile 请求完成(增加到 2000ms)
|
||||||
|
// await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
|
|
||||||
|
// 步骤3:再次发送保存命令确保完全保存
|
||||||
|
sendUnoCommand(savedWindow, '.uno:Save', {});
|
||||||
|
// console.log('[CollaboraViewer] ✓ 二次保存命令已发送');
|
||||||
|
|
||||||
|
// 步骤4:再等待一段时间确保保存完成
|
||||||
|
// await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
|
||||||
|
// console.log('[CollaboraViewer] ✓ 文档保存完成(总等待 3000ms)');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[CollaboraViewer] ✗ 保存文档失败:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('[CollaboraViewer] ⚠️ 无法保存文档:iframe window 不可用');
|
||||||
|
throw new Error('iframe window 不可用');
|
||||||
|
}
|
||||||
|
},
|
||||||
}), [unoCommands, isDocumentLoaded, mode]);
|
}), [unoCommands, isDocumentLoaded, mode]);
|
||||||
|
|
||||||
// 5. 监听 targetPage 和 highlightText 变化,自动跳转并高亮
|
// 5. 监听 targetPage 和 highlightText 变化,自动跳转并高亮
|
||||||
@@ -182,7 +213,7 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
|
|||||||
textToHighlight,
|
textToHighlight,
|
||||||
{ page: targetPage }
|
{ page: targetPage }
|
||||||
);
|
);
|
||||||
console.log(`[CollaboraViewer] 已高亮文本: "${textToHighlight}"${targetPage ? ` (第${targetPage}页)` : ''}`);
|
// console.log(`[CollaboraViewer] 已高亮文本: "${textToHighlight}"${targetPage ? ` (第${targetPage}页)` : ''}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[CollaboraViewer] 高亮失败:', error);
|
console.error('[CollaboraViewer] 高亮失败:', error);
|
||||||
}
|
}
|
||||||
@@ -192,16 +223,30 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
|
|||||||
}
|
}
|
||||||
}, [targetPage, highlightText, isDocumentLoaded]);
|
}, [targetPage, highlightText, isDocumentLoaded]);
|
||||||
|
|
||||||
// 6. 组件销毁时清除所有高亮(使用保存的 window 引用)
|
// 6. 组件销毁时保存文档并清除所有高亮(使用保存的 window 引用)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 返回清理函数,在组件卸载时执行
|
// 返回清理函数,在组件卸载时执行
|
||||||
return () => {
|
return () => {
|
||||||
const savedWindow = iframeWindowRef.current;
|
const savedWindow = iframeWindowRef.current;
|
||||||
if (savedWindow) {
|
if (savedWindow) {
|
||||||
console.log('[CollaboraViewer] 🔥 组件即将销毁,立即清除所有高亮');
|
// console.log('[CollaboraViewer] 🔥 组件即将销毁,触发文档保存和清除高亮');
|
||||||
|
|
||||||
// 立即触发清除操作,不等待异步完成
|
// 步骤1:发送保存命令(如果是编辑模式)
|
||||||
// 使用 void 关键字表示我们不关心 Promise 的结果
|
if (mode === 'edit') {
|
||||||
|
try {
|
||||||
|
console.log('[CollaboraViewer] 💾 组件销毁时发送保存命令');
|
||||||
|
sendUnoCommand(savedWindow, '.uno:Save', {});
|
||||||
|
// 再次发送确保保存
|
||||||
|
setTimeout(() => {
|
||||||
|
sendUnoCommand(savedWindow, '.uno:Save', {});
|
||||||
|
console.log('[CollaboraViewer] ✓ 二次保存命令已发送');
|
||||||
|
}, 100);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[CollaboraViewer] ✗ 组件销毁时保存失败:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 步骤2:清除高亮
|
||||||
void clearHighlights(savedWindow, {
|
void clearHighlights(savedWindow, {
|
||||||
color: 16776960, // 黄色
|
color: 16776960, // 黄色
|
||||||
timeout: 3000,
|
timeout: 3000,
|
||||||
@@ -217,7 +262,7 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
|
|||||||
console.warn('[CollaboraViewer] ⚠️ 组件销毁时未找到保存的 window 引用');
|
console.warn('[CollaboraViewer] ⚠️ 组件销毁时未找到保存的 window 引用');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, []);
|
}, [mode]);
|
||||||
|
|
||||||
// 7. 监听 AI 建议替换参数变化,设置搜索参数
|
// 7. 监听 AI 建议替换参数变化,设置搜索参数
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -227,20 +272,32 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
|
|||||||
|
|
||||||
console.log('[CollaboraViewer] 收到 AI 建议替换参数:', aiSuggestionReplace);
|
console.log('[CollaboraViewer] 收到 AI 建议替换参数:', aiSuggestionReplace);
|
||||||
|
|
||||||
const { searchText: newSearchText, replaceText: newReplaceText, pageNumber } = aiSuggestionReplace;
|
const { searchText: newSearchText, replaceText: newReplaceText, pageNumber, silentReplace } = aiSuggestionReplace;
|
||||||
|
|
||||||
// 显示搜索替换面板
|
// 根据 silentReplace 标志决定是否显示面板
|
||||||
setShowSearchReplacePanel(true);
|
if (silentReplace) {
|
||||||
|
// 静默替换模式:不显示面板
|
||||||
|
console.log('[CollaboraViewer] 静默替换模式,不显示面板');
|
||||||
|
} else {
|
||||||
|
// 显示搜索替换面板
|
||||||
|
setShowSearchReplacePanel(true);
|
||||||
|
}
|
||||||
|
|
||||||
// 设置搜索、替换和页码输入框的值
|
// 设置搜索、替换和页码输入框的值
|
||||||
setSearchText(newSearchText);
|
setSearchText(newSearchText);
|
||||||
setReplaceText(newReplaceText);
|
setReplaceText(newReplaceText);
|
||||||
setSearchReplacePageNumber(String(pageNumber));
|
setSearchReplacePageNumber(String(pageNumber));
|
||||||
|
|
||||||
// 设置自动搜索标志
|
// 根据模式设置对应的自动执行标志
|
||||||
shouldAutoSearchRef.current = true;
|
if (silentReplace) {
|
||||||
|
// 静默替换:自动执行替换
|
||||||
console.log('[CollaboraViewer] 已设置搜索参数,等待状态更新后自动执行查找');
|
shouldAutoReplaceRef.current = true;
|
||||||
|
console.log('[CollaboraViewer] 已设置自动替换标志');
|
||||||
|
} else {
|
||||||
|
// 普通模式:仅自动执行查找
|
||||||
|
shouldAutoSearchRef.current = true;
|
||||||
|
console.log('[CollaboraViewer] 已设置搜索参数,等待状态更新后自动执行查找');
|
||||||
|
}
|
||||||
}, [aiSuggestionReplace, isDocumentLoaded]);
|
}, [aiSuggestionReplace, isDocumentLoaded]);
|
||||||
|
|
||||||
// 8. 当搜索参数更新完成后,自动执行查找
|
// 8. 当搜索参数更新完成后,自动执行查找
|
||||||
@@ -261,6 +318,55 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
|
|||||||
}
|
}
|
||||||
}, [searchText, searchReplacePageNumber, isDocumentLoaded]); // eslint-disable-line react-hooks/exhaustive-deps
|
}, [searchText, searchReplacePageNumber, isDocumentLoaded]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
|
// 9. 当搜索参数更新完成后,自动执行替换(静默模式)
|
||||||
|
useEffect(() => {
|
||||||
|
if (shouldAutoReplaceRef.current && searchText && replaceText && searchReplacePageNumber && isDocumentLoaded) {
|
||||||
|
console.log('[CollaboraViewer] 静默替换模式:自动执行替换:', { searchText, replaceText, searchReplacePageNumber });
|
||||||
|
|
||||||
|
// 重置标志
|
||||||
|
shouldAutoReplaceRef.current = false;
|
||||||
|
|
||||||
|
// 延迟执行,确保 DOM 更新完成
|
||||||
|
const timer = setTimeout(async () => {
|
||||||
|
if (!iframeRef.current?.contentWindow) {
|
||||||
|
console.error('[CollaboraViewer] iframe 未就绪,无法执行替换');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const pageNumber = parseInt(searchReplacePageNumber, 10);
|
||||||
|
|
||||||
|
// 步骤1:跳转到指定页
|
||||||
|
console.log(`[CollaboraViewer] 步骤1:跳转到第 ${pageNumber} 页`);
|
||||||
|
await customGotoPage(iframeRef.current.contentWindow, pageNumber);
|
||||||
|
|
||||||
|
// 等待页面渲染
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
|
|
||||||
|
// 步骤2:搜索文本(确保文本被选中)
|
||||||
|
console.log(`[CollaboraViewer] 步骤2:搜索文本 "${searchText}"`);
|
||||||
|
unoSearchNext(iframeRef.current.contentWindow, searchText);
|
||||||
|
|
||||||
|
// 等待搜索完成
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 300));
|
||||||
|
|
||||||
|
// 步骤3:执行替换
|
||||||
|
console.log(`[CollaboraViewer] 步骤3:替换为 "${replaceText}"`);
|
||||||
|
unoReplaceCurrent(iframeRef.current.contentWindow, searchText, replaceText);
|
||||||
|
|
||||||
|
console.log('[CollaboraViewer] ✓ 静默替换完成');
|
||||||
|
|
||||||
|
// 显示成功提示(可选)
|
||||||
|
// toastService.success(`已替换: "${searchText}" → "${replaceText}"`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[CollaboraViewer] 静默替换失败:', error);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}
|
||||||
|
}, [searchText, replaceText, searchReplacePageNumber, isDocumentLoaded]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
// 加载中状态
|
// 加载中状态
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -73,11 +73,11 @@ export async function highlightText(
|
|||||||
// const page = options?.page ?? 1; // 默认第1页
|
// const page = options?.page ?? 1; // 默认第1页
|
||||||
const page = options?.page ?? null; // 默认第1页
|
const page = options?.page ?? null; // 默认第1页
|
||||||
|
|
||||||
console.log('[HighlightSelectText] 调用 Python 脚本高亮文本:', {
|
// console.log('[HighlightSelectText] 调用 Python 脚本高亮文本:', {
|
||||||
text,
|
// text,
|
||||||
color,
|
// color,
|
||||||
page
|
// page
|
||||||
});
|
// });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 调用 Python 脚本: HighlightAndJumpToPage
|
// 调用 Python 脚本: HighlightAndJumpToPage
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export interface CollaboraViewerProps {
|
|||||||
searchText: string;
|
searchText: string;
|
||||||
replaceText: string;
|
replaceText: string;
|
||||||
pageNumber: number;
|
pageNumber: number;
|
||||||
|
silentReplace?: boolean; // 是否静默替换(不显示面板)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,4 +66,6 @@ export interface CollaboraViewerHandle {
|
|||||||
getIframeWindow: () => Window | null;
|
getIframeWindow: () => Window | null;
|
||||||
/** 清除所有高亮 */
|
/** 清除所有高亮 */
|
||||||
clearAllHighlights: () => Promise<void>;
|
clearAllHighlights: () => Promise<void>;
|
||||||
|
/** 保存文档 */
|
||||||
|
saveDocument: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ interface FilePreviewProps {
|
|||||||
searchText: string;
|
searchText: string;
|
||||||
replaceText: string;
|
replaceText: string;
|
||||||
pageNumber: number;
|
pageNumber: number;
|
||||||
|
silentReplace?: boolean; // 是否静默替换(不显示面板)
|
||||||
}; // AI建议替换参数
|
}; // AI建议替换参数
|
||||||
isTemplate?: boolean;
|
isTemplate?: boolean;
|
||||||
}
|
}
|
||||||
@@ -148,7 +149,7 @@ export const FilePreview = forwardRef<FilePreviewHandle, FilePreviewProps>(funct
|
|||||||
if (intervalCleared) return;
|
if (intervalCleared) return;
|
||||||
|
|
||||||
if (!collaboraViewerRef.current?.isReady) {
|
if (!collaboraViewerRef.current?.isReady) {
|
||||||
console.log('[FilePreview] 等待 Collabora 就绪...');
|
// console.log('[FilePreview] 等待 Collabora 就绪...');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -184,14 +184,17 @@ export default function ContractDraftPage() {
|
|||||||
searchText: string;
|
searchText: string;
|
||||||
replaceText: string;
|
replaceText: string;
|
||||||
pageNumber: number;
|
pageNumber: number;
|
||||||
|
silentReplace?: boolean;
|
||||||
} | undefined>(undefined);
|
} | undefined>(undefined);
|
||||||
|
const [showFilePreview, setShowFilePreview] = useState(true); // 控制 FilePreview 显示
|
||||||
|
const [isCompleting, setIsCompleting] = useState(false); // 标记是否正在执行完成流程
|
||||||
|
|
||||||
const filePreviewRef = useRef<FilePreviewHandle>(null);
|
const filePreviewRef = useRef<FilePreviewHandle>(null);
|
||||||
const hasDeletedNormally = useRef(false); // 标记是否已通过正常流程删除
|
const hasDeletedNormally = useRef(false); // 标记是否已通过正常流程删除
|
||||||
const currentPathRef = useRef(window.location.pathname); // 保存当前路由路径
|
const currentPathRef = useRef(window.location.pathname); // 保存当前路由路径
|
||||||
|
|
||||||
// 从 fetcher.state 判断是否正在操作
|
// 从 fetcher.state 判断是否正在操作
|
||||||
const isDeleting = fetcher.state !== 'idle';
|
const isDeleting = fetcher.state !== 'idle' || isCompleting;
|
||||||
|
|
||||||
// 处理 fetcher 响应(文件删除)
|
// 处理 fetcher 响应(文件删除)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -275,24 +278,25 @@ export default function ContractDraftPage() {
|
|||||||
const placeholder = `{{${key}}}`;
|
const placeholder = `{{${key}}}`;
|
||||||
console.log(`[Draft] 单个替换: ${placeholder} -> ${value}`);
|
console.log(`[Draft] 单个替换: ${placeholder} -> ${value}`);
|
||||||
|
|
||||||
// 设置 AI 建议替换参数,触发 FilePreview 中的替换
|
// 设置 AI 建议替换参数,触发 FilePreview 中的静默替换
|
||||||
setAiSuggestionReplace({
|
setAiSuggestionReplace({
|
||||||
searchText: placeholder,
|
searchText: placeholder,
|
||||||
replaceText: value,
|
replaceText: value,
|
||||||
pageNumber: 1 // 从第一页开始搜索
|
pageNumber: 1, // 从第一页开始搜索
|
||||||
|
silentReplace: true // 静默替换,不显示搜索替换面板
|
||||||
});
|
});
|
||||||
|
|
||||||
// 短暂延迟后清除参数,以便下次可以重新触发
|
// 短暂延迟后清除参数,以便下次可以重新触发
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setAiSuggestionReplace(undefined);
|
setAiSuggestionReplace(undefined);
|
||||||
// toastService.success(`已替换 ${key}`);
|
// toastService.success(`已替换 ${key}`);
|
||||||
}, 1000);
|
}, 2000);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 字段聚焦时高亮对应占位符
|
// 字段聚焦时高亮对应占位符
|
||||||
const handleFieldFocus = (key: string) => {
|
const handleFieldFocus = (key: string) => {
|
||||||
const placeholder = `{{${key}}}`;
|
const placeholder = `{{${key}}}`;
|
||||||
console.log(`[Draft] 高亮占位符: ${placeholder}`);
|
// console.log(`[Draft] 高亮占位符: ${placeholder}`);
|
||||||
|
|
||||||
// 设置高亮值,触发 FilePreview 中的高亮
|
// 设置高亮值,触发 FilePreview 中的高亮
|
||||||
setHighlightValue(placeholder);
|
setHighlightValue(placeholder);
|
||||||
@@ -303,7 +307,7 @@ export default function ContractDraftPage() {
|
|||||||
}, 100);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导出文档(下载当前编辑的文件)
|
// 导出文档(下载当前编辑的文件)- 不再需要手动保存
|
||||||
const handleExportDocument = async () => {
|
const handleExportDocument = async () => {
|
||||||
if (!draft.file_path) {
|
if (!draft.file_path) {
|
||||||
toastService.error('文件路径不存在,无法下载');
|
toastService.error('文件路径不存在,无法下载');
|
||||||
@@ -311,6 +315,9 @@ export default function ContractDraftPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const fileExtension = draft.file_path.split('.').pop()?.toLowerCase();
|
||||||
|
|
||||||
|
console.log('[Draft] 正在下载文件:', draft.file_path);
|
||||||
toastService.info('正在下载文件...');
|
toastService.info('正在下载文件...');
|
||||||
|
|
||||||
// 使用 axios-client 的 downloadFile 方法下载文件
|
// 使用 axios-client 的 downloadFile 方法下载文件
|
||||||
@@ -320,8 +327,7 @@ export default function ContractDraftPage() {
|
|||||||
const blobUrl = URL.createObjectURL(blob);
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
|
||||||
// 清理文件名
|
// 清理文件名
|
||||||
const fileExtension = draft.file_path.split('.').pop() || 'docx';
|
const fileName = `${draft.title}.${fileExtension || 'docx'}`;
|
||||||
const fileName = `${draft.title}.${fileExtension}`;
|
|
||||||
const cleanFileName = fileName.replace(/[<>:"/\\|?*]/g, '_');
|
const cleanFileName = fileName.replace(/[<>:"/\\|?*]/g, '_');
|
||||||
|
|
||||||
// 创建隐藏的a标签并点击下载
|
// 创建隐藏的a标签并点击下载
|
||||||
@@ -342,24 +348,41 @@ export default function ContractDraftPage() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Draft] 下载文件失败:', error);
|
console.error('[Draft] 下载文件失败:', error);
|
||||||
toastService.error(`下载文件失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
toastService.error(`下载文件失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||||
|
throw error; // 重新抛出错误,让 handleComplete 捕获
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 完成起草(下载文件 + 删除 MinIO 文件)
|
// 完成起草(触发保存 → 下载文件 → 删除 MinIO 文件)
|
||||||
const handleComplete = async () => {
|
const handleComplete = async () => {
|
||||||
try {
|
try {
|
||||||
// 1. 先下载文件
|
setIsCompleting(true);
|
||||||
|
|
||||||
|
// 步骤1:隐藏 FilePreview,触发 CollaboraViewer 组件销毁和保存
|
||||||
|
console.log('[Complete] 步骤1:隐藏 FilePreview,触发 Collabora 保存');
|
||||||
|
toastService.info('正在保存文档...');
|
||||||
|
setShowFilePreview(false);
|
||||||
|
|
||||||
|
// 步骤2:等待 Collabora 保存完成(给予充足时间让 WOPI PutFile 完成)
|
||||||
|
console.log('[Complete] 步骤2:等待 4 秒让 WOPI PutFile 完成');
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 4000));
|
||||||
|
|
||||||
|
// 步骤3:下载文件
|
||||||
|
console.log('[Complete] 步骤3:下载文件');
|
||||||
await handleExportDocument();
|
await handleExportDocument();
|
||||||
|
|
||||||
// 2. 删除 MinIO 文件
|
// 步骤4:删除 MinIO 文件
|
||||||
|
console.log('[Complete] 步骤4:删除 MinIO 文件');
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('_action', 'deleteFile');
|
formData.append('_action', 'deleteFile');
|
||||||
formData.append('filePath', draft.file_path);
|
formData.append('filePath', draft.file_path);
|
||||||
|
|
||||||
fetcher.submit(formData, { method: 'post' });
|
fetcher.submit(formData, { method: 'post' });
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Complete] 操作失败:', error);
|
console.error('[Complete] 操作失败:', error);
|
||||||
toastService.error('操作失败,请重试');
|
toastService.error('操作失败,请重试');
|
||||||
|
setIsCompleting(false);
|
||||||
|
setShowFilePreview(true); // 恢复显示
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -417,25 +440,35 @@ export default function ContractDraftPage() {
|
|||||||
<div className="flex-1 flex overflow-hidden gap-4 p-4">
|
<div className="flex-1 flex overflow-hidden gap-4 p-4">
|
||||||
{/* 左侧:文档预览(60%) */}
|
{/* 左侧:文档预览(60%) */}
|
||||||
<div className="w-[60%] bg-white h-full overflow-hidden rounded-xl shadow-lg border border-gray-200">
|
<div className="w-[60%] bg-white h-full overflow-hidden rounded-xl shadow-lg border border-gray-200">
|
||||||
<FilePreview
|
{showFilePreview ? (
|
||||||
ref={filePreviewRef}
|
<FilePreview
|
||||||
fileContent={{
|
ref={filePreviewRef}
|
||||||
path: draft.file_path,
|
fileContent={{
|
||||||
title: draft.title,
|
path: draft.file_path,
|
||||||
contractNumber: '',
|
title: draft.title,
|
||||||
parties: {
|
contractNumber: '',
|
||||||
partyA: { name: '', address: '', representative: '', phone: '' },
|
parties: {
|
||||||
partyB: { name: '', address: '', representative: '', phone: '' }
|
partyA: { name: '', address: '', representative: '', phone: '' },
|
||||||
},
|
partyB: { name: '', address: '', representative: '', phone: '' }
|
||||||
sections: []
|
},
|
||||||
}}
|
sections: []
|
||||||
activeReviewPointResultId={null}
|
}}
|
||||||
targetPage={undefined}
|
activeReviewPointResultId={null}
|
||||||
isStructuredView={false}
|
targetPage={undefined}
|
||||||
isTemplate={false} // 编辑模式
|
isStructuredView={false}
|
||||||
highlightValue={highlightValue}
|
isTemplate={false} // 编辑模式
|
||||||
aiSuggestionReplace={aiSuggestionReplace}
|
highlightValue={highlightValue}
|
||||||
/>
|
aiSuggestionReplace={aiSuggestionReplace}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center justify-center h-full">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="inline-block animate-spin rounded-full h-12 w-12 border-b-2 border-primary mb-4"></div>
|
||||||
|
<p className="text-gray-600 font-medium">正在保存文档...</p>
|
||||||
|
<p className="text-sm text-gray-500 mt-2">请稍候,即将完成</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 右侧:占位符表单(40%) */}
|
{/* 右侧:占位符表单(40%) */}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ export class WopiService {
|
|||||||
|
|
||||||
// 功能配置
|
// 功能配置
|
||||||
DisableInactiveMessages: true,
|
DisableInactiveMessages: true,
|
||||||
DisableAutoSave: true,
|
DisableAutoSave: false,
|
||||||
|
|
||||||
// 文件最后修改时间
|
// 文件最后修改时间
|
||||||
LastModifiedTime: lastModified || new Date().toISOString(),
|
LastModifiedTime: lastModified || new Date().toISOString(),
|
||||||
@@ -260,7 +260,7 @@ export class WopiService {
|
|||||||
throw new Error(`保存文件失败: ${sanitizedFileId}`);
|
throw new Error(`保存文件失败: ${sanitizedFileId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log(`PutFile 成功: ${sanitizedFileId}, Size: ${fileBuffer.byteLength} bytes`);
|
console.log(`PutFile 成功: ${sanitizedFileId}, Size: ${fileBuffer.byteLength} bytes`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('PutFile 失败:', error);
|
console.error('PutFile 失败:', error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
Reference in New Issue
Block a user