From a6847e28de80305e462be5b536bf64b3762478cc Mon Sep 17 00:00:00 2001 From: "bo.yu" Date: Fri, 22 Aug 2025 17:45:41 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=9F=E4=B8=80=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=B9=B6=E4=BF=AE=E5=A4=8D=E5=AD=97=E4=BD=93?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3=E5=8F=82=E6=95=B0=E9=AA=8C?= =?UTF-8?q?=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor(字体服务): 重构日志格式添加上下文信息 fix(API-fonts/list): 添加分页参数验证和限制 style: 调整代码格式和注释 --- .gitignore | 2 +- app/admin/manage/page.tsx | 2 +- app/api/css/route.ts | 8 ++-- app/api/fonts/auto_update/[id]/route.ts | 2 +- app/api/fonts/create/route.ts | 2 +- app/api/fonts/delete/route.ts | 2 +- app/api/fonts/detail/[id]/route.ts | 4 +- app/api/fonts/list/route.ts | 41 +++++++++++++++++++- app/api/fonts/update/route.ts | 2 +- app/fonts/page.tsx | 2 +- src/lib/database/index.ts | 4 +- src/lib/services/typeface.service.ts | 51 +++++++++++++++---------- src/lib/utils/concurrent-uploader.ts | 2 +- 13 files changed, 85 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index 797bead..2fe7c0c 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,7 @@ web_modules/ # Optional eslint cache .eslintcache -.vscode/settings.json +.vscode/* # Optional prettier cache .prettiercache diff --git a/app/admin/manage/page.tsx b/app/admin/manage/page.tsx index b48bc54..486155f 100644 --- a/app/admin/manage/page.tsx +++ b/app/admin/manage/page.tsx @@ -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, }); diff --git a/app/api/css/route.ts b/app/api/css/route.ts index 30076a0..7eb6de9 100644 --- a/app/api/css/route.ts +++ b/app/api/css/route.ts @@ -194,7 +194,7 @@ export async function GET(request: NextRequest): Promise { }, }); } 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; } } diff --git a/app/api/fonts/auto_update/[id]/route.ts b/app/api/fonts/auto_update/[id]/route.ts index 2d01910..e0356eb 100644 --- a/app/api/fonts/auto_update/[id]/route.ts +++ b/app/api/fonts/auto_update/[id]/route.ts @@ -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, diff --git a/app/api/fonts/create/route.ts b/app/api/fonts/create/route.ts index 0a82fa3..51848e1 100644 --- a/app/api/fonts/create/route.ts +++ b/app/api/fonts/create/route.ts @@ -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, diff --git a/app/api/fonts/delete/route.ts b/app/api/fonts/delete/route.ts index 5007738..de5030a 100644 --- a/app/api/fonts/delete/route.ts +++ b/app/api/fonts/delete/route.ts @@ -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, diff --git a/app/api/fonts/detail/[id]/route.ts b/app/api/fonts/detail/[id]/route.ts index b0d3f97..f6bf433 100644 --- a/app/api/fonts/detail/[id]/route.ts +++ b/app/api/fonts/detail/[id]/route.ts @@ -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, diff --git a/app/api/fonts/list/route.ts b/app/api/fonts/list/route.ts index 09afc24..d66fdfd 100644 --- a/app/api/fonts/list/route.ts +++ b/app/api/fonts/list/route.ts @@ -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>> { message: 'success', }); } catch (error: any) { - Logger.error('字体列表页面 - 获取所有字体接口错误:', error); + Logger.error('[API-fonts/list] 获取字体列表接口错误', error); return NextResponse.json( { code: 500, diff --git a/app/api/fonts/update/route.ts b/app/api/fonts/update/route.ts index e98f111..87693d8 100644 --- a/app/api/fonts/update/route.ts +++ b/app/api/fonts/update/route.ts @@ -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, diff --git a/app/fonts/page.tsx b/app/fonts/page.tsx index 5bfc0a2..3ed4eba 100644 --- a/app/fonts/page.tsx +++ b/app/fonts/page.tsx @@ -29,7 +29,7 @@ async function fetchFonts(): Promise { Logger.info('获取字体列表成功,字体列表长度:', result.dataList.length); return []; } catch (error) { - Logger.error('字体展示页面 - 获取字体列表失败:', error); + Logger.error('[页面-fonts] 获取字体列表失败', error); return []; } } diff --git a/src/lib/database/index.ts b/src/lib/database/index.ts index b0439ac..c2ade0e 100644 --- a/src/lib/database/index.ts +++ b/src/lib/database/index.ts @@ -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; } } diff --git a/src/lib/services/typeface.service.ts b/src/lib/services/typeface.service.ts index a9cba74..15cee9c 100644 --- a/src/lib/services/typeface.service.ts +++ b/src/lib/services/typeface.service.ts @@ -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`count(*)` }) - .from(typefaces); + // 获取符合条件的总数 + const countBaseQuery = db.select({ count: sql`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, diff --git a/src/lib/utils/concurrent-uploader.ts b/src/lib/utils/concurrent-uploader.ts index 03640b4..2dda9bf 100644 --- a/src/lib/utils/concurrent-uploader.ts +++ b/src/lib/utils/concurrent-uploader.ts @@ -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,让其他文件继续上传 } });