2026-05-09 18:25:04 +08:00
|
|
|
import { Injectable } from '@nestjs/common';
|
2026-05-17 00:39:46 +08:00
|
|
|
import { PrismaService } from '../../infrastructure/database/prisma.service';
|
2026-05-09 18:25:04 +08:00
|
|
|
|
|
|
|
|
@Injectable()
|
|
|
|
|
export class KnowledgeBaseRepository {
|
2026-05-17 00:39:46 +08:00
|
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
|
|
2026-05-29 19:24:21 +08:00
|
|
|
async create(userId: string, dto: {
|
|
|
|
|
title: string;
|
|
|
|
|
description?: string;
|
|
|
|
|
coverKey?: string;
|
|
|
|
|
coverType?: string;
|
|
|
|
|
coverIcon?: string;
|
|
|
|
|
coverColor?: string;
|
|
|
|
|
visibility?: string;
|
|
|
|
|
}) {
|
2026-05-17 00:39:46 +08:00
|
|
|
return this.prisma.knowledgeBase.create({
|
|
|
|
|
data: {
|
|
|
|
|
userId,
|
|
|
|
|
title: dto.title,
|
|
|
|
|
description: dto.description ?? '',
|
2026-05-28 10:42:58 +08:00
|
|
|
coverKey: dto.coverKey ?? null,
|
2026-05-29 19:24:21 +08:00
|
|
|
coverType: dto.coverType ?? 'custom',
|
|
|
|
|
coverIcon: dto.coverIcon ?? null,
|
|
|
|
|
coverColor: dto.coverColor ?? null,
|
|
|
|
|
visibility: dto.visibility ?? 'private',
|
2026-05-17 00:39:46 +08:00
|
|
|
status: 'active',
|
|
|
|
|
itemCount: 0,
|
|
|
|
|
},
|
|
|
|
|
});
|
2026-05-09 18:25:04 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-17 00:39:46 +08:00
|
|
|
async findById(id: string) {
|
|
|
|
|
return this.prisma.knowledgeBase.findUnique({ where: { id } });
|
2026-05-09 18:25:04 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-29 19:24:21 +08:00
|
|
|
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;
|
2026-05-17 00:39:46 +08:00
|
|
|
return this.prisma.knowledgeBase.findMany({
|
2026-05-29 19:24:21 +08:00
|
|
|
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' }],
|
2026-05-17 19:08:07 +08:00
|
|
|
skip: (page - 1) * limit,
|
|
|
|
|
take: limit,
|
2026-05-17 00:39:46 +08:00
|
|
|
});
|
2026-05-09 18:25:04 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-17 00:39:46 +08:00
|
|
|
async countByUserId(userId: string) {
|
|
|
|
|
return this.prisma.knowledgeBase.count({
|
|
|
|
|
where: { userId, deletedAt: null },
|
|
|
|
|
});
|
2026-05-09 18:25:04 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-29 19:24:21 +08:00
|
|
|
async update(id: string, dto: {
|
|
|
|
|
title?: string;
|
|
|
|
|
description?: string;
|
|
|
|
|
coverKey?: string;
|
|
|
|
|
coverType?: string;
|
|
|
|
|
coverIcon?: string;
|
|
|
|
|
coverColor?: string;
|
|
|
|
|
visibility?: string;
|
|
|
|
|
isPinned?: boolean;
|
|
|
|
|
}) {
|
2026-05-17 00:39:46 +08:00
|
|
|
return this.prisma.knowledgeBase.update({
|
|
|
|
|
where: { id },
|
|
|
|
|
data: dto,
|
|
|
|
|
});
|
2026-05-09 18:25:04 +08:00
|
|
|
}
|
|
|
|
|
|
2026-05-29 19:24:21 +08:00
|
|
|
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 },
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-17 00:39:46 +08:00
|
|
|
async softDelete(id: string) {
|
|
|
|
|
await this.prisma.knowledgeBase.update({
|
|
|
|
|
where: { id },
|
|
|
|
|
data: { deletedAt: new Date() },
|
|
|
|
|
});
|
2026-05-09 18:25:04 +08:00
|
|
|
return true;
|
|
|
|
|
}
|
2026-05-29 19:24:21 +08:00
|
|
|
|
|
|
|
|
// ── 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;
|
|
|
|
|
}
|
2026-05-09 18:25:04 +08:00
|
|
|
}
|