From 06351c73818a99b90004971ce6c243c2bdebebd7 Mon Sep 17 00:00:00 2001 From: WangDL Date: Sun, 24 May 2026 13:34:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20M2-06=20=E2=80=94=20Artifact=20model=20?= =?UTF-8?q?+=20KnowledgeItem.learnable=20+=20Admin=20AAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Artifact base model for future FlashcardSet/Quiz/StudyGuide - KnowledgeItem.learnable boolean (default true) for M3 LearningSession - Admin AAPI: GET candidates (by status/kbId), GET items (by kbId) Co-Authored-By: Claude Opus 4.7 --- .../migration.sql | 16 ++++++++++++++ prisma/schema.prisma | 16 ++++++++++++++ .../admin-knowledge.controller.ts | 21 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 prisma/migrations/20260525040000_add_artifact_learnable/migration.sql diff --git a/prisma/migrations/20260525040000_add_artifact_learnable/migration.sql b/prisma/migrations/20260525040000_add_artifact_learnable/migration.sql new file mode 100644 index 0000000..8a01f56 --- /dev/null +++ b/prisma/migrations/20260525040000_add_artifact_learnable/migration.sql @@ -0,0 +1,16 @@ +ALTER TABLE `KnowledgeItem` ADD COLUMN `learnable` BOOLEAN NOT NULL DEFAULT true; + +CREATE TABLE IF NOT EXISTS `Artifact` ( + `id` VARCHAR(191) NOT NULL, + `userId` VARCHAR(191) NOT NULL, + `kbId` VARCHAR(191) NOT NULL, + `type` VARCHAR(32) NOT NULL, + `title` VARCHAR(255) NOT NULL, + `configJson` JSON NULL, + `status` VARCHAR(16) NOT NULL DEFAULT 'draft', + `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + `updatedAt` DATETIME(3) NOT NULL, + INDEX `Artifact_userId_idx`(`userId`), + INDEX `Artifact_kbId_idx`(`kbId`), + PRIMARY KEY (`id`) +) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f3f5e61..b297bd8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -185,6 +185,21 @@ model KnowledgeBase { @@index([status]) } +model Artifact { + id String @id @default(cuid()) + userId String + kbId String + type String @db.VarChar(32) + title String @db.VarChar(255) + configJson Json? + status String @default("draft") @db.VarChar(16) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([userId]) + @@index([kbId]) +} + model KnowledgeItem { id String @id @default(cuid()) userId String @@ -194,6 +209,7 @@ model KnowledgeItem { title String @db.VarChar(255) content String? @db.LongText summary String? @db.Text + learnable Boolean @default(true) sourceType String? @db.VarChar(32) sourceRef String? @db.VarChar(500) sourceDeleted Boolean @default(false) diff --git a/src/modules/admin-knowledge/admin-knowledge.controller.ts b/src/modules/admin-knowledge/admin-knowledge.controller.ts index cb37447..2f1ed3a 100644 --- a/src/modules/admin-knowledge/admin-knowledge.controller.ts +++ b/src/modules/admin-knowledge/admin-knowledge.controller.ts @@ -67,4 +67,25 @@ export class AdminKnowledgeController { take: 50, }); } + + // ── Candidates ── + + @Get('candidates') + @ApiOperation({ summary: '候选知识点列表' }) + async candidates(@Query('status') status?: string, @Query('kbId') kbId?: string) { + const where: any = {}; + if (status) where.status = status; + if (kbId) where.knowledgeBaseId = kbId; + return this.prisma.importCandidate.findMany({ where, orderBy: { createdAt: 'desc' }, take: 100 }); + } + + // ── Knowledge items ── + + @Get('items') + @ApiOperation({ summary: '知识点列表(管理员)' }) + async items(@Query('kbId') kbId?: string, @Query('limit') limit = '50') { + const where: any = { deletedAt: null }; + if (kbId) where.knowledgeBaseId = kbId; + return this.prisma.knowledgeItem.findMany({ where, orderBy: { createdAt: 'desc' }, take: parseInt(limit) }); + } }