You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

144 lines
4.8 KiB

import { dbGlobal } from "drizzle-pkg/lib/db";
import { characterCards } from "drizzle-pkg/lib/schema/character";
import { eq, and, asc, sql } from "drizzle-orm";
export type CharacterCardRow = typeof characterCards.$inferSelect;
export interface CreateCharacterCardInput {
slug: string;
name: string;
avatar?: string | null;
description?: string | null;
personality?: string | null;
scenario?: string | null;
firstMessage?: string | null;
exampleDialogue?: string | null;
systemPrompt?: string;
defaultModelId?: number | null;
tags?: string | null;
isPublic?: number;
enabled?: number;
sortOrder?: number;
}
export interface UpdateCharacterCardInput {
slug?: string;
name?: string;
avatar?: string | null;
description?: string | null;
personality?: string | null;
scenario?: string | null;
firstMessage?: string | null;
exampleDialogue?: string | null;
systemPrompt?: string;
defaultModelId?: number | null;
tags?: string | null;
isPublic?: number;
enabled?: number;
sortOrder?: number;
}
export async function getCharacterCardBySlug(slug: string): Promise<CharacterCardRow | null> {
const [row] = await dbGlobal
.select()
.from(characterCards)
.where(and(eq(characterCards.slug, slug), eq(characterCards.enabled, 1)))
.limit(1);
return row ?? null;
}
export async function getCharacterCardBySlugAny(slug: string): Promise<CharacterCardRow | null> {
const [row] = await dbGlobal
.select()
.from(characterCards)
.where(eq(characterCards.slug, slug))
.limit(1);
return row ?? null;
}
export async function getCharacterCardById(id: number): Promise<CharacterCardRow | null> {
const [row] = await dbGlobal
.select()
.from(characterCards)
.where(eq(characterCards.id, id))
.limit(1);
return row ?? null;
}
export async function listCharacterCards(onlyEnabled = true): Promise<CharacterCardRow[]> {
const where = onlyEnabled ? eq(characterCards.enabled, 1) : sql`1=1`;
return dbGlobal
.select()
.from(characterCards)
.where(where)
.orderBy(asc(characterCards.sortOrder), asc(characterCards.id));
}
export async function createCharacterCard(input: CreateCharacterCardInput): Promise<CharacterCardRow> {
const existing = await getCharacterCardBySlugAny(input.slug);
if (existing) {
throw new Error(`slug 已存在: ${input.slug}`);
}
const [row] = await dbGlobal
.insert(characterCards)
.values({
slug: input.slug,
name: input.name,
avatar: input.avatar ?? null,
description: input.description ?? null,
personality: input.personality ?? null,
scenario: input.scenario ?? null,
firstMessage: input.firstMessage ?? null,
exampleDialogue: input.exampleDialogue ?? null,
systemPrompt: input.systemPrompt ?? "",
defaultModelId: input.defaultModelId ?? null,
tags: input.tags ?? null,
isPublic: input.isPublic ?? 1,
enabled: input.enabled ?? 1,
sortOrder: input.sortOrder ?? 0,
})
.returning();
if (!row) throw new Error("创建角色卡失败");
return row;
}
export async function updateCharacterCard(
id: number,
input: UpdateCharacterCardInput,
): Promise<CharacterCardRow | null> {
const existing = await getCharacterCardById(id);
if (!existing) return null;
if (input.slug && input.slug !== existing.slug) {
const conflict = await getCharacterCardBySlugAny(input.slug);
if (conflict) {
throw new Error(`slug 已存在: ${input.slug}`);
}
}
const updates: Partial<CharacterCardRow> = {};
if (input.slug !== undefined) updates.slug = input.slug;
if (input.name !== undefined) updates.name = input.name;
if (input.avatar !== undefined) updates.avatar = input.avatar;
if (input.description !== undefined) updates.description = input.description;
if (input.personality !== undefined) updates.personality = input.personality;
if (input.scenario !== undefined) updates.scenario = input.scenario;
if (input.firstMessage !== undefined) updates.firstMessage = input.firstMessage;
if (input.exampleDialogue !== undefined) updates.exampleDialogue = input.exampleDialogue;
if (input.systemPrompt !== undefined) updates.systemPrompt = input.systemPrompt;
if (input.defaultModelId !== undefined) updates.defaultModelId = input.defaultModelId;
if (input.tags !== undefined) updates.tags = input.tags;
if (input.isPublic !== undefined) updates.isPublic = input.isPublic;
if (input.enabled !== undefined) updates.enabled = input.enabled;
if (input.sortOrder !== undefined) updates.sortOrder = input.sortOrder;
if (Object.keys(updates).length > 0) {
await dbGlobal.update(characterCards).set(updates).where(eq(characterCards.id, id));
}
return getCharacterCardById(id);
}
export async function deleteCharacterCard(id: number): Promise<void> {
await dbGlobal.delete(characterCards).where(eq(characterCards.id, id));
}