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 { 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 { const [row] = await dbGlobal .select() .from(characterCards) .where(eq(characterCards.slug, slug)) .limit(1); return row ?? null; } export async function getCharacterCardById(id: number): Promise { const [row] = await dbGlobal .select() .from(characterCards) .where(eq(characterCards.id, id)) .limit(1); return row ?? null; } export async function listCharacterCards(onlyEnabled = true): Promise { 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 { 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 { 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 = {}; 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 { await dbGlobal.delete(characterCards).where(eq(characterCards.id, id)); }