feat: 1. 完善起草合同页面的逻辑交互,对接minio的接口操作
This commit is contained in:
@@ -1,18 +1,17 @@
|
||||
import type { MetaFunction, LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node';
|
||||
import { redirect } from '@remix-run/node';
|
||||
import { useLoaderData, useNavigate, useSubmit } from '@remix-run/react';
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { getContractTemplate } from '~/api/contract-template/templates';
|
||||
import type { ContractTemplate } from '~/api/contract-template/templates';
|
||||
import styles from '~/styles/pages/contract-template.css?url';
|
||||
import filePreviewStyles from '~/styles/components/file-preview-isolation.css?url';
|
||||
import { getUserSession } from '~/api/login/auth.server';
|
||||
import { createDraftContract } from '~/api/contracts/draft-service.server';
|
||||
import { apiRequest, downloadFile } from '~/api/axios-client';
|
||||
|
||||
// 导入FilePreview组件
|
||||
import { FilePreview } from '~/components/reviews';
|
||||
// 导入统一的下载方法和提示服务
|
||||
import { downloadFile } from '~/api/axios-client';
|
||||
import { toastService } from '~/components/ui/Toast';
|
||||
|
||||
export const links = () => [
|
||||
@@ -70,7 +69,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
|
||||
* Action 函数:处理起草合同请求
|
||||
*/
|
||||
export async function action({ request, params }: ActionFunctionArgs) {
|
||||
const templateId = parseInt(params.id || '0');
|
||||
const templateId = params.id!;
|
||||
|
||||
if (!templateId) {
|
||||
return Response.json({ error: '模板ID无效' }, { status: 400 });
|
||||
@@ -86,27 +85,60 @@ export async function action({ request, params }: ActionFunctionArgs) {
|
||||
// 解析表单数据
|
||||
const formData = await request.formData();
|
||||
const title = formData.get('title') as string;
|
||||
const draftFilePath = formData.get('draftFilePath') as string | null;
|
||||
const originalFilePath = formData.get('originalFilePath') as string;
|
||||
|
||||
if (!title) {
|
||||
return Response.json({ error: '标题不能为空' }, { status: 400 });
|
||||
}
|
||||
|
||||
// 创建草稿记录(到时候可以换成接口,使用接口来在minio中生成备份文件:备份文件可以用时间戳+uuid来保证唯一性。)
|
||||
// const draft = await createDraftContract(
|
||||
// {
|
||||
// templateId,
|
||||
// title,
|
||||
// draftFilePath: draftFilePath || undefined
|
||||
// },
|
||||
// parseInt(userInfo.sub),
|
||||
// draftFilePath || undefined,
|
||||
// frontendJWT || undefined
|
||||
// );
|
||||
if (!originalFilePath) {
|
||||
return Response.json({ error: '文件路径不存在' }, { status: 400 });
|
||||
}
|
||||
|
||||
// 重定向到草稿编辑页面
|
||||
// return redirect(`/contract-draft/${draft.id}`);
|
||||
return redirect(`/contract-draft/1`);
|
||||
// 生成新文件路径
|
||||
const area = userInfo.area || 'unknown';
|
||||
const timestamp = Date.now();
|
||||
const uuid = crypto.randomUUID();
|
||||
|
||||
// 提取文件目录和文件名
|
||||
const lastSlashIndex = originalFilePath.lastIndexOf('/');
|
||||
const directory = lastSlashIndex >= 0 ? originalFilePath.substring(0, lastSlashIndex) : '';
|
||||
const fileName = lastSlashIndex >= 0 ? originalFilePath.substring(lastSlashIndex + 1) : originalFilePath;
|
||||
|
||||
// 提取文件扩展名
|
||||
const lastDotIndex = fileName.lastIndexOf('.');
|
||||
const baseName = lastDotIndex >= 0 ? fileName.substring(0, lastDotIndex) : fileName;
|
||||
const extension = lastDotIndex >= 0 ? fileName.substring(lastDotIndex) : '';
|
||||
|
||||
// 构建新文件名
|
||||
const newFileName = `${baseName}_${area}_${timestamp}_${uuid}${extension}`;
|
||||
const newFilePath = directory ? `${directory}/${newFileName}` : newFileName;
|
||||
|
||||
console.log('[Draft] 复制文件:', { originalFilePath, newFilePath });
|
||||
|
||||
// 调用 MinIO 复制文件 API(需要传递 JWT)
|
||||
const jwt = frontendJWT || undefined;
|
||||
const copyResponse = await apiRequest('/api/v2/storage/files/copy', {
|
||||
method: 'POST',
|
||||
data: {
|
||||
source_path: originalFilePath,
|
||||
destination_path: newFilePath
|
||||
},
|
||||
headers: {
|
||||
'Authorization': jwt ? `Bearer ${jwt}` : ''
|
||||
}
|
||||
});
|
||||
|
||||
if (copyResponse.error) {
|
||||
console.error('[Draft] 文件复制失败:', copyResponse.error);
|
||||
return Response.json({ error: `文件复制失败: ${copyResponse.error}` }, { status: 500 });
|
||||
}
|
||||
|
||||
console.log('[Draft] 文件复制成功:', copyResponse.data);
|
||||
|
||||
// 重定向到草稿编辑页面,通过 URL 参数传递文件路径和模板 ID
|
||||
const draftUrl = `/contract-draft/1?filePath=${encodeURIComponent(newFilePath)}&templateId=${templateId}&title=${encodeURIComponent(title)}`;
|
||||
return redirect(draftUrl);
|
||||
} catch (error) {
|
||||
console.error('[Template Detail] 创建草稿失败:', error);
|
||||
return Response.json(
|
||||
@@ -124,6 +156,12 @@ export default function ContractTemplateDetail() {
|
||||
// 注释掉收藏功能
|
||||
// const [isFavorited, setIsFavorited] = useState(false);
|
||||
|
||||
// 防止页面加载时自动滚动到预览区域(由 Collabora iframe 的 tabIndex 导致)
|
||||
useEffect(() => {
|
||||
// 页面加载后立即滚动回顶部
|
||||
window.scrollTo({ top: 0, behavior: 'instant' });
|
||||
}, []);
|
||||
|
||||
const handleBack = () => {
|
||||
navigate(-1);
|
||||
};
|
||||
@@ -181,21 +219,20 @@ export default function ContractTemplateDetail() {
|
||||
const handleStartDraft = () => {
|
||||
if (isCreatingDraft) return;
|
||||
|
||||
// 生成默认标题
|
||||
// const defaultTitle = `${template.title}-${new Date().toLocaleDateString('zh-CN').replace(/\//g, '')}`;
|
||||
if (!template.file_path) {
|
||||
toastService.error('模板文件路径不存在,无法起草');
|
||||
return;
|
||||
}
|
||||
|
||||
// // 提示用户输入标题
|
||||
// const title = prompt('请输入合同标题:', defaultTitle);
|
||||
// if (!title) return;
|
||||
// 生成默认标题
|
||||
const defaultTitle = `${template.title}-${new Date().toLocaleDateString('zh-CN').replace(/\//g, '')}`;
|
||||
|
||||
setIsCreatingDraft(true);
|
||||
|
||||
// 使用 Remix 的 submit 提交表单
|
||||
const formData = new FormData();
|
||||
// formData.append('title', title.trim());
|
||||
formData.append('title', '买卖合同-拟起草合同');
|
||||
// 可选:如果需要复制文件,可以先调用文件复制服务,然后传递 draftFilePath
|
||||
// formData.append('draftFilePath', draftFilePath);
|
||||
formData.append('title', defaultTitle);
|
||||
formData.append('originalFilePath', template.file_path);
|
||||
|
||||
submit(formData, { method: 'post' });
|
||||
};
|
||||
@@ -430,7 +467,7 @@ export default function ContractTemplateDetail() {
|
||||
|
||||
{/* 合同预览 - 只有当存在pdf_file_path时才显示 */}
|
||||
{fileContent && (
|
||||
<div className="content-section mb-8" id="template-preview">
|
||||
<div className="content-section mb-8">
|
||||
<h3 className="section-title text-xl font-semibold mb-4">合同预览</h3>
|
||||
<div className="border border-gray-200 rounded-lg overflow-hidden">
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user