From 92983baf527b76cba98a2a222237193bf2854f64 Mon Sep 17 00:00:00 2001 From: longdayi <13477510+longdayilongdayi@user.noreply.gitee.com> Date: Fri, 21 Feb 2025 16:10:14 +0800 Subject: [PATCH] 02211610 --- apps/web/.env.example | 4 +- apps/web/src/app/error.tsx | 40 ++++++++++++++++--- apps/web/src/app/main/home/page.tsx | 2 + apps/web/src/app/main/paths/page.tsx | 2 +- .../common/uploader/TusUploader.tsx | 26 ++++-------- .../form/CourseContentForm/LectureList.tsx | 6 --- apps/web/src/env.ts | 8 ++-- apps/web/src/hooks/useTusUpload.ts | 12 ++---- package.json | 3 +- packages/common/prisma/schema.prisma | 1 - 10 files changed, 56 insertions(+), 48 deletions(-) diff --git a/apps/web/.env.example b/apps/web/.env.example index 2d66081..4d30872 100755 --- a/apps/web/.env.example +++ b/apps/web/.env.example @@ -1,7 +1,5 @@ -VITE_APP_TUS_URL=http://localhost:8080 -VITE_APP_API_URL=http://localhost:3000 VITE_APP_SERVER_IP=192.168.252.239 VITE_APP_SERVER_PORT=3000 -VITE_APP_UPLOAD_PORT=80 +VITE_APP_FILE_PORT=80 VITE_APP_VERSION=0.3.0 VITE_APP_APP_NAME=MOOC diff --git a/apps/web/src/app/error.tsx b/apps/web/src/app/error.tsx index c32c11b..c51af76 100755 --- a/apps/web/src/app/error.tsx +++ b/apps/web/src/app/error.tsx @@ -1,11 +1,41 @@ +/** + * 错误处理模块 - 全局路由级错误展示组件 + * 功能: 捕获React Router路由层级错误并展示可视化错误信息 + * 特性: + * - 自动解析路由错误对象 + * - 自适应错误信息展示 + * - 响应式布局设计 + */ import { useRouteError } from "react-router-dom"; +/** + * 错误展示页面组件 + * @核心功能 呈现标准化错误界面,用于处理应用程序的路由层级错误 + * @设计模式 采用展示型组件模式,完全解耦业务逻辑实现纯UI展示 + * @使用示例 在React Router的RouterProvider中配置errorElement={} + */ export default function ErrorPage() { + // 使用React Router提供的Hook获取路由错误对象 + // 类型定义为any以兼容React Router不同版本的类型差异 const error: any = useRouteError(); - return
-
-
哦?页面似乎出错了...
-
{error?.statusText || error?.message}
+ + return ( + // 主容器: 基于Flex的垂直水平双居中布局 + // pt-64: 顶部留白实现视觉层次结构 +
+ {/* 内容区块: 采用纵向弹性布局控制内部元素间距 */} +
+ {/* 主标题: 强调性文字样式配置 */} +
+ 哦?页面似乎出错了... +
+ + {/* 错误详情: 动态渲染错误信息,实现优雅降级策略 */} + {/* 使用可选链操作符防止未定义错误,信息优先级: statusText > message */} +
+ {error?.statusText || error?.message} +
+
-
+ ) } \ No newline at end of file diff --git a/apps/web/src/app/main/home/page.tsx b/apps/web/src/app/main/home/page.tsx index 0225772..62f9d64 100644 --- a/apps/web/src/app/main/home/page.tsx +++ b/apps/web/src/app/main/home/page.tsx @@ -2,6 +2,7 @@ import HeroSection from './components/HeroSection'; import CategorySection from './components/CategorySection'; import CoursesSection from './components/CoursesSection'; import FeaturedTeachersSection from './components/FeaturedTeachersSection'; +import { TusUploader } from '@web/src/components/common/uploader/TusUploader'; const HomePage = () => { const mockCourses = [ { @@ -105,6 +106,7 @@ const HomePage = () => { return (
+ + return } diff --git a/apps/web/src/components/common/uploader/TusUploader.tsx b/apps/web/src/components/common/uploader/TusUploader.tsx index 27b120c..e9fa45b 100644 --- a/apps/web/src/components/common/uploader/TusUploader.tsx +++ b/apps/web/src/components/common/uploader/TusUploader.tsx @@ -5,12 +5,8 @@ import { DeleteOutlined, } from "@ant-design/icons"; import { Upload, Progress, Button } from "antd"; -import type { UploadFile } from "antd"; import { useTusUpload } from "@web/src/hooks/useTusUpload"; import toast from "react-hot-toast"; -import { getCompressedImageUrl } from "@nice/utils"; -import { api } from "@nice/client"; - export interface TusUploaderProps { value?: string[]; onChange?: (value: string[]) => void; @@ -30,16 +26,7 @@ export const TusUploader = ({ onChange, multiple = true, }: TusUploaderProps) => { - const { data: files } = api.resource.findMany.useQuery({ - where: { - fileId: { in: value }, - }, - select: { - id: true, - fileId: true, - title: true, - }, - }); + const { handleFileUpload, uploadProgress } = useTusUpload(); const [uploadingFiles, setUploadingFiles] = useState([]); const [completedFiles, setCompletedFiles] = useState( @@ -74,6 +61,7 @@ export const TusUploader = ({ const handleBeforeUpload = useCallback( (file: File) => { + const fileKey = `${file.name}-${Date.now()}`; setUploadingFiles((prev) => [ @@ -151,7 +139,7 @@ export const TusUploader = ({ name="files" multiple={multiple} showUploadList={false} - style={{ background: "transparent", borderStyle: "none" }} + beforeUpload={handleBeforeUpload}>

@@ -177,10 +165,10 @@ export const TusUploader = ({ file.status === "done" ? 100 : Math.round( - uploadProgress?.[ - file.fileKey! - ] || 0 - ) + uploadProgress?.[ + file.fileKey! + ] || 0 + ) } status={ file.status === "error" diff --git a/apps/web/src/components/models/course/editor/form/CourseContentForm/LectureList.tsx b/apps/web/src/components/models/course/editor/form/CourseContentForm/LectureList.tsx index 0ef99e7..8395c94 100644 --- a/apps/web/src/components/models/course/editor/form/CourseContentForm/LectureList.tsx +++ b/apps/web/src/components/models/course/editor/form/CourseContentForm/LectureList.tsx @@ -33,15 +33,9 @@ import { useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable"; -import { CSS } from "@dnd-kit/utilities"; -import QuillEditor from "@web/src/components/common/editor/quill/QuillEditor"; -import { TusUploader } from "@web/src/components/common/uploader/TusUploader"; import { Lecture, LectureType, PostType } from "@nice/common"; import { useCourseEditor } from "../../context/CourseEditorContext"; import { usePost } from "@nice/client"; -import toast from "react-hot-toast"; -import { CourseContentFormHeader } from "./CourseContentFormHeader"; -import { CourseSectionEmpty } from "./CourseSectionEmpty"; import { LectureData, SectionData } from "./interface"; import { SortableLecture } from "./SortableLecture"; diff --git a/apps/web/src/env.ts b/apps/web/src/env.ts index 30278b3..956a74b 100755 --- a/apps/web/src/env.ts +++ b/apps/web/src/env.ts @@ -2,7 +2,7 @@ export const env: { APP_NAME: string; SERVER_IP: string; VERSION: string; - UPLOAD_PORT: string; + FILE_PORT: string; SERVER_PORT: string; } = { APP_NAME: import.meta.env.PROD @@ -11,9 +11,9 @@ export const env: { SERVER_IP: import.meta.env.PROD ? (window as any).env.VITE_APP_SERVER_IP : import.meta.env.VITE_APP_SERVER_IP, - UPLOAD_PORT: import.meta.env.PROD - ? (window as any).env.VITE_APP_UPLOAD_PORT - : import.meta.env.VITE_APP_UPLOAD_PORT, + FILE_PORT: import.meta.env.PROD + ? (window as any).env.VITE_APP_FILE_PORT + : import.meta.env.VITE_APP_FILE_PORT, SERVER_PORT: import.meta.env.PROD ? (window as any).env.VITE_APP_SERVER_PORT : import.meta.env.VITE_APP_SERVER_PORT, diff --git a/apps/web/src/hooks/useTusUpload.ts b/apps/web/src/hooks/useTusUpload.ts index 8c855fa..0b99a1d 100644 --- a/apps/web/src/hooks/useTusUpload.ts +++ b/apps/web/src/hooks/useTusUpload.ts @@ -2,11 +2,6 @@ import { useState } from "react"; import * as tus from "tus-js-client"; import { env } from "../env"; import { getCompressedImageUrl } from "@nice/utils"; -// useTusUpload.ts -interface UploadProgress { - fileId: string; - progress: number; -} interface UploadResult { compressedUrl: string; @@ -35,9 +30,7 @@ export function useTusUpload() { if (uploadIndex === -1 || uploadIndex + 4 >= parts.length) { throw new Error("Invalid upload URL format"); } - console.log(env.UPLOAD_PORT); - const resUrl = `http://${env.SERVER_IP}:${env.UPLOAD_PORT}/uploads/${parts.slice(uploadIndex + 1, uploadIndex + 6).join("/")}`; - + const resUrl = `http://${env.SERVER_IP}:${env.FILE_PORT}/uploads/${parts.slice(uploadIndex + 1, uploadIndex + 6).join("/")}`; return resUrl; }; const handleFileUpload = async ( @@ -46,11 +39,13 @@ export function useTusUpload() { onError: (error: Error) => void, fileKey: string // 添加文件唯一标识 ) => { + // console.log() setIsUploading(true); setUploadProgress((prev) => ({ ...prev, [fileKey]: 0 })); setUploadError(null); try { + console.log(`http://${env.SERVER_IP}:${env.SERVER_PORT}/upload`) const upload = new tus.Upload(file, { endpoint: `http://${env.SERVER_IP}:${env.SERVER_PORT}/upload`, retryDelays: [0, 1000, 3000, 5000], @@ -97,6 +92,7 @@ export function useTusUpload() { onError: (error) => { setIsUploading(false); setUploadError(error.message); + console.log(error) onError(error); }, }); diff --git a/package.json b/package.json index 40e6ac1..8a85a11 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "dev": "pnpm run --parallel dev" + "dev": "pnpm run --parallel dev", + "db:clear": "pnpm --filter common run db:clear" }, "keywords": [], "author": "insiinc", diff --git a/packages/common/prisma/schema.prisma b/packages/common/prisma/schema.prisma index 061c73e..01bb99e 100644 --- a/packages/common/prisma/schema.prisma +++ b/packages/common/prisma/schema.prisma @@ -413,7 +413,6 @@ model Animal { personId String? person Person? @relation(fields: [personId], references: [id]) } - model Person { id String @id @default(cuid()) name String