From 5fe31a880556417a19b4d24ae7942c773138b103 Mon Sep 17 00:00:00 2001 From: wangdl Date: Fri, 29 May 2026 19:29:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20H0-10=20=E5=AD=98=E5=82=A8=E7=A9=BA?= =?UTF-8?q?=E9=97=B4=E7=BB=9F=E8=AE=A1=20+=20=E5=AD=A6=E4=B9=A0=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E8=AE=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /users/me/storage(totalBytes/usedBytes/fileCount) - GET /users/me/assets-summary(kbCount/itemCount/cardCount) Co-Authored-By: Claude Opus 4.7 --- src/modules/users/users.controller.ts | 14 ++++++++++++++ src/modules/users/users.service.ts | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/modules/users/users.controller.ts b/src/modules/users/users.controller.ts index 5c3f71e..c60ee15 100644 --- a/src/modules/users/users.controller.ts +++ b/src/modules/users/users.controller.ts @@ -77,4 +77,18 @@ export class UsersController { async removeDevice(@CurrentUser() user: UserPayload, @Param('deviceId') deviceId: string) { return this.usersService.removeDevice(String(user.id), deviceId); } + + // ── Storage & Assets ── + + @Get('me/storage') + @ApiOperation({ summary: '存储空间统计' }) + async getStorage(@CurrentUser() user: UserPayload) { + return this.usersService.getStorage(String(user.id)); + } + + @Get('me/assets-summary') + @ApiOperation({ summary: '学习资产摘要' }) + async getAssetsSummary(@CurrentUser() user: UserPayload) { + return this.usersService.getAssetsSummary(String(user.id)); + } } diff --git a/src/modules/users/users.service.ts b/src/modules/users/users.service.ts index 248abb0..3d058c2 100644 --- a/src/modules/users/users.service.ts +++ b/src/modules/users/users.service.ts @@ -68,4 +68,27 @@ export class UsersService { }); return { success: true }; } + + // ── Storage ── + + async getStorage(userId: string) { + const files = await this.prisma.uploadedFile.findMany({ + where: { userId }, + select: { sizeBytes: true, mimeType: true }, + }); + const usedBytes = files.reduce((sum, f) => sum + f.sizeBytes, 0); + const totalBytes = 1024 * 1024 * 1024; // 1GB hardcoded for now + return { totalBytes, usedBytes, fileCount: files.length }; + } + + // ── Assets Summary ── + + async getAssetsSummary(userId: string) { + const [kbCount, itemCount, cardCount] = await Promise.all([ + this.prisma.knowledgeBase.count({ where: { userId, deletedAt: null } }), + this.prisma.knowledgeItem.count({ where: { userId, deletedAt: null } }), + this.prisma.reviewCard.count({ where: { userId } }), + ]); + return { knowledgeBaseCount: kbCount, knowledgeItemCount: itemCount, reviewCardCount: cardCount }; + } }