180 lines
3.7 KiB
TypeScript
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()
|
|
};
|
|
};
|