Files
leaudit-platform-frontend/app/api/contracts/draft-service.server.ts
T
2025-12-05 00:09:32 +08:00

214 lines
5.8 KiB
TypeScript

/**
* 合同起草服务
* 处理草稿创建、更新等业务逻辑
* 包含文件复制功能(预留 MinIO 实现)
*/
import { postgrestGet, postgrestPost, postgrestPut, postgrestDelete } from '~/api/postgrest-client';
import type { DraftedContract, CreateDraftRequest } from '~/types/contract-draft';
/**
* 生成草稿文件路径
* @param templateFilePath 模板文件路径
* @param userId 用户ID
* @param templateId 模板ID
* @returns 草稿文件路径
*/
export function generateDraftFilePath(
templateFilePath: string,
userId: number,
templateId: number
): string {
const timestamp = Date.now();
const fileExtension = templateFilePath.split('.').pop() || 'docx';
const newFileName = `contract_${templateId}_${userId}_${timestamp}.${fileExtension}`;
return `drafts/${newFileName}`;
}
/**
* 复制 MinIO 文件(预留实现)
* @param sourceFilePath 源文件路径
* @param targetFilePath 目标文件路径
* @param bucket Bucket 名称
* @returns 是否成功
*
* TODO: 实现 MinIO 文件复制逻辑
* 1. 安装 minio SDK: npm install minio
* 2. 创建 MinIO 客户端实例
* 3. 调用 copyObject 方法复制文件
*
* 参考实现:
* ```typescript
* import { Client } from 'minio';
*
* const minioClient = new Client({
* endPoint: process.env.MINIO_ENDPOINT || 'localhost',
* port: parseInt(process.env.MINIO_PORT || '9000'),
* useSSL: false,
* accessKey: process.env.MINIO_ACCESS_KEY || '',
* secretKey: process.env.MINIO_SECRET_KEY || ''
* });
*
* await minioClient.copyObject(
* bucket,
* targetFilePath,
* `/${bucket}/${sourceFilePath}`,
* null
* );
* ```
*/
export async function copyMinioFile(
sourceFilePath: string,
targetFilePath: string,
bucket: string = 'docauditai'
): Promise<boolean> {
try {
console.log('[Draft Service] 复制文件(预留实现):', {
sourceFilePath,
targetFilePath,
bucket
});
// TODO: 实现 MinIO 文件复制
// 当前为临时实现,直接返回成功
console.warn('[Draft Service] ⚠️ 文件复制功能尚未实现,请实施 MinIO 集成');
return true;
} catch (error) {
console.error('[Draft Service] 文件复制失败:', error);
return false;
}
}
/**
* 创建起草合同记录
* @param request 创建请求
* @param userId 用户ID
* @param draftFilePath 可选:草稿文件路径(如果不提供,使用模板路径)
* @returns 创建的记录
*
* 使用场景:
* 1. 不传 draftFilePath:直接使用模板文件路径,在原模板上编辑
* 2. 传 draftFilePath:使用复制后的文件路径(由文件复制接口提供)
*/
export async function createDraftContract(
request: CreateDraftRequest,
userId: number,
draftFilePath?: string,
jwt?: string
): Promise<DraftedContract> {
try {
// 1. 查询模板信息
const templateResponse = await postgrestGet('contract_templates', {
select: 'id,file_path',
filter: { id: `eq.${request.templateId}` },
token: jwt
});
if (!templateResponse.data || (Array.isArray(templateResponse.data) && templateResponse.data.length === 0)) {
throw new Error('模板不存在');
}
const template = Array.isArray(templateResponse.data) ? templateResponse.data[0] : templateResponse.data;
// 2. 确定使用的文件路径
// 如果没有提供草稿路径,直接使用模板路径(适合直接编辑模板的场景)
// 如果提供了草稿路径,使用复制后的文件路径
const finalFilePath = draftFilePath || template.file_path;
console.log('[Draft Service] 创建草稿:', {
templateId: request.templateId,
templatePath: template.file_path,
draftPath: draftFilePath,
finalPath: finalFilePath,
mode: draftFilePath ? '使用复制文件' : '直接使用模板文件'
});
// 3. 创建草稿记录
const insertResponse = await postgrestPost('drafted_contracts', {
body: {
template_id: request.templateId,
file_path: finalFilePath,
title: request.title,
placeholder_values: {},
status: 'draft',
created_by: userId
},
select: '*',
token: jwt
});
if (!insertResponse.data) {
throw new Error('创建草稿记录失败');
}
const draft = Array.isArray(insertResponse.data) ? insertResponse.data[0] : insertResponse.data;
return draft as DraftedContract;
} catch (error) {
console.error('[Draft Service] 创建草稿失败:', error);
throw error;
}
}
/**
* 删除草稿记录
* @param draftId 草稿ID
* @param userId 用户ID
* @param jwt JWT token
*/
export async function deleteDraft(
draftId: number,
userId: number,
jwt?: string
): Promise<void> {
try {
const response = await postgrestDelete('drafted_contracts', {
filter: {
id: `eq.${draftId}`,
created_by: `eq.${userId}` // 确保只能删除自己的草稿
},
token: jwt
});
console.log('[Draft Service] 草稿已删除:', draftId);
} catch (error) {
console.error('[Draft Service] 删除草稿失败:', error);
throw error;
}
}
/**
* 获取草稿详情
* @param draftId 草稿ID
* @param userId 用户ID
* @returns 草稿记录
*/
export async function getDraftById(
draftId: number,
userId: number,
jwt?: string
): Promise<DraftedContract | null> {
try {
const response = await postgrestGet('drafted_contracts', {
select: '*',
filter: {
id: `eq.${draftId}`,
created_by: `eq.${userId}`
},
token: jwt
});
if (!response.data || (Array.isArray(response.data) && response.data.length === 0)) {
return null;
}
const draft = Array.isArray(response.data) ? response.data[0] : response.data;
return draft as DraftedContract;
} catch (error) {
console.error('[Draft Service] 获取草稿失败:', error);
return null;
}
}