From 668a3a015b67433cc2b8b7d17a73b418e20c45c9 Mon Sep 17 00:00:00 2001 From: Li1304553726 <1304553726@qq.com> Date: Tue, 25 Feb 2025 16:28:17 +0800 Subject: [PATCH 1/3] add. Li --- .../main/courses/components/FilterSection.tsx | 6 +-- .../main/home/components/CategorySection.tsx | 2 + .../main/home/components/CoursesSection.tsx | 37 +++++++------------ 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/apps/web/src/app/main/courses/components/FilterSection.tsx b/apps/web/src/app/main/courses/components/FilterSection.tsx index c64a1f8..9c74447 100755 --- a/apps/web/src/app/main/courses/components/FilterSection.tsx +++ b/apps/web/src/app/main/courses/components/FilterSection.tsx @@ -69,10 +69,10 @@ export default function FilterSection({ return (
-
+ {/* -
- {taxonomies.map((tax) => { + */} + {taxonomies?.map((tax) => { return ( <>
diff --git a/apps/web/src/app/main/home/components/CategorySection.tsx b/apps/web/src/app/main/home/components/CategorySection.tsx index e06a5da..d0735fa 100755 --- a/apps/web/src/app/main/home/components/CategorySection.tsx +++ b/apps/web/src/app/main/home/components/CategorySection.tsx @@ -69,6 +69,8 @@ const CategorySection = () => { const [displayedCategories,setDisplayedCategories] = useState([]) useEffect(() => { console.log(courseCategoriesData); + // 如果 showAll 为 true,则显示所有分类数据, +// 如果 showAll 为 false,则只显示前 8 个分类数据, if(!isLoading){ if(showAll){ setDisplayedCategories(courseCategoriesData) diff --git a/apps/web/src/app/main/home/components/CoursesSection.tsx b/apps/web/src/app/main/home/components/CoursesSection.tsx index ec2e759..1fe12af 100755 --- a/apps/web/src/app/main/home/components/CoursesSection.tsx +++ b/apps/web/src/app/main/home/components/CoursesSection.tsx @@ -54,7 +54,10 @@ function useFetchCoursesByCategory(category: string) { include: { terms: true, depts:true - } + }, + orderBy: { + createdAt: 'desc', // 按创建时间降序排列 + }, }); return { data, isLoading }; @@ -97,38 +100,21 @@ const CoursesSection: React.FC = ({ }) const { data, isLoading: isDataLoading } = useFetchCoursesByCategory(selectedCategory); - // useEffect(() => { - // console.log('data:', data) - // }) + + useEffect(() => { + console.log('dept data:', data) + }) const handleClick = (course: CourseDto) => { navigate(`/course/${course.id}/detail`); } - useEffect(() => { - console.log('data:', data) - }) - - // const { data: depts, isLoading: isDeptLoading }: { data: CourseDto[], isLoading: boolean } = api.post.findMany.useQuery({ - // where: {}, - // include: { - // depts: true, - // }, - // orderBy: { - // createdAt: 'desc' // 按创建时间降序排列 - // }, - // take: 8 // 只获取前8个课程 - // }); - - const filteredCourses = useMemo(() => { return selectedCategory === '全部' ? data : data?.filter(c => c.terms.some(t => t.name === selectedCategory)); }, [selectedCategory, data]); - const displayedCourses = isDataLoading ? [] : filteredCourses?.slice(0, visibleCourses); - return (
@@ -164,7 +150,7 @@ const CoursesSection: React.FC = ({ color={selectedCategory === category ? 'blue' : 'default'} onClick={() => { setSelectedCategory(category) - console.log(category) + // console.log(category) }} className={`px-6 py-2 text-base cursor-pointer rounded-full transition-all duration-300 ${selectedCategory === category ? 'bg-blue-600 text-white shadow-lg' @@ -269,7 +255,10 @@ const CoursesSection: React.FC = ({
{/*
+ ghost> 清除行模型缓存
diff --git a/apps/web/src/components/common/uploader/MultiImageUploader.tsx b/apps/web/src/components/common/uploader/MultiImageUploader.tsx new file mode 100644 index 0000000..5f6d026 --- /dev/null +++ b/apps/web/src/components/common/uploader/MultiImageUploader.tsx @@ -0,0 +1,173 @@ +import React, { useState } from 'react'; +import { Upload, Modal, message } from 'antd'; +import { PlusOutlined } from '@ant-design/icons'; +import { useTusUpload } from "@web/src/hooks/useTusUpload"; +import toast from "react-hot-toast"; + + +export interface MultiImageUploadProps { + value?: string; + placeholder?: string; + className?: string; + onChange?: (value: string) => void; + compressed?: boolean; + style?: React.CSSProperties; // 添加style属性 +} + +interface UploadFile { + name: string; + progress: number; + status: "uploading" | "done" | "error"; + url?: string; + fileKey?: string; + uid: string; +} +const MultiImageUpload: React.FC = ({ + value, + onChange, + compressed = false, + className, + placeholder = "点击上传", + style, // 解构style属性 +}) => { + const [fileList, setFileList] = useState(null); // 存储已上传的文件列表 + const [previewVisible, setPreviewVisible] = useState(false); // 控制预览模态框的显示 + const [previewImage, setPreviewImage] = useState(''); // 当前预览的图片URL + const { handleFileUpload, uploadProgress } = useTusUpload(); + const [compressedUrl, setCompressedUrl] = useState(value || ""); + const [url, setUrl] = useState(value || ""); + const [uploading, setUploading] = useState(false); + + // 处理文件上传前的校验 + const beforeUpload = (file) => { + const isImage = file.type.startsWith('image/'); + if (!isImage) { + message.error('只能上传图片文件!'); + } + const isLt10M = file.size / 1024 / 1024 < 10; + if (!isLt10M) { + message.error('图片大小不能超过10MB!'); + } + return isImage && isLt10M; + }; + + // 处理文件列表变化 + const handleChange = async ({ fileList }) => { + //setFileList(fileList); + console.log(fileList); + const imageUrls = fileList.map(file => { + return URL.createObjectURL(file.originFileObj) + }); + console.log("imageUrls", imageUrls); + + const newFileList = fileList.map(file => { + return { + name: file.name, + progress: 0, + status: "uploading", + //uid: file.uid, + fileKey: `${file.name}-${Date.now()}`, + //url: file.url, + } + }); + console.log("newFileList", newFileList); + setUploading(true); + + try { + const resFileList = newFileList.map(async (file, index) => { + const uploadedUrl = await new Promise((resolve, reject) => { + handleFileUpload( + fileList[index].originFileObj, + (result) => { + () => { + return { + ...newFileList[index], + progress: 100, + status: "done", + fileId: result.fileId, + url: result.url, + compressedUrl: result.compressedUrl, + } + } + // setFile((prev) => ({ + // ...prev!, + // progress: 100, + // status: "done", + // fileId: result.fileId, + // url: result.url, + // compressedUrl: result.compressedUrl, + // })); + setUrl(result.url); + setCompressedUrl(result.compressedUrl); + // 直接使用 result 中的最新值 + resolve(compressed ? result.compressedUrl : result.url); + }, + (error) => { + reject(error); + }, + newFileList[index]?.fileKey + ); + }); + }) + // await new Promise((resolve) => setTimeout(resolve,4999)); // 方法1:使用 await 暂停执行 + // 使用 resolved 的最新值调用 onChange + // 强制刷新 Avatar 组件 + // setAvatarKey((prev) => prev + 1); // 修改 key 强制重新挂载 + onChange?.(resFileList); + console.log(resFileList); + toast.success("图片上传成功"); + } catch (error) { + console.error("上传错误:", error); + toast.error("图片上传失败"); + // setFile((prev) => ({ ...prev!, status: "error" })); + } finally { + setUploading(false); + } + };uploadProgress + + // 处理预览 + const handlePreview = async (file) => { + if (!file.url && !file.preview) { + file.preview = await getBase64(file.originFileObj); + } + setPreviewImage(file.url || file.preview); + setPreviewVisible(true); + }; + + // 关闭预览模态框 + const handleCancel = () => setPreviewVisible(false); + + // 将文件转换为Base64格式(用于预览) + const getBase64 = (file) => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => resolve(reader.result); + reader.onerror = (error) => reject(error); + }); + }; + + return ( +
+ +

+

+

点击或拖拽文件到此区域上传

+

支持单个或批量上传

+
+ + 预览 + +
+ ); +}; + +export default MultiImageUpload; diff --git a/apps/web/src/components/common/uploader/TestUploader.tsx b/apps/web/src/components/common/uploader/TestUploader.tsx new file mode 100644 index 0000000..d4c196e --- /dev/null +++ b/apps/web/src/components/common/uploader/TestUploader.tsx @@ -0,0 +1,18 @@ +import AvatarUploader from "./AvatarUploader" + + + +interface TestUploaderProps { + value?: string[], + onChange?: (value: string[]) => void +} + +export function TestUploader({ + value, + onChange, +}: TestUploaderProps) { + + return <> + + +} \ No newline at end of file From 237d5a44d81af987b0b7204eba76533f5bb81bad Mon Sep 17 00:00:00 2001 From: ditiqi Date: Tue, 25 Feb 2025 16:43:42 +0800 Subject: [PATCH 3/3] addd --- .../src/app/main/home/components/CoursesSection.tsx | 12 +++++++----- packages/common/src/models/post.ts | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/web/src/app/main/home/components/CoursesSection.tsx b/apps/web/src/app/main/home/components/CoursesSection.tsx index 2117baa..24bb307 100755 --- a/apps/web/src/app/main/home/components/CoursesSection.tsx +++ b/apps/web/src/app/main/home/components/CoursesSection.tsx @@ -6,7 +6,12 @@ import { TeamOutlined, ArrowRightOutlined, } from "@ant-design/icons"; -import { CourseDto, TaxonomySlug, TermDto } from "@nice/common"; +import { + courseDetailSelect, + CourseDto, + TaxonomySlug, + TermDto, +} from "@nice/common"; import { api } from "@nice/client"; import CourseCard from "../../courses/components/CourseCard"; interface GetTaxonomyProps { @@ -50,10 +55,7 @@ function useFetchCoursesByCategory(category: string) { }, }, take: 8, - include: { - terms: true, - depts: true, - }, + select: courseDetailSelect, }); return { data, isLoading }; diff --git a/packages/common/src/models/post.ts b/packages/common/src/models/post.ts index 6994d4b..0d2bf07 100755 --- a/packages/common/src/models/post.ts +++ b/packages/common/src/models/post.ts @@ -77,7 +77,7 @@ export type Course = Post & { export type CourseDto = Course & { enrollments?: Enrollment[]; sections?: SectionDto[]; - terms: Term[]; + terms: TermDto[]; lectureCount?: number; depts:Department[] };