api-server/src/modules/knowledge-base/knowledge-base.repository.ts
wangdl b9f8334245
Some checks failed
Deploy API Server / build-and-deploy (push) Failing after 11s
feat: H0-08 KnowledgeBase 增加业务字段 + 订阅 + 发现 + 置顶 + 公开
Schema 新增:
- coverType/coverIcon/coverColor(封面类型/系统图标/颜色)
- visibility(private/public)
- isPinned(置顶)
- ownerType(user/official)
- isVerified(认证标识)
- KnowledgeBaseSubscription 表

API 新增:
- POST /knowledge-bases/:id/pin(切换置顶)
- PATCH /knowledge-bases/:id/visibility(切换公开/私有)
- POST /knowledge-bases/:id/subscribe(订阅)
- DELETE /knowledge-bases/:id/subscribe(取消订阅)
- GET /knowledge-bases/subscribed(已订阅列表)
- GET /knowledge-bases/discover(发现公开库)

增强:
- findAll 支持 visibility/ownerType 筛选 + 置顶优先排序
- findOne 公开库允许任何人查看
- update 支持所有新字段

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 19:24:21 +08:00

157 lines
4.1 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { PrismaService } from '../../infrastructure/database/prisma.service';
@Injectable()
export class KnowledgeBaseRepository {
constructor(private readonly prisma: PrismaService) {}
async create(userId: string, dto: {
title: string;
description?: string;
coverKey?: string;
coverType?: string;
coverIcon?: string;
coverColor?: string;
visibility?: string;
}) {
return this.prisma.knowledgeBase.create({
data: {
userId,
title: dto.title,
description: dto.description ?? '',
coverKey: dto.coverKey ?? null,
coverType: dto.coverType ?? 'custom',
coverIcon: dto.coverIcon ?? null,
coverColor: dto.coverColor ?? null,
visibility: dto.visibility ?? 'private',
status: 'active',
itemCount: 0,
},
});
}
async findById(id: string) {
return this.prisma.knowledgeBase.findUnique({ where: { id } });
}
async findAllByUserId(
userId: string,
opts?: {
page?: number;
limit?: number;
visibility?: string;
ownerType?: string;
},
) {
const page = opts?.page ?? 1;
const limit = opts?.limit ?? 20;
const where: any = { userId, deletedAt: null };
if (opts?.visibility) where.visibility = opts.visibility;
if (opts?.ownerType) where.ownerType = opts.ownerType;
return this.prisma.knowledgeBase.findMany({
where,
orderBy: [{ isPinned: 'desc' }, { updatedAt: 'desc' }],
skip: (page - 1) * limit,
take: limit,
});
}
async findAllPublic(opts?: { page?: number; limit?: number; search?: string }) {
const page = opts?.page ?? 1;
const limit = opts?.limit ?? 20;
const where: any = { visibility: 'public', deletedAt: null };
if (opts?.search) {
where.OR = [
{ title: { contains: opts.search } },
{ description: { contains: opts.search } },
];
}
return this.prisma.knowledgeBase.findMany({
where,
orderBy: [{ isPinned: 'desc' }, { updatedAt: 'desc' }],
skip: (page - 1) * limit,
take: limit,
});
}
async countByUserId(userId: string) {
return this.prisma.knowledgeBase.count({
where: { userId, deletedAt: null },
});
}
async update(id: string, dto: {
title?: string;
description?: string;
coverKey?: string;
coverType?: string;
coverIcon?: string;
coverColor?: string;
visibility?: string;
isPinned?: boolean;
}) {
return this.prisma.knowledgeBase.update({
where: { id },
data: dto,
});
}
async togglePin(id: string, isPinned: boolean) {
return this.prisma.knowledgeBase.update({
where: { id },
data: { isPinned },
});
}
async setVisibility(id: string, visibility: string) {
return this.prisma.knowledgeBase.update({
where: { id },
data: { visibility },
});
}
async softDelete(id: string) {
await this.prisma.knowledgeBase.update({
where: { id },
data: { deletedAt: new Date() },
});
return true;
}
// ── Subscription ──
async subscribe(userId: string, knowledgeBaseId: string) {
return this.prisma.knowledgeBaseSubscription.create({
data: { userId, knowledgeBaseId },
});
}
async unsubscribe(userId: string, knowledgeBaseId: string) {
await this.prisma.knowledgeBaseSubscription.deleteMany({
where: { userId, knowledgeBaseId },
});
return true;
}
async findSubscribed(userId: string, opts?: { page?: number; limit?: number }) {
const page = opts?.page ?? 1;
const limit = opts?.limit ?? 20;
return this.prisma.knowledgeBase.findMany({
where: {
subscriptions: { some: { userId } },
deletedAt: null,
},
orderBy: { updatedAt: 'desc' },
skip: (page - 1) * limit,
take: limit,
});
}
async isSubscribed(userId: string, knowledgeBaseId: string): Promise<boolean> {
const sub = await this.prisma.knowledgeBaseSubscription.findUnique({
where: { userId_knowledgeBaseId: { userId, knowledgeBaseId } },
});
return !!sub;
}
}