add
This commit is contained in:
parent
9d6e9136cf
commit
4ff101ab7b
|
@ -200,6 +200,8 @@ export class PostService extends BaseTreeService<Prisma.PostDelegate> {
|
|||
rating: number | null;
|
||||
createdAt: Date;
|
||||
views: number;
|
||||
hates: number;
|
||||
likes: number;
|
||||
publishedAt: Date | null;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date | null;
|
||||
|
|
|
@ -15,13 +15,13 @@ export class VisitRouter {
|
|||
private readonly visitService: VisitService,
|
||||
) {}
|
||||
router = this.trpc.router({
|
||||
create: this.trpc.protectProcedure
|
||||
create: this.trpc.procedure
|
||||
.input(VisitCreateArgsSchema)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const { staff } = ctx;
|
||||
return await this.visitService.create(input, staff);
|
||||
}),
|
||||
createMany: this.trpc.protectProcedure
|
||||
createMany: this.trpc.procedure
|
||||
.input(z.array(VisitCreateManyInputSchema))
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const { staff } = ctx;
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
export async function updateTotalCourseViewCount(type: VisitType) {
|
||||
const posts = await db.post.findMany({
|
||||
where: {
|
||||
type: { in: [PostType.COURSE, PostType.LECTURE] },
|
||||
// type: { in: [PostType.COURSE, PostType.LECTURE,] },
|
||||
deletedAt: null,
|
||||
},
|
||||
select: { id: true, type: true },
|
||||
|
@ -66,27 +66,34 @@ export async function updatePostViewCount(id: string, type: VisitType) {
|
|||
where: { id },
|
||||
select: { id: true, meta: true, type: true },
|
||||
});
|
||||
console.log(post?.type);
|
||||
console.log('updatePostViewCount');
|
||||
const metaFieldMap = {
|
||||
[VisitType.READED]: 'views',
|
||||
[VisitType.LIKE]: 'likes',
|
||||
[VisitType.HATE]: 'hates',
|
||||
};
|
||||
if (post?.type === PostType.LECTURE) {
|
||||
const course = await db.postAncestry.findFirst({
|
||||
const courseAncestry = await db.postAncestry.findFirst({
|
||||
where: {
|
||||
descendantId: post?.id,
|
||||
ancestor: {
|
||||
type: PostType.COURSE,
|
||||
},
|
||||
},
|
||||
select: { id: true },
|
||||
select: { id: true, ancestorId: true },
|
||||
});
|
||||
const lectures = await db.postAncestry.findMany({
|
||||
const course = { id: courseAncestry.ancestorId };
|
||||
const lecturesAncestry = await db.postAncestry.findMany({
|
||||
where: { ancestorId: course.id, descendant: { type: PostType.LECTURE } },
|
||||
select: {
|
||||
id: true,
|
||||
descendantId: true,
|
||||
},
|
||||
});
|
||||
const lectures = lecturesAncestry.map((ancestry) => ({
|
||||
id: ancestry.descendantId,
|
||||
}));
|
||||
const courseViews = await db.visit.aggregate({
|
||||
_sum: {
|
||||
views: true,
|
||||
|
@ -98,9 +105,11 @@ export async function updatePostViewCount(id: string, type: VisitType) {
|
|||
type: type,
|
||||
},
|
||||
});
|
||||
console.log(courseViews);
|
||||
await db.post.update({
|
||||
where: { id: course.id },
|
||||
data: {
|
||||
[metaFieldMap[type]]: courseViews._sum.views || 0,
|
||||
meta: {
|
||||
...((post?.meta as any) || {}),
|
||||
[metaFieldMap[type]]: courseViews._sum.views || 0,
|
||||
|
@ -117,9 +126,11 @@ export async function updatePostViewCount(id: string, type: VisitType) {
|
|||
type: type,
|
||||
},
|
||||
});
|
||||
console.log('totalViews', totalViews);
|
||||
await db.post.update({
|
||||
where: { id },
|
||||
data: {
|
||||
[metaFieldMap[type]]: totalViews._sum.views || 0,
|
||||
meta: {
|
||||
...((post?.meta as any) || {}),
|
||||
[metaFieldMap[type]]: totalViews._sum.views || 0,
|
||||
|
|
|
@ -24,7 +24,7 @@ const DeptInfo = ({ post }: { post: PostDto }) => {
|
|||
<div className="flex items-center gap-2">
|
||||
<span className="gap-1 text-xs font-medium text-gray-500 flex items-center">
|
||||
<EyeOutlined />
|
||||
{`${post?.meta?.views || 0}`}
|
||||
{`${post?.views || 0}`}
|
||||
</span>
|
||||
{post?.studentIds && post?.studentIds?.length > 0 && (
|
||||
<span className="gap-1 text-xs font-medium text-gray-500 flex items-center">
|
||||
|
|
|
@ -80,6 +80,7 @@ export function CourseDetailProvider({
|
|||
|
||||
useEffect(() => {
|
||||
if (lecture?.id) {
|
||||
console.log(123);
|
||||
read.mutateAsync({
|
||||
data: {
|
||||
visitorId: user?.id || null,
|
||||
|
|
|
@ -36,11 +36,11 @@ export const CourseDetailDescription: React.FC = () => {
|
|||
{!selectedLectureId && (
|
||||
<div className="relative mb-4 overflow-hidden flex justify-center items-center">
|
||||
{
|
||||
<Image
|
||||
src={course.meta.thumbnail}
|
||||
preview={false}
|
||||
className="w-full h-full object-cover z-0"
|
||||
fallback="/placeholder.webp"
|
||||
<div
|
||||
className="w-full rounded-xl aspect-video bg-cover bg-center z-0"
|
||||
style={{
|
||||
backgroundImage: `url(${course?.meta?.thumbnail || "/placeholder.webp"})`,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
<div
|
||||
|
@ -59,7 +59,7 @@ export const CourseDetailDescription: React.FC = () => {
|
|||
});
|
||||
}
|
||||
}}
|
||||
className="w-full h-full absolute top-0 z-10 bg-[rgba(0,0,0,0.3)] transition-all duration-300 ease-in-out hover:bg-[rgba(0,0,0,0.7)] cursor-pointer group">
|
||||
className="absolute rounded-xl top-0 left-0 right-0 bottom-0 z-10 bg-[rgba(0,0,0,0.3)] transition-all duration-300 ease-in-out hover:bg-[rgba(0,0,0,0.7)] cursor-pointer group">
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-white text-4xl z-10 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
点击进入学习
|
||||
</div>
|
||||
|
|
|
@ -12,11 +12,12 @@ import dayjs from "dayjs";
|
|||
import CourseOperationBtns from "./JoinLearingButton";
|
||||
|
||||
export default function CourseDetailTitle() {
|
||||
const { course } = useContext(CourseDetailContext);
|
||||
const { course, lecture, selectedLectureId } =
|
||||
useContext(CourseDetailContext);
|
||||
return (
|
||||
<div className="flex justify-center flex-col items-center gap-2 w-full my-2 px-6">
|
||||
<div className="flex justify-start w-full text-2xl font-bold">
|
||||
{course?.title}
|
||||
{!selectedLectureId ? course?.title : lecture?.title}
|
||||
</div>
|
||||
<div className="text-gray-600 flex w-full justify-start items-center gap-5">
|
||||
{course?.author?.showname && (
|
||||
|
@ -36,15 +37,25 @@ export default function CourseDetailTitle() {
|
|||
<div className="flex gap-1">
|
||||
<CalendarOutlined></CalendarOutlined>
|
||||
{"发布于:"}
|
||||
{dayjs(course?.createdAt).format("YYYY年M月D日")}
|
||||
{dayjs(
|
||||
!selectedLectureId
|
||||
? course?.createdAt
|
||||
: lecture?.createdAt
|
||||
).format("YYYY年M月D日")}
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
{"最后更新:"}
|
||||
{dayjs(course?.updatedAt).format("YYYY年M月D日")}
|
||||
{dayjs(
|
||||
!selectedLectureId
|
||||
? course?.updatedAt
|
||||
: lecture?.updatedAt
|
||||
).format("YYYY年M月D日")}
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<EyeOutlined></EyeOutlined>
|
||||
<div>{`观看次数${course?.meta?.views || 0}`}</div>
|
||||
<div>{`观看次数${
|
||||
!selectedLectureId ? course?.views : lecture?.views || 0
|
||||
}`}</div>
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<BookOutlined />
|
||||
|
|
|
@ -45,7 +45,9 @@ export const LectureItem: React.FC<LectureItemProps> = ({
|
|||
</div>
|
||||
)}
|
||||
<div className="flex-grow flex justify-between items-center w-2/3 realative">
|
||||
<h4 className="font-medium text-gray-800 w-4/5">{lecture.title}</h4>
|
||||
<h4 className="font-medium text-gray-800 w-4/5">
|
||||
{lecture.title}
|
||||
</h4>
|
||||
{lecture.subTitle && (
|
||||
<span className="text-sm text-gray-500 mt-1 w-4/5">
|
||||
{lecture.subTitle}
|
||||
|
@ -53,7 +55,9 @@ export const LectureItem: React.FC<LectureItemProps> = ({
|
|||
)}
|
||||
<div className="text-gray-500 whitespace-normal">
|
||||
<EyeOutlined></EyeOutlined>
|
||||
<span className="ml-2">{lecture?.meta?.views ? lecture?.meta?.views : 0}</span>
|
||||
<span className="ml-2">
|
||||
{lecture?.views ? lecture?.views : 0}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -101,13 +101,17 @@ export function CourseFormProvider({
|
|||
terms:
|
||||
termIds?.length > 0
|
||||
? {
|
||||
set: termIds.map((id) => ({ id })), // 转换成 connect 格式
|
||||
[editId ? "set" : "connect"]: termIds.map((id) => ({
|
||||
id,
|
||||
})), // 转换成 connect 格式
|
||||
}
|
||||
: undefined,
|
||||
depts:
|
||||
deptIds?.length > 0
|
||||
? {
|
||||
set: deptIds.map((id) => ({ id })),
|
||||
[editId ? "set" : "connect"]: deptIds.map((id) => ({
|
||||
id,
|
||||
})),
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
|
|
|
@ -115,7 +115,7 @@ export const SortableLecture: React.FC<SortableLectureProps> = ({
|
|||
resources:
|
||||
[videoUrlId, ...fileIds].filter(Boolean)?.length > 0
|
||||
? {
|
||||
connect: [videoUrlId, ...fileIds]
|
||||
set: [videoUrlId, ...fileIds]
|
||||
.filter(Boolean)
|
||||
.map((fileId) => ({
|
||||
fileId,
|
||||
|
|
|
@ -207,6 +207,8 @@ model Post {
|
|||
students Staff[] @relation("post_student")
|
||||
depts Department[] @relation("post_dept")
|
||||
views Int @default(0) @map("views")
|
||||
hates Int @default(0) @map("hates")
|
||||
likes Int @default(0) @map("likes")
|
||||
// 索引
|
||||
// 日期时间类型字段
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
|
|
@ -45,11 +45,13 @@ export const postDetailSelect: Prisma.PostSelect = {
|
|||
},
|
||||
},
|
||||
meta: true,
|
||||
views: true,
|
||||
};
|
||||
export const postUnDetailSelect: Prisma.PostSelect = {
|
||||
id: true,
|
||||
type: true,
|
||||
title: true,
|
||||
views: true,
|
||||
parent: true,
|
||||
parentId: true,
|
||||
content: true,
|
||||
|
@ -79,6 +81,7 @@ export const messageDetailSelect: Prisma.MessageSelect = {
|
|||
id: true,
|
||||
sender: true,
|
||||
content: true,
|
||||
|
||||
title: true,
|
||||
url: true,
|
||||
option: true,
|
||||
|
@ -88,6 +91,7 @@ export const courseDetailSelect: Prisma.PostSelect = {
|
|||
id: true,
|
||||
title: true,
|
||||
subTitle: true,
|
||||
views: true,
|
||||
type: true,
|
||||
author: true,
|
||||
authorId: true,
|
||||
|
@ -124,6 +128,7 @@ export const lectureDetailSelect: Prisma.PostSelect = {
|
|||
subTitle: true,
|
||||
content: true,
|
||||
resources: true,
|
||||
views: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
// 关联表选择
|
||||
|
|
Loading…
Reference in New Issue