fix: 统一日志格式并修复字体列表接口参数验证
refactor(字体服务): 重构日志格式添加上下文信息 fix(API-fonts/list): 添加分页参数验证和限制 style: 调整代码格式和注释
This commit is contained in:
parent
6eb838d9f0
commit
a6847e28de
13 changed files with 85 additions and 39 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -56,7 +56,7 @@ web_modules/
|
|||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
.vscode/settings.json
|
||||
.vscode/*
|
||||
# Optional prettier cache
|
||||
.prettiercache
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ const useFontList = (filters: {
|
|||
const res: ApiResponse = await requestPost('/api/fonts/list', {
|
||||
pageData: { page, size: PAGE_SIZE },
|
||||
tags: filters.tags || undefined,
|
||||
keywords: debouncedKeywords || undefined,
|
||||
keyword: debouncedKeywords || undefined,
|
||||
languages: filters.languages || undefined,
|
||||
category: filters.category || undefined,
|
||||
});
|
||||
|
|
|
@ -194,7 +194,7 @@ export async function GET(request: NextRequest): Promise<NextResponse> {
|
|||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('CSS生成页面 - CSS生成接口错误:', error);
|
||||
Logger.error('[API-css] CSS生成接口错误', error);
|
||||
return new NextResponse('/* 内部服务器错误 */', {
|
||||
status: 500,
|
||||
headers: {
|
||||
|
@ -296,8 +296,8 @@ async function generateCSSResponseOriginal(
|
|||
const staticBaseRaw = APP_CONFIG.fontStaticUrl;
|
||||
if (!staticBaseRaw) {
|
||||
Logger.error(
|
||||
'CSS生成页面 - 缺少字体静态资源基础 URL。请在环境变量中设置 NEXT_PUBLIC_FONT_STATIC_URL 或 OSS_ENDPOINT。'
|
||||
);
|
||||
'[API-css] 缺少字体静态资源基础 URL。请在环境变量中设置 NEXT_PUBLIC_FONT_STATIC_URL 或 OSS_ENDPOINT。'
|
||||
);
|
||||
throw new Error('缺少字体静态资源基础 URL');
|
||||
}
|
||||
const staticBase = staticBaseRaw.replace(/\/+$/g, '');
|
||||
|
@ -342,7 +342,7 @@ async function generateCSSResponseOriginal(
|
|||
|
||||
return cssContent;
|
||||
} catch (error: any) {
|
||||
Logger.error('CSS生成页面 - 生成CSS响应时出错:', error);
|
||||
Logger.error('[API-css] 生成CSS响应时出错', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ export async function GET(
|
|||
message: 'success',
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('字体管理页面 - 自动更新字体接口错误:', error);
|
||||
Logger.error('[API-fonts/auto_update] 自动更新字体接口错误', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
|
|
|
@ -61,7 +61,7 @@ export async function POST(
|
|||
message: 'success',
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('字体管理页面 - 创建字体接口错误:', error);
|
||||
Logger.error('[API-fonts/create] 创建字体接口错误', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
|
|
|
@ -32,7 +32,7 @@ export async function POST(
|
|||
message: 'success',
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('字体管理页面 - 删除字体接口错误:', error);
|
||||
Logger.error('[API-fonts/delete] 删除字体接口错误', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
|
|
|
@ -39,7 +39,7 @@ export async function GET(
|
|||
message: 'success',
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('字体详情页面 - 获取字体详情接口错误:', error);
|
||||
Logger.error('[API-fonts/detail] 获取字体详情接口错误', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
|
@ -94,7 +94,7 @@ export async function POST(
|
|||
message: 'success',
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('字体详情页面 - 根据名称获取字体详情接口错误:', error);
|
||||
Logger.error('[API-fonts/detail] 根据名称获取字体详情接口错误', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
|
|
|
@ -14,6 +14,43 @@ export async function POST(
|
|||
const typefaceService = new TypefaceService();
|
||||
|
||||
const body: ListTypefaceDto = await request.json();
|
||||
|
||||
// 验证必需的参数
|
||||
if (!body.pageData || typeof body.pageData !== 'object') {
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 400,
|
||||
message: 'pageData 参数是必需的',
|
||||
status: 'fail',
|
||||
},
|
||||
{ status: 200 }
|
||||
);
|
||||
}
|
||||
|
||||
const { page, size } = body.pageData;
|
||||
if (typeof page !== 'number' || typeof size !== 'number' || page < 1 || size < 1) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 400,
|
||||
message: 'pageData.page 和 pageData.size 必须是大于0的数字',
|
||||
status: 'fail',
|
||||
},
|
||||
{ status: 200 }
|
||||
);
|
||||
}
|
||||
|
||||
// 限制每页最大数量,防止性能问题
|
||||
if (size > 100) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 400,
|
||||
message: '每页最多只能查询100条数据',
|
||||
status: 'fail',
|
||||
},
|
||||
{ status: 200 }
|
||||
);
|
||||
}
|
||||
|
||||
const result = await typefaceService.findAll(body);
|
||||
|
||||
// Convert Paging instance to IPageData format
|
||||
|
@ -35,7 +72,7 @@ export async function POST(
|
|||
message: 'success',
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('字体列表页面 - 获取字体列表接口错误:', error);
|
||||
Logger.error('[API-fonts/list] 获取字体列表接口错误', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
|
@ -60,7 +97,7 @@ export async function GET(): Promise<NextResponse<IResponseData<any>>> {
|
|||
message: 'success',
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('字体列表页面 - 获取所有字体接口错误:', error);
|
||||
Logger.error('[API-fonts/list] 获取字体列表接口错误', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
|
|
|
@ -33,7 +33,7 @@ export async function POST(
|
|||
message: 'success',
|
||||
});
|
||||
} catch (error: any) {
|
||||
Logger.error('字体管理页面 - 更新字体接口错误:', error);
|
||||
Logger.error('[API-fonts/update] 更新字体接口错误', error);
|
||||
return NextResponse.json(
|
||||
{
|
||||
code: 500,
|
||||
|
|
|
@ -29,7 +29,7 @@ async function fetchFonts(): Promise<TypefaceOutput[]> {
|
|||
Logger.info('获取字体列表成功,字体列表长度:', result.dataList.length);
|
||||
return [];
|
||||
} catch (error) {
|
||||
Logger.error('字体展示页面 - 获取字体列表失败:', error);
|
||||
Logger.error('[页面-fonts] 获取字体列表失败', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ export async function testConnection() {
|
|||
Logger.info('Database connection established successfully');
|
||||
return true;
|
||||
} catch (error) {
|
||||
Logger.error('数据库服务 - 数据库连接失败:', error);
|
||||
Logger.error('[数据库服务] 数据库连接失败', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ export async function closeDatabase() {
|
|||
await client.end();
|
||||
Logger.info('Database connection closed');
|
||||
} catch (error) {
|
||||
Logger.error('数据库服务 - 关闭数据库连接错误:', error);
|
||||
Logger.error('[数据库服务] 关闭数据库连接错误', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,9 +255,17 @@ export class TypefaceService {
|
|||
conditions.push(like(typefaces.languages, `%${languages}%`));
|
||||
}
|
||||
|
||||
const query = db.select().from(typefaces).where(and(...conditions));
|
||||
// 构建查询条件
|
||||
const whereCondition = conditions.length > 0 ? and(...conditions) : undefined;
|
||||
|
||||
const data = await query.limit(size).offset(offset);
|
||||
// 查询数据
|
||||
const baseQuery = db.select().from(typefaces);
|
||||
const query = whereCondition ? baseQuery.where(whereCondition) : baseQuery;
|
||||
|
||||
const data = await query
|
||||
.orderBy(desc(typefaces.createdAt))
|
||||
.limit(size)
|
||||
.offset(offset);
|
||||
|
||||
// 转换字段名以匹配前端期望的格式
|
||||
const transformedData = data.map(font => ({
|
||||
|
@ -266,9 +274,10 @@ export class TypefaceService {
|
|||
updated_at: font.updatedAt,
|
||||
}));
|
||||
|
||||
const [{ count }] = await db
|
||||
.select({ count: sql<number>`count(*)` })
|
||||
.from(typefaces);
|
||||
// 获取符合条件的总数
|
||||
const countBaseQuery = db.select({ count: sql<number>`count(*)` }).from(typefaces);
|
||||
const countQuery = whereCondition ? countBaseQuery.where(whereCondition) : countBaseQuery;
|
||||
const [{ count }] = await countQuery;
|
||||
|
||||
return new Paging(transformedData, Number(count), page, size);
|
||||
} catch (error) {
|
||||
|
@ -432,7 +441,7 @@ export class TypefaceService {
|
|||
|
||||
const processedVariants = [];
|
||||
let finalMetaInfo = null;
|
||||
|
||||
console.log(fontSubfamilies);
|
||||
// 遍历每个fontSubfamily变体
|
||||
for (const subfamily of fontSubfamilies) {
|
||||
try {
|
||||
|
@ -441,7 +450,7 @@ export class TypefaceService {
|
|||
const fontBuffer = await this.ossClient.get(ossFilePath);
|
||||
|
||||
if (!fontBuffer || !fontBuffer.content) {
|
||||
Logger.warn(`Font file not found in OSS for variant: ${subfamily}`);
|
||||
Logger.warn(`[字体服务-autoUpdate] OSS文件不存在 - 字体变体: ${subfamily}, 路径: ${ossFilePath}`);
|
||||
// eslint-disable-next-line no-continue
|
||||
continue;
|
||||
}
|
||||
|
@ -500,7 +509,7 @@ export class TypefaceService {
|
|||
if (licenseFileBuffer) break;
|
||||
}
|
||||
} catch (licenseError) {
|
||||
Logger.warn(`字体服务 - 获取许可证文件失败 ${subfamily}:`, licenseError);
|
||||
Logger.warn(`[字体服务-autoUpdate] 获取许可证文件失败 - 字体变体: ${subfamily}`, licenseError);
|
||||
}
|
||||
|
||||
// 上传处理后的文件到 OSS
|
||||
|
@ -513,9 +522,9 @@ export class TypefaceService {
|
|||
licenseFileBuffer,
|
||||
licenseFileName,
|
||||
});
|
||||
Logger.info(`字体服务 - 成功上传字体变体到OSS: ${subfamily}`);
|
||||
Logger.info(`[字体服务-autoUpdate] OSS上传成功 - 字体变体: ${subfamily}`);
|
||||
} catch (uploadError) {
|
||||
Logger.error(`字体服务 - OSS上传字体变体失败: ${subfamily}`, uploadError);
|
||||
Logger.error(`[字体服务-autoUpdate] OSS上传失败 - 字体变体: ${subfamily}`, uploadError);
|
||||
// 继续处理,不因为上传失败而中断整个流程
|
||||
}
|
||||
|
||||
|
@ -526,17 +535,17 @@ export class TypefaceService {
|
|||
finalMetaInfo = metaInfo;
|
||||
}
|
||||
|
||||
Logger.info(`字体服务 - 成功处理字体变体: ${subfamily}`);
|
||||
Logger.info(`[字体服务-autoUpdate] 字体变体处理成功: ${subfamily}`);
|
||||
|
||||
// 清理临时文件目录
|
||||
try {
|
||||
await rm(fontPackageDir, { recursive: true, force: true });
|
||||
Logger.info(`字体服务 - 清理临时目录: ${fontPackageDir}`);
|
||||
Logger.info(`[字体服务-autoUpdate] 临时目录清理成功: ${fontPackageDir}`);
|
||||
} catch (cleanupError) {
|
||||
Logger.warn(`字体服务 - 清理临时目录失败: ${fontPackageDir}`, cleanupError);
|
||||
Logger.warn(`[字体服务-autoUpdate] 临时目录清理失败: ${fontPackageDir}`, cleanupError);
|
||||
}
|
||||
} catch (variantError) {
|
||||
Logger.error(`字体服务 - 处理字体变体失败: ${subfamily}`, variantError);
|
||||
Logger.error(`[字体服务-autoUpdate] 字体变体处理失败: ${subfamily}`, variantError);
|
||||
// 继续处理下一个变体,不中断整个流程
|
||||
}
|
||||
}
|
||||
|
@ -577,7 +586,7 @@ export class TypefaceService {
|
|||
metaInfo: finalMetaInfo,
|
||||
};
|
||||
} catch (error) {
|
||||
Logger.error('字体服务 - 自动更新失败:', error);
|
||||
Logger.error(`[字体服务-autoUpdate] 自动更新失败 - 字体ID: ${id}`, error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
@ -723,9 +732,9 @@ export class TypefaceService {
|
|||
if (fontPackageDir) {
|
||||
try {
|
||||
await rm(fontPackageDir, { recursive: true, force: true });
|
||||
Logger.info(`字体服务 - 清理临时目录: ${fontPackageDir}`);
|
||||
Logger.info(`[字体服务-create] 临时目录清理成功: ${fontPackageDir}`);
|
||||
} catch (cleanupError) {
|
||||
Logger.warn(`字体服务 - 清理临时目录失败: ${fontPackageDir}`, cleanupError);
|
||||
Logger.warn(`[字体服务-create] 临时目录清理失败: ${fontPackageDir}`, cleanupError);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -735,7 +744,7 @@ export class TypefaceService {
|
|||
|
||||
return result;
|
||||
} catch (error) {
|
||||
Logger.error('字体服务 - 创建字体失败:', error);
|
||||
Logger.error('[字体服务-create] 创建字体失败', error);
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
@ -853,7 +862,7 @@ export class TypefaceService {
|
|||
);
|
||||
|
||||
if (failedFiles.length > 0) {
|
||||
Logger.warn('以下文件上传失败:', failedFiles.map(f => `${f.fileName}: ${f.error}`));
|
||||
Logger.warn(`[字体服务-uploadToOSS] 部分文件上传失败 - 字体: ${fontFamily}-${fontSubfamily}`, failedFiles.map(f => `${f.fileName}: ${f.error}`));
|
||||
// 如果关键文件上传失败,抛出错误
|
||||
const criticalFiles = [`${fontFamily}-${fontSubfamily}.ttf`, `${OSS_CONFIG.subFolderWeb}.zip`];
|
||||
const failedCriticalFiles = failedFiles.filter(f =>
|
||||
|
@ -865,7 +874,7 @@ export class TypefaceService {
|
|||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
Logger.error('字体服务 - OSS上传失败:', error);
|
||||
Logger.error(`[字体服务-uploadToOSS] OSS上传失败 - 字体: ${fontFamily}-${fontSubfamily}`, error);
|
||||
throw new Error(`OSS upload failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
@ -979,7 +988,7 @@ export class TypefaceService {
|
|||
errors: undefined,
|
||||
};
|
||||
} catch (error) {
|
||||
Logger.error('字体服务 - 批量更新事务失败:', error);
|
||||
Logger.error('[字体服务-batchUpdate] 批量更新事务失败', error);
|
||||
return {
|
||||
success: false,
|
||||
results,
|
||||
|
|
|
@ -29,7 +29,7 @@ export class ConcurrentUploader {
|
|||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
this.results.push({ success: false, fileName, error: errorMessage });
|
||||
Logger.error(`字体服务 - 文件上传失败 ${fileName}:`, error);
|
||||
Logger.error(`[字体服务-concurrent-uploader] 文件上传失败 - 文件: ${fileName}`, error);
|
||||
resolve(); // 不要 reject,让其他文件继续上传
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue