import type { ActionFunctionArgs } from '@remix-run/node';
import type { ConvertRequest, ConvertResponse, Template } from '@shared/types/mod.ts';
import { ERROR_CODES, EXCEL_TEMPLATE_TABLE } from '@shared/types/mod.ts';
import { excelParser } from '~/lib/ExcelParser.server.ts';
import { getApiClient } from '~/lib/ApiClient.server.ts';
/**
* 公开的Excel转JSON API接口
* POST /api/v1/convert
*
* 需要在请求头中提供有效的API密钥:
* - X-API-Key: 'YOUR_API_KEY'
*/
export const action = async ({ request }: ActionFunctionArgs) => {
console.log('[ExcelToJSON API] 收到转换请求');
// 只支持POST请求
if (request.method !== 'POST') {
console.log('[ExcelToJSON API] 错误: 不支持的请求方法', request.method);
return Response.json({
success: false,
code: ERROR_CODES.VALIDATION_ERROR,
message: '不支持的请求方法,仅支持POST'
}, { status: 405 });
}
// 验证API密钥
const apiKey = request.headers.get('X-API-Key');
if (!apiKey) {
console.log('[ExcelToJSON API] 错误: 缺少API密钥');
return Response.json({
success: false,
code: ERROR_CODES.AUTH_ERROR,
message: '缺少API密钥,请在请求头中提供X-API-Key'
}, { status: 401 });
}
// TODO: 在实际生产环境中,应该从数据库或环境变量中获取并验证API密钥
const validApiKey = process.env.API_KEY || 'excel2json-api-key';
if (apiKey !== validApiKey) {
console.log('[ExcelToJSON API] 错误: API密钥无效', apiKey);
return Response.json({
success: false,
code: ERROR_CODES.AUTH_ERROR,
message: 'API密钥无效'
}, { status: 401 });
}
try {
// 解析请求数据
const requestData = await request.json() as ConvertRequest;
console.log('[ExcelToJSON API] 请求数据:', {
templateId: requestData.templateId,
hasConfig: !!requestData.config,
inputType: requestData.input?.substring(0, 20) + '...' // 只记录输入类型的前20个字符
});
// 验证输入参数
if (!requestData.input) {
console.log('[ExcelToJSON API] 错误: 缺少input参数');
return Response.json({
success: false,
code: ERROR_CODES.VALIDATION_ERROR,
message: '请提供input参数'
}, { status: 400 });
}
// 获取API客户端
console.log('[ExcelToJSON API] 获取API客户端');
const apiClient = await getApiClient();
// 解析配置
let templateConfig;
// 如果提供了templateId,从数据库获取模板配置
if (requestData.templateId) {
console.log('[ExcelToJSON API] 正在获取模板,ID:', requestData.templateId);
try {
const template = await apiClient.database.table(EXCEL_TEMPLATE_TABLE)
.where('id', requestData.templateId)
.where('is_deleted', 0)
.first() as Template;
if (!template) {
console.log('[ExcelToJSON API] 错误: 模板不存在', requestData.templateId);
return Response.json({
success: false,
code: ERROR_CODES.NOT_FOUND,
message: '模板不存在'
}, { status: 404 });
}
templateConfig = template.template_config;
console.log('[ExcelToJSON API] 成功获取模板配置,工作表数:', templateConfig.sheets?.length);
} catch (error) {
console.error('[ExcelToJSON API] 获取模板失败:', error);
return Response.json({
success: false,
code: ERROR_CODES.SERVER_ERROR,
message: '获取模板失败'
}, { status: 500 });
}
}
// 如果提供了自定义配置,使用自定义配置
else if (requestData.config) {
templateConfig = requestData.config;
console.log('[ExcelToJSON API] 使用自定义配置,工作表数:', templateConfig.sheets?.length);
}
// 如果没有提供模板ID或自定义配置,返回错误
else {
console.log('[ExcelToJSON API] 错误: 缺少templateId或config参数');
return Response.json({
success: false,
code: ERROR_CODES.VALIDATION_ERROR,
message: '请提供templateId或config参数'
}, { status: 400 });
}
// 将输入转换为ArrayBuffer
let buffer: ArrayBuffer;
try {
console.log('[ExcelToJSON API] 正在获取文件数据');
buffer = await excelParser.getBufferFromUrlOrBase64(requestData.input);
console.log('[ExcelToJSON API] 成功获取文件数据,大小:', buffer.byteLength, '字节');
} catch (error) {
console.error('[ExcelToJSON API] 获取文件数据失败:', error);
return Response.json({
success: false,
code: ERROR_CODES.VALIDATION_ERROR,
message: '获取文件数据失败,请确保提供了有效的URL或Base64编码'
}, { status: 400 });
}
// 处理Excel文件
console.log('[ExcelToJSON API] 开始解析Excel文件');
const result = await excelParser.parseExcelBuffer(buffer, templateConfig.sheets);
console.log('[ExcelToJSON API] Excel解析完成,总表格数:', result.totalTables, '警告数:', result.warnings.length);
// 构造响应
const response: ConvertResponse = {
success: true,
data: result.exportData,
warnings: result.warnings,
availableFields: result.availableFieldsBySheet,
totalTables: result.totalTables
};
// 记录API调用日志(可选)
// await apiClient.database.table('api_logs').insert({
// api_key: apiKey,
// endpoint: '/api/v1/convert',
// created_at: new Date()
// });
console.log('[ExcelToJSON API] 转换成功,响应数据大小:',
JSON.stringify(response).length, '字节');
return Response.json(response);
} catch (error) {
console.error('[ExcelToJSON API] 转换失败:', error);
return Response.json({
success: false,
code: ERROR_CODES.SERVER_ERROR,
message: `转换失败: ${error instanceof Error ? error.message : '未知错误'}`
}, { status: 500 });
}
};