// server/utils/plazaPosts.ts - 广场发布记录数据库操作:公开、取消公开和广场列表查询。 import type { IImagePublicStateData, IPlazaPostItem, IPlazaPostListData } from "#shared/types/openai"; import { ImageGenerationStatus, PlazaPostStatus } from "~~/app/generated/prisma/client"; import { prisma } from "~~/server/utils/prisma"; const ANONYMOUS_AUTHOR_NAME = "匿名用户"; export type PublishPlazaPostResult = IImagePublicStateData | null | "REMOVED"; export const publishImageGenerationToPlaza = async ( userId: number, recordId: bigint ): Promise => { const record = await prisma.imageGeneration.findFirst({ where: { id: recordId, userId, deletedAt: null }, select: { id: true, userId: true, plazaPost: { select: { status: true } } } }); if (!record) return null; if (record.plazaPost?.status === PlazaPostStatus.REMOVED) return "REMOVED"; await prisma.plazaPost.upsert({ where: { imageGenerationId: record.id }, create: { imageGenerationId: record.id, userId: record.userId, status: PlazaPostStatus.PUBLIC }, update: { status: PlazaPostStatus.PUBLIC, hiddenAt: null, removedAt: null } }); return { isPublic: true }; }; export const hideImageGenerationFromPlaza = async ( userId: number, recordId: bigint ): Promise => { const record = await prisma.imageGeneration.findFirst({ where: { id: recordId, userId, deletedAt: null }, select: { id: true } }); if (!record) return null; const result = await prisma.plazaPost.updateMany({ where: { imageGenerationId: record.id, userId, status: { not: PlazaPostStatus.REMOVED } }, data: { status: PlazaPostStatus.HIDDEN, hiddenAt: new Date() } }); if (result.count === 0) return null; return { isPublic: false }; }; export const listPlazaPosts = async ({ page, pageSize }: { page: number; pageSize: number; }): Promise => { const where = { status: PlazaPostStatus.PUBLIC, imageGeneration: { status: ImageGenerationStatus.SUCCEEDED, deletedAt: null, hostedImageUrl: { not: null } } }; const [total, posts] = await Promise.all([ prisma.plazaPost.count({ where }), prisma.plazaPost.findMany({ where, include: { imageGeneration: { select: { id: true, prompt: true, hostedImageUrl: true } }, user: { select: { displayName: true, username: true } } }, orderBy: { publishedAt: "desc" }, skip: (page - 1) * pageSize, take: pageSize }) ]); return { page, pageSize, total, items: posts .map(mapPlazaPostItem) .filter((item): item is IPlazaPostItem => Boolean(item)) }; }; const mapPlazaPostItem = (post: { id: bigint; publishedAt: Date; imageGeneration: { id: bigint; prompt: string; hostedImageUrl: string | null; }; user: { displayName: string; username: string; }; }): IPlazaPostItem | null => { if (!post.imageGeneration.hostedImageUrl) return null; return { id: post.id.toString(), imageGenerationId: post.imageGeneration.id.toString(), prompt: post.imageGeneration.prompt, hostedImageUrl: post.imageGeneration.hostedImageUrl, authorDisplayName: post.user.displayName || post.user.username || ANONYMOUS_AUTHOR_NAME, publishedAt: post.publishedAt.toISOString() }; };