This commit is contained in:
ditiqi 2025-02-25 09:55:36 +08:00
parent f8f3e7985e
commit 3432b1af79
7 changed files with 61 additions and 24 deletions

View File

@ -7,11 +7,18 @@ import {
VisitType, VisitType,
} from '@nice/common'; } from '@nice/common';
export async function updateTotalCourseViewCount(type: VisitType) { export async function updateTotalCourseViewCount(type: VisitType) {
const courses = await db.post.findMany({ const posts = await db.post.findMany({
where: { type: PostType.COURSE }, where: {
select: { id: true }, type: { in: [PostType.COURSE, PostType.LECTURE] },
deletedAt: null,
},
select: { id: true, type: true },
}); });
const courseIds = courses.map((course) => course.id);
const courseIds = posts
.filter((post) => post.type === PostType.COURSE)
.map((course) => course.id);
const lectures = posts.filter((post) => post.type === PostType.LECTURE);
const totalViews = await db.visit.aggregate({ const totalViews = await db.visit.aggregate({
_sum: { _sum: {
views: true, views: true,
@ -30,6 +37,10 @@ export async function updateTotalCourseViewCount(type: VisitType) {
meta: true, meta: true,
}, },
}); });
const staffs = await db.staff.count({
where: { deletedAt: null },
});
const baseSeting = appConfig.meta as BaseSetting; const baseSeting = appConfig.meta as BaseSetting;
await db.appConfig.update({ await db.appConfig.update({
where: { where: {
@ -38,7 +49,15 @@ export async function updateTotalCourseViewCount(type: VisitType) {
data: { data: {
meta: { meta: {
...baseSeting, ...baseSeting,
reads: totalViews._sum.views, appConfig: {
...(baseSeting?.appConfig || {}),
statistics: {
reads: totalViews._sum.views || 0,
courses: courseIds?.length || 0,
staffs: staffs || 0,
lectures: lectures?.length || 0,
},
},
}, },
}, },
}); });

View File

@ -45,16 +45,16 @@ const carouselItems: CarouselItem[] = [
}, },
]; ];
const platformStats: PlatformStat[] = [
{ icon: <TeamOutlined />, value: "50,000+", label: "注册学员" },
{ icon: <BookOutlined />, value: "1,000+", label: "精品课程" },
// { icon: <StarOutlined />, value: '98%', label: '好评度' },
{ icon: <EyeOutlined />, value: "100万+", label: "观看次数" },
];
const HeroSection = () => { const HeroSection = () => {
const carouselRef = useRef<CarouselRef>(null); const carouselRef = useRef<CarouselRef>(null);
const { statistics, baseSetting } = useAppConfig();
const platformStats: PlatformStat[] = [
{ icon: <TeamOutlined />, value: "50,000+", label: "注册学员" },
{ icon: <BookOutlined />, value: "1,000+", label: "精品课程" },
// { icon: <StarOutlined />, value: '98%', label: '好评度' },
{ icon: <EyeOutlined />, value: "4552", label: "观看次数" },
];
const handlePrev = useCallback(() => { const handlePrev = useCallback(() => {
carouselRef.current?.prev(); carouselRef.current?.prev();
}, []); }, []);
@ -74,8 +74,8 @@ const HeroSection = () => {
dots={{ dots={{
className: "carousel-dots !bottom-32 !z-20", className: "carousel-dots !bottom-32 !z-20",
}}> }}>
{Array.isArray(carouselItems)? {Array.isArray(carouselItems) ? (
(carouselItems.map((item, index) => ( carouselItems.map((item, index) => (
<div key={index} className="relative h-[600px]"> <div key={index} className="relative h-[600px]">
<div <div
className="absolute inset-0 bg-cover bg-center transform transition-[transform,filter] duration-[2000ms] group-hover:scale-105 group-hover:brightness-110 will-change-[transform,filter]" className="absolute inset-0 bg-cover bg-center transform transition-[transform,filter] duration-[2000ms] group-hover:scale-105 group-hover:brightness-110 will-change-[transform,filter]"
@ -93,11 +93,10 @@ const HeroSection = () => {
{/* Content Container */} {/* Content Container */}
<div className="relative h-full max-w-7xl mx-auto px-6 lg:px-8"></div> <div className="relative h-full max-w-7xl mx-auto px-6 lg:px-8"></div>
</div> </div>
))) ))
:( ) : (
<div></div> <div></div>
) )}
}
</Carousel> </Carousel>
{/* Navigation Buttons */} {/* Navigation Buttons */}

View File

@ -1,6 +1,6 @@
import React from "react"; import React, { ReactNode } from "react";
export interface MenuItemType { export interface MenuItemType {
icon: React.; icon: ReactNode;
label: string; label: string;
action: () => void; action: () => void;
} }

View File

@ -2,6 +2,7 @@ import {
SkeletonItem, SkeletonItem,
SkeletonSection, SkeletonSection,
} from "@web/src/components/presentation/Skeleton"; } from "@web/src/components/presentation/Skeleton";
import { api } from "packages/client/dist";
export const CourseDetailSkeleton = () => { export const CourseDetailSkeleton = () => {
return ( return (

View File

@ -15,7 +15,7 @@ export function useTusUpload() {
>({}); >({});
const [isUploading, setIsUploading] = useState(false); const [isUploading, setIsUploading] = useState(false);
const [uploadError, setUploadError] = useState<string | null>(null); const [uploadError, setUploadError] = useState<string | null>(null);
const getFileId = (url: string) => { const getFileId = (url: string) => {
const parts = url.split("/"); const parts = url.split("/");
const uploadIndex = parts.findIndex((part) => part === "upload"); const uploadIndex = parts.findIndex((part) => part === "upload");

View File

@ -10,6 +10,7 @@ export function useAppConfig() {
api.app_config.findFirst.useQuery({ api.app_config.findFirst.useQuery({
where: { slug: AppConfigSlug.BASE_SETTING }, where: { slug: AppConfigSlug.BASE_SETTING },
}); });
const handleMutationSuccess = useCallback(() => { const handleMutationSuccess = useCallback(() => {
utils.app_config.invalidate(); utils.app_config.invalidate();
}, [utils]); }, [utils]);
@ -26,7 +27,8 @@ export function useAppConfig() {
}); });
useEffect(() => { useEffect(() => {
if (data?.meta) { if (data?.meta) {
setBaseSetting(JSON.parse(data?.meta)); // console.log(JSON.parse(data?.meta));
setBaseSetting(data?.meta);
} }
}, [data, isLoading]); }, [data, isLoading]);
const splashScreen = useMemo(() => { const splashScreen = useMemo(() => {
@ -38,6 +40,16 @@ export function useAppConfig() {
const slides = useMemo(() => { const slides = useMemo(() => {
return baseSetting?.appConfig?.slides || []; return baseSetting?.appConfig?.slides || [];
}, [baseSetting]); }, [baseSetting]);
const statistics = useMemo(() => {
return (
baseSetting?.appConfig?.statistics || {
reads: 0,
staffs: 0,
courses: 0,
lectures: 0,
}
);
}, [baseSetting]);
return { return {
create, create,
deleteMany, deleteMany,
@ -47,5 +59,6 @@ export function useAppConfig() {
devDept, devDept,
isLoading, isLoading,
slides, slides,
statistics,
}; };
} }

View File

@ -44,7 +44,12 @@ export interface BaseSetting {
splashScreen?: string; splashScreen?: string;
devDept?: string; devDept?: string;
slides?: []; slides?: [];
reads?: number; statistics?: {
reads?: number;
courses?: number;
lectures?: number;
staffs?: number;
};
}; };
} }
export type RowModelResult = { export type RowModelResult = {