diff --git a/apps/server/src/auth/utils.ts b/apps/server/src/auth/utils.ts
index b1b2a88..ef8968d 100755
--- a/apps/server/src/auth/utils.ts
+++ b/apps/server/src/auth/utils.ts
@@ -155,7 +155,7 @@ export class UserProfileService {
where: { id },
select: {
id: true,
- avatar:true,
+ avatar: true,
deptId: true,
department: true,
domainId: true,
diff --git a/apps/web/src/app/admin/base-setting/page.tsx b/apps/web/src/app/admin/base-setting/page.tsx
index eb43d6b..c0aed70 100755
--- a/apps/web/src/app/admin/base-setting/page.tsx
+++ b/apps/web/src/app/admin/base-setting/page.tsx
@@ -3,6 +3,7 @@ import { useContext, useEffect, useState } from "react";
import { Button, Form, Input, message, theme } from "antd";
import { useAppConfig } from "@nice/client";
import { useAuth } from "@web/src/providers/auth-provider";
+import MultiImageUploader from "@web/src/components/common/uploader/MultiImageUploader";
import FixedHeader from "@web/src/components/layout/fix-header";
import { useForm } from "antd/es/form/Form";
@@ -26,6 +27,7 @@ export default function BaseSettingPage() {
const { user, hasSomePermissions } = useAuth();
const context = useContext(MainLayoutContext);
const pageWidth = context?.pageWidth;
+ // const [meta,setMeta ] = useState<>(baseSetting);
function handleFieldsChange() {
setIsFormChanged(true);
}
@@ -129,7 +131,7 @@ export default function BaseSettingPage() {
-
+
{/*
+ ghost>
清除行模型缓存
diff --git a/apps/web/src/app/main/courses/components/FilterSection.tsx b/apps/web/src/app/main/courses/components/FilterSection.tsx
index 5ffc49d..69fd828 100755
--- a/apps/web/src/app/main/courses/components/FilterSection.tsx
+++ b/apps/web/src/app/main/courses/components/FilterSection.tsx
@@ -85,27 +85,6 @@ export default function FilterSection({
})}
-
-
-
难度等级
- onLevelChange(e.target.value)}
- className="flex flex-col space-y-3">
- {levels.isLoading ? (
-
- ) : (
- <>
- 全部难度
- {levels.categories.map((level) => (
-
- {level}
-
- ))}
- >
- )}
-
-
);
}
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/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