Files
aiartstudio/server/utils/plazaPosts.ts
T
2026-04-26 19:17:15 +08:00

180 lines
3.7 KiB
TypeScript

// 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<PublishPlazaPostResult> => {
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<IImagePublicStateData | null> => {
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<IPlazaPostListData> => {
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()
};
};