From 29340b8bb293f5ef150b9957fe580fcf495e93b3 Mon Sep 17 00:00:00 2001
From: linfeng <2819853134@qq.com>
Date: Wed, 12 Mar 2025 08:23:33 +0800
Subject: [PATCH] lin
---
apps/web/src/app/main/course/detail/page.tsx | 7 -
.../components/couresPreviewTabmsg.tsx | 25 --
.../preview/components/courseCatalog.tsx | 11 -
.../components/coursePreviewAllmsg.tsx | 73 -----
apps/web/src/app/main/course/preview/page.tsx | 81 ------
apps/web/src/app/main/course/preview/type.ts | 8 -
.../courses/components/CoursesContainer.tsx | 25 --
apps/web/src/app/main/courses/page.tsx | 18 --
.../main/home/components/CategorySection.tsx | 107 -------
.../home/components/CategorySectionCard.tsx | 58 ----
.../main/home/components/CoursesSection.tsx | 112 --------
.../home/components/CoursesSectionTag.tsx | 24 --
.../components/FeaturedTeachersSection.tsx | 222 ---------------
.../app/main/home/components/HeroSection.tsx | 164 -----------
.../app/main/home/components/LookForMore.tsx | 27 --
apps/web/src/app/main/home/page.tsx | 41 +--
.../main/layout/BasePost/BasePostLayout.tsx | 29 --
.../main/layout/BasePost/FilterSection.tsx | 46 ----
.../main/layout/BasePost/SearchModeRadio.tsx | 25 --
apps/web/src/app/main/layout/MainFooter.tsx | 76 -----
apps/web/src/app/main/layout/MainHeader.tsx | 149 +++-------
apps/web/src/app/main/layout/MainLayout.tsx | 28 +-
apps/web/src/app/main/layout/MainProvider.tsx | 109 --------
.../src/app/main/layout/NavigationMenu.tsx | 92 +++----
.../main/layout/UserMenu/UserEditModal.tsx | 27 --
.../src/app/main/layout/UserMenu/UserForm.tsx | 164 -----------
.../src/app/main/layout/UserMenu/UserMenu.tsx | 246 -----------------
.../web/src/app/main/layout/UserMenu/types.ts | 6 -
.../components/MyDutyPathContainer.tsx | 26 --
apps/web/src/app/main/my-duty-path/page.tsx | 17 --
.../components/MyDutyListContainer.tsx | 27 --
apps/web/src/app/main/my-duty/page.tsx | 16 --
.../components/MyLearningListContainer.tsx | 31 ---
apps/web/src/app/main/my-learning/page.tsx | 17 --
.../components/MyPathListContainer.tsx | 33 ---
apps/web/src/app/main/my-path/page.tsx | 17 --
.../src/app/main/path/components/DeptInfo.tsx | 42 ---
.../path/components/PathListContainer.tsx | 25 --
.../src/app/main/path/components/TermInfo.tsx | 47 ----
apps/web/src/app/main/path/editor/page.tsx | 12 -
apps/web/src/app/main/path/page.tsx | 20 --
.../search/components/SearchContainer.tsx | 33 ---
apps/web/src/app/main/search/page.tsx | 20 --
apps/web/src/app/main/self/courses/page.tsx | 7 -
apps/web/src/app/main/self/profiles/page.tsx | 3 -
apps/web/src/app/main/staffpage/page.tsx | 260 ++++++++++++++++++
apps/web/src/routes/index.tsx | 115 +-------
47 files changed, 362 insertions(+), 2406 deletions(-)
delete mode 100755 apps/web/src/app/main/course/detail/page.tsx
delete mode 100755 apps/web/src/app/main/course/preview/components/couresPreviewTabmsg.tsx
delete mode 100755 apps/web/src/app/main/course/preview/components/courseCatalog.tsx
delete mode 100755 apps/web/src/app/main/course/preview/components/coursePreviewAllmsg.tsx
delete mode 100755 apps/web/src/app/main/course/preview/page.tsx
delete mode 100755 apps/web/src/app/main/course/preview/type.ts
delete mode 100755 apps/web/src/app/main/courses/components/CoursesContainer.tsx
delete mode 100755 apps/web/src/app/main/courses/page.tsx
delete mode 100755 apps/web/src/app/main/home/components/CategorySection.tsx
delete mode 100755 apps/web/src/app/main/home/components/CategorySectionCard.tsx
delete mode 100755 apps/web/src/app/main/home/components/CoursesSection.tsx
delete mode 100755 apps/web/src/app/main/home/components/CoursesSectionTag.tsx
delete mode 100755 apps/web/src/app/main/home/components/FeaturedTeachersSection.tsx
delete mode 100755 apps/web/src/app/main/home/components/HeroSection.tsx
delete mode 100755 apps/web/src/app/main/home/components/LookForMore.tsx
delete mode 100755 apps/web/src/app/main/layout/BasePost/BasePostLayout.tsx
delete mode 100755 apps/web/src/app/main/layout/BasePost/FilterSection.tsx
delete mode 100755 apps/web/src/app/main/layout/BasePost/SearchModeRadio.tsx
delete mode 100755 apps/web/src/app/main/layout/MainFooter.tsx
mode change 100755 => 100644 apps/web/src/app/main/layout/MainHeader.tsx
mode change 100755 => 100644 apps/web/src/app/main/layout/MainLayout.tsx
delete mode 100755 apps/web/src/app/main/layout/MainProvider.tsx
mode change 100755 => 100644 apps/web/src/app/main/layout/NavigationMenu.tsx
delete mode 100755 apps/web/src/app/main/layout/UserMenu/UserEditModal.tsx
delete mode 100755 apps/web/src/app/main/layout/UserMenu/UserForm.tsx
delete mode 100755 apps/web/src/app/main/layout/UserMenu/UserMenu.tsx
delete mode 100755 apps/web/src/app/main/layout/UserMenu/types.ts
delete mode 100755 apps/web/src/app/main/my-duty-path/components/MyDutyPathContainer.tsx
delete mode 100755 apps/web/src/app/main/my-duty-path/page.tsx
delete mode 100755 apps/web/src/app/main/my-duty/components/MyDutyListContainer.tsx
delete mode 100755 apps/web/src/app/main/my-duty/page.tsx
delete mode 100755 apps/web/src/app/main/my-learning/components/MyLearningListContainer.tsx
delete mode 100755 apps/web/src/app/main/my-learning/page.tsx
delete mode 100755 apps/web/src/app/main/my-path/components/MyPathListContainer.tsx
delete mode 100755 apps/web/src/app/main/my-path/page.tsx
delete mode 100755 apps/web/src/app/main/path/components/DeptInfo.tsx
delete mode 100755 apps/web/src/app/main/path/components/PathListContainer.tsx
delete mode 100755 apps/web/src/app/main/path/components/TermInfo.tsx
delete mode 100755 apps/web/src/app/main/path/editor/page.tsx
delete mode 100755 apps/web/src/app/main/path/page.tsx
delete mode 100755 apps/web/src/app/main/search/components/SearchContainer.tsx
delete mode 100755 apps/web/src/app/main/search/page.tsx
delete mode 100755 apps/web/src/app/main/self/courses/page.tsx
delete mode 100755 apps/web/src/app/main/self/profiles/page.tsx
create mode 100644 apps/web/src/app/main/staffpage/page.tsx
diff --git a/apps/web/src/app/main/course/detail/page.tsx b/apps/web/src/app/main/course/detail/page.tsx
deleted file mode 100755
index 82dd7ae..0000000
--- a/apps/web/src/app/main/course/detail/page.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import CourseDetail from "@web/src/components/models/course/detail/CourseDetail";
-import { useParams } from "react-router-dom";
-
-export function CourseDetailPage() {
- const { id, lectureId } = useParams();
- return ;
-}
diff --git a/apps/web/src/app/main/course/preview/components/couresPreviewTabmsg.tsx b/apps/web/src/app/main/course/preview/components/couresPreviewTabmsg.tsx
deleted file mode 100755
index 8f32fce..0000000
--- a/apps/web/src/app/main/course/preview/components/couresPreviewTabmsg.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Checkbox, List } from 'antd';
-import React from 'react';
-
-export function CoursePreviewTabmsg({data}){
-
-
- const renderItem = (item) => (
-
-
-
- );
-
- return(
-
-
-
- )
-}
\ No newline at end of file
diff --git a/apps/web/src/app/main/course/preview/components/courseCatalog.tsx b/apps/web/src/app/main/course/preview/components/courseCatalog.tsx
deleted file mode 100755
index b13e87d..0000000
--- a/apps/web/src/app/main/course/preview/components/courseCatalog.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import type { MenuProps } from 'antd';
-import { Menu } from 'antd';
-
-type MenuItem = Required['items'][number];
-
-export function CourseCatalog(){
- return (
- <>
- >
- )
-}
\ No newline at end of file
diff --git a/apps/web/src/app/main/course/preview/components/coursePreviewAllmsg.tsx b/apps/web/src/app/main/course/preview/components/coursePreviewAllmsg.tsx
deleted file mode 100755
index 73ed1f9..0000000
--- a/apps/web/src/app/main/course/preview/components/coursePreviewAllmsg.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { useEffect } from "react";
-import { CoursePreviewMsg } from "@web/src/app/main/course/preview/type.ts";
-import { Button, Tabs, Image, Skeleton } from "antd";
-import type { TabsProps } from "antd";
-import { PlayCircleOutlined } from "@ant-design/icons";
-export function CoursePreviewAllmsg({
- previewMsg,
- items,
- isLoading,
-}: {
- previewMsg?: CoursePreviewMsg;
- items: TabsProps["items"];
- isLoading: boolean;
-}) {
- useEffect(() => {
- console.log(previewMsg);
- });
- const TapOnChange = (key: string) => {
- console.log(key);
- };
- return (
-
-
-
-
- {isLoading ? (
-
- ) : (
- <>
-
- {previewMsg.Title}
-
-
- {previewMsg.SubTitle}
-
-
- {previewMsg.Description}
-
- >
- )}
-
-
-
-
-
-
-
-
- );
-}
diff --git a/apps/web/src/app/main/course/preview/page.tsx b/apps/web/src/app/main/course/preview/page.tsx
deleted file mode 100755
index 367c21a..0000000
--- a/apps/web/src/app/main/course/preview/page.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import { Skeleton, type TabsProps } from 'antd';
-import { CoursePreviewAllmsg } from "./components/coursePreviewAllmsg";
-import { CoursePreviewTabmsg } from "./components/couresPreviewTabmsg";
-import { CoursePreviewMsg } from "./type";
-import { api } from '@nice/client'
-import { useNavigate, useParams } from 'react-router-dom';
-import { useEffect, useState } from 'react';
-import { courseDetailSelect, CourseDto } from '@nice/common';
-
-export function CoursePreview(){
- const { id } = useParams()
- const { data:course,isLoading:courseIsLoading}:{data:CourseDto,isLoading:boolean}= api.post.findFirst.useQuery({
- where:{
- id
- },
- select:courseDetailSelect
- })
- // course.sections[0].lectures[0]
- // `/course/${course.id}/detail/${Lecture.id}`
- useEffect(() => {
- if(!courseIsLoading){
- setPreviewMsg({
- videoPreview: course?.meta?.thumbnail,
- Title: course?.title,
- SubTitle:course?.subTitle,
- Description:course?.content,
- ToCourseUrl:`/course/${id}`,
- isLoading:courseIsLoading
- })
- }
-
- },[courseIsLoading])
- const [previewMsg,setPreviewMsg] = useState({
- videoPreview: '',
- Title: '',
- SubTitle:'',
- Description:'',
- ToCourseUrl:'',
- isLoading:courseIsLoading
- })
- const tapData = [
- {
- title: '掌握R语言的基本概念语法',
- description: '学生将学习R语言和RStudio的基本知识',
- },
- {
- title: '掌握R语言的基本概念语法',
- description: '学生将学习R语言的变量、数据类型、循环和条件语句等',
- },
- {
- title: '掌握R语言的数据导入管理',
- description: '学生将学会如何将数据导入R环境,并且使用各种类型的数据',
- },
- {
- title: '掌握R语言的基本数据清洗',
- description: '学生将学会使用R语言进行数据清洗、整理和管理',
- },
- {
- title: '掌握R语言的基本数据统计',
- description: '学生将学会使用R语言进行基本的数据统计',
- },
- {
- title: '掌握R语言的基本绘图功能',
- description: '学生将学会使用R语言基本的绘图功能和ggplot2的应用',
- },
- ];
- const isLoading = false
- const items: TabsProps['items'] = [
- {
- key: '1',
- label: '课程学习目标',
- children: isLoading ? : ,
- }
- ];
-
- return(
-
-
-
- )
-}
\ No newline at end of file
diff --git a/apps/web/src/app/main/course/preview/type.ts b/apps/web/src/app/main/course/preview/type.ts
deleted file mode 100755
index fe3a2fd..0000000
--- a/apps/web/src/app/main/course/preview/type.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface CoursePreviewMsg {
- videoPreview: string;
- Title: string;
- SubTitle: string;
- Description: string;
- ToCourseUrl: string;
- isLoading: boolean;
-}
diff --git a/apps/web/src/app/main/courses/components/CoursesContainer.tsx b/apps/web/src/app/main/courses/components/CoursesContainer.tsx
deleted file mode 100755
index 72b9499..0000000
--- a/apps/web/src/app/main/courses/components/CoursesContainer.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useMainContext } from "../../layout/MainProvider";
-import { PostType, Prisma } from "@nice/common";
-import PostList from "@web/src/components/models/course/list/PostList";
-import CourseCard from "@web/src/components/models/post/SubPost/CourseCard";
-
-export function CoursesContainer() {
- const { searchCondition, termsCondition } = useMainContext();
- return (
- <>
- }
- params={{
- pageSize: 12,
- where: {
- type: PostType.COURSE,
- ...termsCondition,
- ...searchCondition,
- },
- }}
- cols={4}>
- >
- );
-}
-
-export default CoursesContainer;
diff --git a/apps/web/src/app/main/courses/page.tsx b/apps/web/src/app/main/courses/page.tsx
deleted file mode 100755
index 79eda89..0000000
--- a/apps/web/src/app/main/courses/page.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import BasePostLayout from "../layout/BasePost/BasePostLayout";
-import CoursesContainer from "./components/CoursesContainer";
-import { useEffect } from "react";
-import { useMainContext } from "../layout/MainProvider";
-import { PostType } from "@nice/common";
-export default function CoursesPage() {
- const { setSearchMode } = useMainContext();
- useEffect(() => {
- setSearchMode(PostType.COURSE);
- }, [setSearchMode]);
- return (
- <>
-
-
-
- >
- );
-}
diff --git a/apps/web/src/app/main/home/components/CategorySection.tsx b/apps/web/src/app/main/home/components/CategorySection.tsx
deleted file mode 100755
index 7bddcf2..0000000
--- a/apps/web/src/app/main/home/components/CategorySection.tsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import React, { useState, useCallback, useEffect, useMemo } from "react";
-import { Typography, Skeleton } from "antd";
-import { stringToColor, TaxonomySlug, TermDto } from "@nice/common";
-import { api, useTrainSituation } from "@nice/client";
-import LookForMore from "./LookForMore";
-import CategorySectionCard from "./CategorySectionCard";
-import { useNavigate } from "react-router-dom";
-import { useMainContext } from "../../layout/MainProvider";
-import { useAuth } from "@web/src/providers/auth-provider";
-
-const { Title, Text } = Typography;
-const CategorySection = () => {
- const [hoveredIndex, setHoveredIndex] = useState(null);
- const { selectedTerms, setSelectedTerms } = useMainContext();
- const {
- data: courseCategoriesData,
- isLoading,
- }: { data: TermDto[]; isLoading: boolean } = api.term.findMany.useQuery({
- where: {
- taxonomy: {
- slug: TaxonomySlug.CATEGORY,
- },
- parentId: null,
- },
- take: 8,
- });
- const navigate = useNavigate();
-
- const handleMouseEnter = useCallback((index: number) => {
- setHoveredIndex(index);
- }, []);
-
- const handleMouseLeave = useCallback(() => {
- setHoveredIndex(null);
- }, []);
-
- const handleMouseClick = useCallback((categoryId: string) => {
- setSelectedTerms({
- ...selectedTerms,
- [TaxonomySlug.CATEGORY]: [categoryId],
- });
- navigate("/courses");
- window.scrollTo({ top: 0, behavior: "smooth" });
- }, []);
-
-
- const {user} = useAuth()
- const {create} = useTrainSituation()
- useEffect(() => {
- if (user?.id) {
- create.mutate({
- data: {
- //staffId: user.id, // 确保类型匹配
- mustTrainTime: "1",
- alreadyTrainTime: "1",
- //trainContentId: "cm83w52dr00ff3jc8ep4uf4a4",
- staff: { connect: { id: user.id } },
- trainContent: { connect: { id: "cm847lcc805ne123v81l5h13e" } }
- }
- });
- console.log("create score time")
- }
- }, []);
-
- return (
-
-
-
-
- 探索课程分类
-
-
- 选择你感兴趣的方向,开启学习之旅
-
-
-
- {isLoading ? (
-
- ) : (
- courseCategoriesData?.filter(c=>!c.deletedAt)?.map((category, index) => {
- const categoryColor = stringToColor(category.name);
- const isHovered = hoveredIndex === index;
-
- return (
-
- );
- })
- )}
-
-
-
-
- );
-};
-
-export default CategorySection;
diff --git a/apps/web/src/app/main/home/components/CategorySectionCard.tsx b/apps/web/src/app/main/home/components/CategorySectionCard.tsx
deleted file mode 100755
index e3e1273..0000000
--- a/apps/web/src/app/main/home/components/CategorySectionCard.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import { useNavigate } from "react-router-dom";
-import { Typography } from "antd";
-export default function CategorySectionCard({handleMouseClick, index,handleMouseEnter,handleMouseLeave,category,categoryColor,isHovered,}) {
- const navigate = useNavigate()
- const { Title, Text } = Typography;
- return (
- handleMouseEnter(index)}
- onMouseLeave={handleMouseLeave}
- role="button"
- tabIndex={0}
- aria-label={`查看${category.name}课程类别`}
- onClick={()=>{
- handleMouseClick(category.id)
- }}
- >
-
-
-
-
-
-
-
- {category.name}
-
-
-
- 了解更多
-
- →
-
-
-
-
- )
-}
\ No newline at end of file
diff --git a/apps/web/src/app/main/home/components/CoursesSection.tsx b/apps/web/src/app/main/home/components/CoursesSection.tsx
deleted file mode 100755
index bd7e18d..0000000
--- a/apps/web/src/app/main/home/components/CoursesSection.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import React, { useState, useMemo, ReactNode } from "react";
-import { Typography, Skeleton } from "antd";
-import { TaxonomySlug, TermDto } from "@nice/common";
-import { api } from "@nice/client";
-import { CoursesSectionTag } from "./CoursesSectionTag";
-import LookForMore from "./LookForMore";
-import PostList from "@web/src/components/models/course/list/PostList";
-interface GetTaxonomyProps {
- categories: string[];
- isLoading: boolean;
-}
-function useGetTaxonomy({ type }): GetTaxonomyProps {
- const { data, isLoading }: { data: TermDto[]; isLoading: boolean } =
- api.term.findMany.useQuery({
- where: {
- taxonomy: {
- slug: type,
- },
- parentId: null,
- },
- take: 11, // 只取前10个
- });
- const categories = useMemo(() => {
- const allCategories = isLoading
- ? []
- : data?.filter(c=>!c.deletedAt)?.map((course) => course.name);
- return [...Array.from(new Set(allCategories))];
- }, [data]);
- return { categories, isLoading };
-}
-const { Title, Text } = Typography;
-interface CoursesSectionProps {
- title: string;
- description: string;
- initialVisibleCoursesCount?: number;
- postType:string;
- render?:(post)=>ReactNode;
- to:string
-}
-const CoursesSection: React.FC = ({
- title,
- description,
- initialVisibleCoursesCount = 8,
- postType,
- render,
- to
-}) => {
- const [selectedCategory, setSelectedCategory] = useState("全部");
- const gateGory: GetTaxonomyProps = useGetTaxonomy({
- type: TaxonomySlug.CATEGORY,
- });
- return (
-
-
-
-
-
- {title}
-
-
- {description}
-
-
-
-
- {gateGory.isLoading ? (
-
- ) : (
- <>
- {["全部", ...gateGory.categories].map(
- (category, idx) => (
-
- )
- )}
- >
- )}
-
-
render(post)}
- params={{
- page: 1,
- pageSize: initialVisibleCoursesCount,
- where: {
- terms: !(selectedCategory === "全部")
- ? {
- some: {
- name: selectedCategory,
- },
- }
- : {},
- type: postType
- },
- }}
- showPagination={false}
- cols={4}>
-
-
-
- );
-};
-export default CoursesSection;
diff --git a/apps/web/src/app/main/home/components/CoursesSectionTag.tsx b/apps/web/src/app/main/home/components/CoursesSectionTag.tsx
deleted file mode 100755
index c03d718..0000000
--- a/apps/web/src/app/main/home/components/CoursesSectionTag.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Tag } from "antd";
-
-export function CoursesSectionTag({category, selectedCategory, setSelectedCategory}) {
- return (
- <>
- {
- setSelectedCategory(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"
- : "bg-white text-gray-600 hover:bg-gray-100"
- }`}>
- {category}
-
- >
- )
-}
diff --git a/apps/web/src/app/main/home/components/FeaturedTeachersSection.tsx b/apps/web/src/app/main/home/components/FeaturedTeachersSection.tsx
deleted file mode 100755
index c880b07..0000000
--- a/apps/web/src/app/main/home/components/FeaturedTeachersSection.tsx
+++ /dev/null
@@ -1,222 +0,0 @@
-import React, { useRef } from 'react';
-import { Typography, Tag, Carousel } from 'antd';
-import { StarFilled, UserOutlined, ReadOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
-
-const { Title, Text } = Typography;
-
-interface Teacher {
- name: string;
- title: string;
- avatar: string;
- courses: number;
- students: number;
- rating: number;
- description: string;
-}
-
-const featuredTeachers: Teacher[] = [
- {
- name: '张教授',
- title: '资深前端开发专家',
- avatar: '/images/teacher1.jpg',
- courses: 12,
- students: 25000,
- rating: 4.9,
- description: '前 BAT 高级工程师,10年+开发经验'
- },
- {
- name: '李教授',
- title: '算法与数据结构专家',
- avatar: '/images/teacher2.jpg',
- courses: 8,
- students: 18000,
- rating: 4.8,
- description: '计算机博士,专注算法教育8年'
- },
- {
- name: '王博士',
- title: '人工智能研究员',
- avatar: '/images/teacher3.jpg',
- courses: 15,
- students: 30000,
- rating: 4.95,
- description: '人工智能领域专家,曾主导多个大型AI项目'
- },
- {
- name: '陈教授',
- title: '云计算架构师',
- avatar: '/images/teacher4.jpg',
- courses: 10,
- students: 22000,
- rating: 4.85,
- description: '知名云服务提供商技术总监,丰富的实战经验'
- },
- {
- name: '郑老师',
- title: '移动开发专家',
- avatar: '/images/teacher5.jpg',
- courses: 14,
- students: 28000,
- rating: 4.88,
- description: '资深移动端开发者,著名互联网公司技术专家'
- }
-];
-
-const generateGradientColors = (name: string) => {
- // 优化的哈希函数
- const hash = name.split('').reduce((acc, char, index) => {
- return char.charCodeAt(0) + ((acc << 5) - acc) + index;
- }, 0);
-
- // 定义蓝色色相范围(210-240)
- const blueHueStart = 210;
- const blueHueRange = 30;
-
- // 基础蓝色色相 - 将哈希值映射到蓝色范围内
- const baseHue = blueHueStart + Math.abs(hash % blueHueRange);
-
- // 生成第二个蓝色色相,保持在蓝色范围内
- let secondHue = baseHue + 15; // 在基础色相的基础上略微偏移
- if (secondHue > blueHueStart + blueHueRange) {
- secondHue -= blueHueRange;
- }
-
- // 基于输入字符串的特征调整饱和度和亮度
- const nameLength = name.length;
- const saturation = Math.max(65, Math.min(85, 75 + (nameLength % 10))); // 65-85%范围
- const lightness = Math.max(45, Math.min(65, 55 + (hash % 10))); // 45-65%范围
-
- // 为第二个颜色稍微调整饱和度和亮度,创造层次感
- const saturation2 = Math.max(60, saturation - 5);
- const lightness2 = Math.min(70, lightness + 5);
-
- return {
- from: `hsl(${Math.round(baseHue)}, ${Math.round(saturation)}%, ${Math.round(lightness)}%)`,
- to: `hsl(${Math.round(secondHue)}, ${Math.round(saturation2)}%, ${Math.round(lightness2)}%)`
- };
-};
-
-const FeaturedTeachersSection: React.FC = () => {
- const carouselRef = useRef(null);
-
- const settings = {
- dots: true,
- infinite: true,
- speed: 500,
- slidesToShow: 4,
- slidesToScroll: 1,
- autoplay: true,
- autoplaySpeed: 5000,
- responsive: [
- {
- breakpoint: 1024,
- settings: {
- slidesToShow: 2,
- slidesToScroll: 1
- }
- },
- {
- breakpoint: 640,
- settings: {
- slidesToShow: 1,
- slidesToScroll: 1
- }
- }
- ]
- };
-
- const TeacherCard = ({ teacher }: { teacher: Teacher }) => {
- const gradientColors = generateGradientColors(teacher.name);
- return (
-
-
-
-

-
-
-
-
- {teacher.name}
-
-
- {teacher.title}
-
-
-
-
- {teacher.description}
-
-
-
-
-
-
- {teacher.courses}
-
-
课程
-
-
-
-
- {(teacher.students / 1000).toFixed(1)}k
-
-
学员
-
-
-
-
- {teacher.rating}
-
-
评分
-
-
-
-
-
- );
- };
-
- return (
-
-
-
-
- 优秀讲师
-
-
- 业界专家实战分享,传授独家经验
-
-
-
-
-
- {featuredTeachers.map((teacher, index) => (
-
- ))}
-
-
-
-
-
-
-
- );
-};
-
-export default FeaturedTeachersSection;
diff --git a/apps/web/src/app/main/home/components/HeroSection.tsx b/apps/web/src/app/main/home/components/HeroSection.tsx
deleted file mode 100755
index 07b775e..0000000
--- a/apps/web/src/app/main/home/components/HeroSection.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-import React, {
- useRef,
- useCallback,
- useEffect,
- useMemo,
- useState,
-} from "react";
-import { Carousel, Typography } from "antd";
-import {
- TeamOutlined,
- BookOutlined,
- StarOutlined,
- LeftOutlined,
- RightOutlined,
- EyeOutlined,
-} from "@ant-design/icons";
-import type { CarouselRef } from "antd/es/carousel";
-import { api, useAppConfig } from "@nice/client";
-import { useNavigate } from "react-router-dom";
-
-interface PlatformStat {
- icon: React.ReactNode;
- value: number;
- label: string;
-}
-
-const HeroSection = () => {
- const carouselRef = useRef(null);
- const { statistics, slides, slideLinks = [] } = useAppConfig();
- const [countStatistics, setCountStatistics] = useState(4);
- const navigator = useNavigate()
- const platformStats: PlatformStat[] = useMemo(() => {
- return [
- {
- icon: ,
- value: statistics.staffs,
- label: "注册学员",
- },
- {
- icon: ,
- value: statistics.courses,
- label: "精品课程",
- },
- {
- icon: ,
- value: statistics.lectures,
- label: "课程章节",
- },
- {
- icon: ,
- value: statistics.reads,
- label: "播放次数",
- },
- ];
- }, [statistics]);
- const handlePrev = useCallback(() => {
- carouselRef.current?.prev();
- }, []);
-
- const handleNext = useCallback(() => {
- carouselRef.current?.next();
- }, []);
-
- const countNonZeroValues = (statistics: Record): number => {
- return Object.values(statistics).filter((value) => value !== 0).length;
- };
-
- useEffect(() => {
- const count = countNonZeroValues(statistics);
- console.log(count);
- setCountStatistics(count);
- }, [statistics]);
-
-
-
-
-
-
-
- return (
-
-
-
- {Array.isArray(slides) ? (
- slides.map((item, index) => (
- {
- if(slideLinks?.[index])window.open(slideLinks?.[index],"_blank")
- }}
- >
-
- {/*
*/}
-
-
- {/* Content Container */}
-
-
- ))
- ) : (
-
- )}
-
-
- {/* Navigation Buttons */}
-
-
-
-
- {/* Stats Container */}
- {countStatistics > 1 && (
-
-
- {platformStats.map((stat, index) => {
- return stat.value ? (
-
-
- {stat.icon}
-
-
- {stat.value}
-
-
- {stat.label}
-
-
- ) : null;
- })}
-
-
- )}
-
- );
-};
-
-export default HeroSection;
diff --git a/apps/web/src/app/main/home/components/LookForMore.tsx b/apps/web/src/app/main/home/components/LookForMore.tsx
deleted file mode 100755
index 2bd74cc..0000000
--- a/apps/web/src/app/main/home/components/LookForMore.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { ArrowRightOutlined } from "@ant-design/icons";
-import { Button } from "antd";
-import { useNavigate } from "react-router-dom";
-
-export default function LookForMore({to}:{to:string}) {
- const navigate = useNavigate();
- return (
- <>
-
-
-
-
-
-
- >
- )
-
-}
diff --git a/apps/web/src/app/main/home/page.tsx b/apps/web/src/app/main/home/page.tsx
index 4482872..729e69d 100755
--- a/apps/web/src/app/main/home/page.tsx
+++ b/apps/web/src/app/main/home/page.tsx
@@ -1,34 +1,9 @@
-import HeroSection from "./components/HeroSection";
-import CategorySection from "./components/CategorySection";
-import CoursesSection from "./components/CoursesSection";
-import { PostType } from "@nice/common";
-import PathCard from "@web/src/components/models/post/SubPost/PathCard";
-import CourseCard from "@web/src/components/models/post/SubPost/CourseCard";
+import React from "react"
-
-const HomePage = () => {
-
- return (
-
-
-
}
- to={"path"}
- />
- }
- to={"/courses"}
- />
-
-
-
- );
-};
-
-export default HomePage;
+export default function HomePage() {
+ return (
+
+ 首页
+
+ )
+}
\ No newline at end of file
diff --git a/apps/web/src/app/main/layout/BasePost/BasePostLayout.tsx b/apps/web/src/app/main/layout/BasePost/BasePostLayout.tsx
deleted file mode 100755
index 09c7852..0000000
--- a/apps/web/src/app/main/layout/BasePost/BasePostLayout.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { ReactNode, useEffect } from "react";
-import FilterSection from "./FilterSection";
-import { useMainContext } from "../MainProvider";
-
-export function BasePostLayout({
- children,
- showSearchMode = false,
-}: {
- children: ReactNode;
- showSearchMode?: boolean;
-}) {
- const { setShowSearchMode } = useMainContext();
- useEffect(() => {
- setShowSearchMode(showSearchMode);
- }, [showSearchMode]);
- return (
- <>
-
- >
- );
-}
-export default BasePostLayout;
diff --git a/apps/web/src/app/main/layout/BasePost/FilterSection.tsx b/apps/web/src/app/main/layout/BasePost/FilterSection.tsx
deleted file mode 100755
index 084878c..0000000
--- a/apps/web/src/app/main/layout/BasePost/FilterSection.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { Divider } from "antd";
-import { api } from "@nice/client";
-import { useMainContext } from "../MainProvider";
-import TermParentSelector from "@web/src/components/models/term/term-parent-selector";
-import SearchModeRadio from "./SearchModeRadio";
-export default function FilterSection() {
- const { data: taxonomies } = api.taxonomy.getAll.useQuery({});
- const { selectedTerms, setSelectedTerms, showSearchMode } =
- useMainContext();
- const handleTermChange = (slug: string, selected: string[]) => {
- setSelectedTerms({
- ...selectedTerms,
- [slug]: selected, // 更新对应 slug 的选择
- });
- };
- return (
-
- {showSearchMode &&
}
- {taxonomies?.map((tax, index) => {
- const items = Object.entries(selectedTerms).find(
- ([key, items]) => key === tax.slug
- )?.[1];
- return (
-
-
- {tax?.name}
- {/* {JSON.stringify(items)} */}
-
-
- handleTermChange(
- tax?.slug,
- selected as string[]
- )
- }
- taxonomyId={tax?.id}>
-
-
- );
- })}
-
- );
-}
diff --git a/apps/web/src/app/main/layout/BasePost/SearchModeRadio.tsx b/apps/web/src/app/main/layout/BasePost/SearchModeRadio.tsx
deleted file mode 100755
index 507e94f..0000000
--- a/apps/web/src/app/main/layout/BasePost/SearchModeRadio.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { useMainContext } from "../MainProvider";
-import { Radio, Space, Typography } from "antd";
-import { PostType } from "@nice/common"; // Assuming PostType is defined in this path
-
-export default function SearchModeRadio() {
- const { searchMode, setSearchMode } = useMainContext();
-
- const handleModeChange = (e) => {
- setSearchMode(e.target.value);
- };
-
- return (
-
- 只搜索
-
- 视频课程
- 思维导图
- 所有资源
-
-
- );
-}
diff --git a/apps/web/src/app/main/layout/MainFooter.tsx b/apps/web/src/app/main/layout/MainFooter.tsx
deleted file mode 100755
index eb4ef75..0000000
--- a/apps/web/src/app/main/layout/MainFooter.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import {
- CloudOutlined,
- FileSearchOutlined,
- HomeOutlined,
- MailOutlined,
- PhoneOutlined,
-} from "@ant-design/icons";
-
-export function MainFooter() {
- return (
-
- );
-}
diff --git a/apps/web/src/app/main/layout/MainHeader.tsx b/apps/web/src/app/main/layout/MainHeader.tsx
old mode 100755
new mode 100644
index 91b1771..fee3ad5
--- a/apps/web/src/app/main/layout/MainHeader.tsx
+++ b/apps/web/src/app/main/layout/MainHeader.tsx
@@ -1,107 +1,46 @@
-import { Input, Button } from "antd";
-import { PlusOutlined, SearchOutlined, UserOutlined } from "@ant-design/icons";
-import { useAuth } from "@web/src/providers/auth-provider";
-import { useNavigate, useParams } from "react-router-dom";
-import { UserMenu } from "./UserMenu/UserMenu";
-import { NavigationMenu } from "./NavigationMenu";
-import { useMainContext } from "./MainProvider";
-import { env } from "@web/src/env";
-export function MainHeader() {
- const { isAuthenticated, user } = useAuth();
- const { id } = useParams();
- const navigate = useNavigate();
- const { searchValue, setSearchValue } = useMainContext();
+import { Layout, Menu, Avatar, Button } from 'antd';
+import { UserOutlined, SettingOutlined } from '@ant-design/icons';
+import { useNavigate, Outlet, useLocation } from 'react-router-dom';
+import NavigationMenu from './NavigationMenu';
- return (
-
- {/* 左侧区域 - 设置为不收缩 */}
-
-

-
navigate("/")}
- className="text-2xl font-bold bg-gradient-to-r from-primary-600 via-primary-500 to-primary-400 bg-clip-text text-transparent hover:scale-105 transition-transform cursor-pointer whitespace-nowrap">
- {env.APP_NAME}
-
-
-
+const { Sider, Content } = Layout;
- {/* 右侧区域 - 可以灵活收缩 */}
-
-
-
- }
- placeholder="搜索课程"
- className="w-full md:w-96 rounded-full"
- value={searchValue}
- onClick={(e) => {
- if (
- !window.location.pathname.startsWith("/search")
- ) {
- navigate(`/search`);
- window.scrollTo({
- top: 0,
- behavior: "smooth",
- });
- }
- }}
- onChange={(e) => setSearchValue(e.target.value)}
- onPressEnter={(e) => {
- if (
- !window.location.pathname.startsWith("/search")
- ) {
- navigate(`/search`);
- window.scrollTo({
- top: 0,
- behavior: "smooth",
- });
- }
- }}
- />
- {isAuthenticated && (
- <>
-
- >
- )}
- {isAuthenticated && (
-
- )}
- {isAuthenticated ? (
-
- ) : (
-
- )}
-
-
-
- );
-}
+export default function MainHeader() {
+ const navigate = useNavigate();
+
+
+
+ return (
+
+ {/* 左侧导航栏 */}
+
+ {/* 用户头像区域 */}
+
+
+
}
+ className=" transition-all duration-300"
+ />
+
}
+ className="!absolute bottom-0 right-6 opacity-0 group-hover:opacity-100 transition-opacity duration-300"
+ onClick={() => navigate('/profile')}
+ />
+
+
+
+
+ {/* 新增可滚动内容区域 */}
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/apps/web/src/app/main/layout/MainLayout.tsx b/apps/web/src/app/main/layout/MainLayout.tsx
old mode 100755
new mode 100644
index fa3bad7..6957b9a
--- a/apps/web/src/app/main/layout/MainLayout.tsx
+++ b/apps/web/src/app/main/layout/MainLayout.tsx
@@ -1,21 +1,11 @@
-import { Layout } from "antd";
import { Outlet } from "react-router-dom";
-import { MainHeader } from "./MainHeader";
-import { MainFooter } from "./MainFooter";
-import { MainProvider } from "./MainProvider";
+import MainHeader from "./MainHeader";
+import { Content } from "antd/es/layout/layout";
+export default function MainLayout() {
+ return (
+ <>
+
+ >
-const { Content } = Layout;
-
-export function MainLayout() {
- return (
-
-
-
-
-
-
-
-
-
- );
-}
+ )
+}
\ No newline at end of file
diff --git a/apps/web/src/app/main/layout/MainProvider.tsx b/apps/web/src/app/main/layout/MainProvider.tsx
deleted file mode 100755
index 1d0396c..0000000
--- a/apps/web/src/app/main/layout/MainProvider.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import { PostType, Prisma } from "@nice/common";
-import React, {
- createContext,
- ReactNode,
- useContext,
- useMemo,
- useState,
-} from "react";
-import { useDebounce } from "use-debounce";
-interface SelectedTerms {
- [key: string]: string[]; // 每个 slug 对应一个 string 数组
-}
-
-interface MainContextType {
- searchValue?: string;
- selectedTerms?: SelectedTerms;
- setSearchValue?: React.Dispatch>;
- setSelectedTerms?: React.Dispatch>;
- searchCondition?: Prisma.PostWhereInput;
- termsCondition?: Prisma.PostWhereInput;
- searchMode?: PostType.COURSE | PostType.PATH | "both";
- setSearchMode?: React.Dispatch<
- React.SetStateAction
- >;
- showSearchMode?: boolean;
- setShowSearchMode?: React.Dispatch>;
-}
-
-const MainContext = createContext(null);
-interface MainProviderProps {
- children: ReactNode;
-}
-
-export function MainProvider({ children }: MainProviderProps) {
- const [searchMode, setSearchMode] = useState<
- PostType.COURSE | PostType.PATH | "both"
- >("both");
- const [showSearchMode, setShowSearchMode] = useState(false);
- const [searchValue, setSearchValue] = useState("");
- const [debouncedValue] = useDebounce(searchValue, 500);
- const [selectedTerms, setSelectedTerms] = useState({}); // 初始化状态
- const termFilters = useMemo(() => {
- return Object.entries(selectedTerms)
- .filter(([, terms]) => terms.length > 0)
- ?.map(([, terms]) => terms);
- }, [selectedTerms]);
-
- const termsCondition: Prisma.PostWhereInput = useMemo(() => {
- return termFilters && termFilters?.length > 0
- ? {
- AND: termFilters.map((termFilter) => ({
- terms: {
- some: {
- id: {
- in: termFilter, // 确保至少有一个 term.id 在当前 termFilter 中
- },
- },
- },
- })),
- }
- : {};
- }, [termFilters]);
- const searchCondition: Prisma.PostWhereInput = useMemo(() => {
- const containTextCondition: Prisma.StringNullableFilter = {
- contains: debouncedValue,
- mode: "insensitive" as Prisma.QueryMode, // 使用类型断言
- };
- return debouncedValue
- ? {
- OR: [
- { title: containTextCondition },
- { subTitle: containTextCondition },
- { content: containTextCondition },
- {
- terms: {
- some: {
- name: containTextCondition,
- },
- },
- },
- ],
- }
- : {};
- }, [debouncedValue]);
- return (
-
- {children}
-
- );
-}
-export const useMainContext = () => {
- const context = useContext(MainContext);
- if (!context) {
- throw new Error("useMainContext must be used within MainProvider");
- }
- return context;
-};
diff --git a/apps/web/src/app/main/layout/NavigationMenu.tsx b/apps/web/src/app/main/layout/NavigationMenu.tsx
old mode 100755
new mode 100644
index 1f50140..126b0fa
--- a/apps/web/src/app/main/layout/NavigationMenu.tsx
+++ b/apps/web/src/app/main/layout/NavigationMenu.tsx
@@ -1,59 +1,37 @@
-import { useAuth } from "@web/src/providers/auth-provider";
import { Menu } from "antd";
-import { useMemo } from "react";
-import { useNavigate, useLocation } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
-export const NavigationMenu = () => {
- const navigate = useNavigate();
- const { isAuthenticated } = useAuth();
- const { pathname } = useLocation();
-
- const menuItems = useMemo(() => {
- const baseItems = [
- { key: "home", path: "/", label: "首页" },
- { key: "path", path: "/path", label: "全部思维导图" },
- { key: "courses", path: "/courses", label: "所有课程" },
- ];
-
- if (!isAuthenticated) {
- return baseItems;
- } else {
- return [
- ...baseItems,
- { key: "my-duty", path: "/my-duty", label: "我创建的课程" },
- { key: "my-learning", path: "/my-learning", label: "我学习的课程" },
- { key: "my-duty-path", path: "/my-duty-path", label: "我创建的思维导图" },
- { key: "my-path", path: "/my-path", label: "我学习的思维导图" },
- ];
- }
- }, [isAuthenticated]);
-
- const selectedKey = useMemo(() => {
- const normalizePath = (path: string): string => path.replace(/\/$/, "");
- return pathname === '/' ? "home" : menuItems.find((item) => normalizePath(pathname) === item.path)?.key || "";
- }, [pathname]);
-
- return (
-
- );
-};
+export default function NavigationMenu() {
+ const navigate = useNavigate();
+ // 导航菜单项配置
+ const menuItems = [
+ { key: 'home', label: '首页', path: '/' },
+ { key: 'staff', label: '人员总览', path: '/staff' },
+ { key: 'day', label: '日统计', path: '/day' },
+ { key: 'month', label: '月统计', path: '/month' },
+ { key: 'year', label: '年度统计', path: '/year' }
+ ];
+ return (
+ <>
+ {/* 导航菜单 */}
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/apps/web/src/app/main/layout/UserMenu/UserEditModal.tsx b/apps/web/src/app/main/layout/UserMenu/UserEditModal.tsx
deleted file mode 100755
index ed30812..0000000
--- a/apps/web/src/app/main/layout/UserMenu/UserEditModal.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Button, Drawer, Modal } from "antd";
-import React, { useContext, useEffect, useState } from "react";
-
-import { UserEditorContext } from "./UserMenu";
-import UserForm from "./UserForm";
-
-export default function UserEditModal() {
- const { formLoading, modalOpen, setModalOpen, form } =
- useContext(UserEditorContext);
- const handleOk = () => {
- form.submit();
- };
- return (
- {
- setModalOpen(false);
- }}
- title={"编辑个人信息"}>
-
-
- );
-}
diff --git a/apps/web/src/app/main/layout/UserMenu/UserForm.tsx b/apps/web/src/app/main/layout/UserMenu/UserForm.tsx
deleted file mode 100755
index edef377..0000000
--- a/apps/web/src/app/main/layout/UserMenu/UserForm.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-import { Button, Form, Input, Spin, Switch, message } from "antd";
-import { useContext, useEffect } from "react";
-import { useStaff } from "@nice/client";
-import DepartmentSelect from "@web/src/components/models/department/department-select";
-import { api } from "@nice/client";
-
-import { useAuth } from "@web/src/providers/auth-provider";
-import AvatarUploader from "@web/src/components/common/uploader/AvatarUploader";
-import { StaffDto } from "@nice/common";
-import { UserEditorContext } from "./UserMenu";
-import toast from "react-hot-toast";
-export default function StaffForm() {
- const { user } = useAuth();
- const { create, update } = useStaff(); // Ensure you have these methods in your hooks
- const { formLoading, modalOpen, setModalOpen, domainId, setDomainId, form, setFormLoading, } = useContext(UserEditorContext);
- const {
- data,
- isLoading,
- }: {
- data: StaffDto;
- isLoading: boolean;
- } = api.staff.findFirst.useQuery(
- { where: { id: user?.id } },
- { enabled: !!user?.id }
- );
- const { isRoot } = useAuth();
- async function handleFinish(values: any) {
- const {
- username,
- showname,
- deptId,
- domainId,
- password,
- phoneNumber,
- officerId,
- enabled,
- avatar,
- photoUrl,
- email,
- rank,
- office,
- } = values;
- setFormLoading(true);
- try {
- if (data && user?.id) {
- await update.mutateAsync({
- where: { id: data.id },
- data: {
- username,
- deptId,
- showname,
- domainId,
- password,
- phoneNumber,
- officerId,
- enabled,
- avatar,
- },
- });
- }
- toast.success("提交成功");
- setModalOpen(false);
- } catch (err: any) {
- toast.error(err.message);
- } finally {
- setFormLoading(false);
- }
- }
- useEffect(() => {
- form.resetFields();
- console.log('cc', data);
-
- if (data) {
- form.setFieldValue("username", data.username);
- form.setFieldValue("showname", data.showname);
- form.setFieldValue("domainId", data.domainId);
- form.setFieldValue("deptId", data.deptId);
- form.setFieldValue("officerId", data.officerId);
- form.setFieldValue("phoneNumber", data.phoneNumber);
- form.setFieldValue("enabled", data.enabled);
- form.setFieldValue("avatar", data.avatar);
- }
- }, [data]);
- // useEffect(() => {
- // if (!data && domainId) {
- // form.setFieldValue("domainId", domainId);
- // form.setFieldValue("deptId", domainId);
- // }
- // }, [domainId, data as any]);
- return (
-
- {isLoading && (
-
-
-
- )}
-
-
- );
-}
diff --git a/apps/web/src/app/main/layout/UserMenu/UserMenu.tsx b/apps/web/src/app/main/layout/UserMenu/UserMenu.tsx
deleted file mode 100755
index fc63758..0000000
--- a/apps/web/src/app/main/layout/UserMenu/UserMenu.tsx
+++ /dev/null
@@ -1,246 +0,0 @@
-import { useClickOutside } from "@web/src/hooks/useClickOutside";
-import { useAuth } from "@web/src/providers/auth-provider";
-import { motion, AnimatePresence } from "framer-motion";
-import React, {
- useState,
- useRef,
- useCallback,
- useMemo,
- createContext,
-} from "react";
-import { Avatar } from "@web/src/components/common/element/Avatar";
-import {
- UserOutlined,
- SettingOutlined,
- LogoutOutlined,
-} from "@ant-design/icons";
-import { FormInstance, Spin } from "antd";
-import { useNavigate } from "react-router-dom";
-import { MenuItemType } from "./types";
-import { RolePerms } from "@nice/common";
-import { useForm } from "antd/es/form/Form";
-import UserEditModal from "./UserEditModal";
-const menuVariants = {
- hidden: { opacity: 0, scale: 0.95, y: -10 },
- visible: {
- opacity: 1,
- scale: 1,
- y: 0,
- transition: {
- type: "spring",
- stiffness: 300,
- damping: 30,
- },
- },
- exit: {
- opacity: 0,
- scale: 0.95,
- y: -10,
- transition: {
- duration: 0.2,
- },
- },
-};
-
-export const UserEditorContext = createContext<{
- domainId: string;
- setDomainId: React.Dispatch>;
- modalOpen: boolean;
- setModalOpen: React.Dispatch>;
- form: FormInstance;
- formLoading: boolean;
- setFormLoading: React.Dispatch>;
-}>({
- modalOpen: false,
- domainId: undefined,
- setDomainId: undefined,
- setModalOpen: undefined,
- form: undefined,
- formLoading: undefined,
- setFormLoading: undefined,
-});
-
-export function UserMenu() {
- const [form] = useForm();
- const [formLoading, setFormLoading] = useState();
- const [showMenu, setShowMenu] = useState(false);
- const menuRef = useRef(null);
- const { user, logout, isLoading, hasSomePermissions } = useAuth();
- const navigate = useNavigate();
- useClickOutside(menuRef, () => setShowMenu(false));
- const [modalOpen, setModalOpen] = useState(false);
- const [domainId, setDomainId] = useState();
- const toggleMenu = useCallback(() => {
- setShowMenu((prev) => !prev);
- }, []);
- const canManageAnyStaff = useMemo(() => {
- return hasSomePermissions(RolePerms.MANAGE_ANY_STAFF);
- }, [user]);
- const menuItems: MenuItemType[] = useMemo(
- () =>
- [
- {
- icon: ,
- label: "个人信息",
- action: () => {
- setModalOpen(true);
- },
- },
-
- canManageAnyStaff && {
- icon: ,
- label: "设置",
- action: () => {
- navigate("/admin/staff");
- },
- },
-
- {
- icon: ,
- label: "注销",
- action: () => logout(),
- },
- ].filter(Boolean),
- [logout]
- );
-
- const handleMenuItemClick = useCallback((action: () => void) => {
- action();
- setShowMenu(false);
- }, []);
-
- if (isLoading) {
- return (
-
-
-
- );
- }
-
- return (
-
-
-
- {/* Avatar 容器,相对定位 */}
-
-
-
-
- {showMenu && (
-
- )}
-
-
-
-
- );
-}
diff --git a/apps/web/src/app/main/layout/UserMenu/types.ts b/apps/web/src/app/main/layout/UserMenu/types.ts
deleted file mode 100755
index dfe4b00..0000000
--- a/apps/web/src/app/main/layout/UserMenu/types.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import React, { ReactNode } from "react";
-export interface MenuItemType {
- icon: ReactNode;
- label: string;
- action: () => void;
-}
diff --git a/apps/web/src/app/main/my-duty-path/components/MyDutyPathContainer.tsx b/apps/web/src/app/main/my-duty-path/components/MyDutyPathContainer.tsx
deleted file mode 100755
index 4b7f273..0000000
--- a/apps/web/src/app/main/my-duty-path/components/MyDutyPathContainer.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import PostList from "@web/src/components/models/course/list/PostList";
-import { useAuth } from "@web/src/providers/auth-provider";
-import { useMainContext } from "../../layout/MainProvider";
-import { PostType } from "@nice/common";
-import PathCard from "@web/src/components/models/post/SubPost/PathCard";
-
-export default function MyDutyPathContainer() {
- const { user } = useAuth();
- const { searchCondition, termsCondition } = useMainContext();
- return (
- <>
- }
- params={{
- pageSize: 12,
- where: {
- type: PostType.PATH,
- authorId: user?.id,
- ...termsCondition,
- ...searchCondition,
- },
- }}
- cols={4}>
- >
- );
-}
diff --git a/apps/web/src/app/main/my-duty-path/page.tsx b/apps/web/src/app/main/my-duty-path/page.tsx
deleted file mode 100755
index 24d7931..0000000
--- a/apps/web/src/app/main/my-duty-path/page.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { useEffect } from "react";
-import BasePostLayout from "../layout/BasePost/BasePostLayout";
-import { useMainContext } from "../layout/MainProvider";
-import { PostType } from "@nice/common";
-import MyDutyPathContainer from "./components/MyDutyPathContainer";
-
-export default function MyDutyPathPage() {
- const { setSearchMode } = useMainContext();
- useEffect(() => {
- setSearchMode(PostType.PATH);
- }, [setSearchMode]);
- return (
-
-
-
- );
-}
diff --git a/apps/web/src/app/main/my-duty/components/MyDutyListContainer.tsx b/apps/web/src/app/main/my-duty/components/MyDutyListContainer.tsx
deleted file mode 100755
index 727e828..0000000
--- a/apps/web/src/app/main/my-duty/components/MyDutyListContainer.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import PostList from "@web/src/components/models/course/list/PostList";
-import { useAuth } from "@web/src/providers/auth-provider";
-import { PostType } from "@nice/common";
-import { useMainContext } from "../../layout/MainProvider";
-import PostCard from "@web/src/components/models/post/PostCard";
-import CourseCard from "@web/src/components/models/post/SubPost/CourseCard";
-
-export default function MyDutyListContainer() {
- const { user } = useAuth();
- const { searchCondition, termsCondition } = useMainContext();
- return (
- <>
- }
- params={{
- pageSize: 12,
- where: {
- type: PostType.COURSE,
- authorId: user.id,
- ...termsCondition,
- ...searchCondition,
- },
- }}
- cols={4}>
- >
- );
-}
diff --git a/apps/web/src/app/main/my-duty/page.tsx b/apps/web/src/app/main/my-duty/page.tsx
deleted file mode 100755
index fff4c91..0000000
--- a/apps/web/src/app/main/my-duty/page.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import BasePostLayout from "../layout/BasePost/BasePostLayout";
-import MyDutyListContainer from "./components/MyDutyListContainer";
-import { useEffect } from "react";
-import { useMainContext } from "../layout/MainProvider";
-import { PostType } from "@nice/common";
-export default function MyDutyPage() {
- const { setSearchMode } = useMainContext();
- useEffect(() => {
- setSearchMode(PostType.COURSE);
- }, [setSearchMode]);
- return (
-
-
-
- );
-}
diff --git a/apps/web/src/app/main/my-learning/components/MyLearningListContainer.tsx b/apps/web/src/app/main/my-learning/components/MyLearningListContainer.tsx
deleted file mode 100755
index be281ae..0000000
--- a/apps/web/src/app/main/my-learning/components/MyLearningListContainer.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import PostList from "@web/src/components/models/course/list/PostList";
-import { useAuth } from "@web/src/providers/auth-provider";
-import { useMainContext } from "../../layout/MainProvider";
-import { PostType } from "@nice/common";
-import PostCard from "@web/src/components/models/post/PostCard";
-import CourseCard from "@web/src/components/models/post/SubPost/CourseCard";
-
-export default function MyLearningListContainer() {
- const { user } = useAuth();
- const { searchCondition, termsCondition } = useMainContext();
- return (
- <>
- }
- params={{
- pageSize: 12,
- where: {
- type: PostType.COURSE,
- students: {
- some: {
- id: user?.id,
- },
- },
- ...termsCondition,
- ...searchCondition,
- },
- }}
- cols={4}>
- >
- );
-}
diff --git a/apps/web/src/app/main/my-learning/page.tsx b/apps/web/src/app/main/my-learning/page.tsx
deleted file mode 100755
index cee2c94..0000000
--- a/apps/web/src/app/main/my-learning/page.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { useEffect } from "react";
-import BasePostLayout from "../layout/BasePost/BasePostLayout";
-import { useMainContext } from "../layout/MainProvider";
-import MyLearningListContainer from "./components/MyLearningListContainer";
-import { PostType } from "@nice/common";
-
-export default function MyLearningPage() {
- const { setSearchMode } = useMainContext();
- useEffect(() => {
- setSearchMode(PostType.COURSE);
- }, [setSearchMode]);
- return (
-
-
-
- );
-}
diff --git a/apps/web/src/app/main/my-path/components/MyPathListContainer.tsx b/apps/web/src/app/main/my-path/components/MyPathListContainer.tsx
deleted file mode 100755
index b7dfd33..0000000
--- a/apps/web/src/app/main/my-path/components/MyPathListContainer.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import PostList from "@web/src/components/models/course/list/PostList";
-import { useAuth } from "@web/src/providers/auth-provider";
-
-import { PostType } from "@nice/common";
-import { useMainContext } from "../../layout/MainProvider";
-import PostCard from "@web/src/components/models/post/PostCard";
-import PathCard from "@web/src/components/models/post/SubPost/PathCard";
-
-export default function MyPathListContainer() {
- const { user } = useAuth();
- const { searchCondition, termsCondition } = useMainContext();
- return (
- <>
- }
- params={{
- pageSize: 12,
- where: {
- type: PostType.PATH,
- students: {
- some: {
- id: user?.id,
- },
- },
-
- ...termsCondition,
- ...searchCondition,
- },
- }}
- cols={4}>
- >
- );
-}
diff --git a/apps/web/src/app/main/my-path/page.tsx b/apps/web/src/app/main/my-path/page.tsx
deleted file mode 100755
index 81f7298..0000000
--- a/apps/web/src/app/main/my-path/page.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { useEffect } from "react";
-import BasePostLayout from "../layout/BasePost/BasePostLayout";
-import { useMainContext } from "../layout/MainProvider";
-import MyPathListContainer from "./components/MyPathListContainer";
-import { PostType } from "@nice/common";
-
-export default function MyPathPage() {
- const { setSearchMode } = useMainContext();
- useEffect(() => {
- setSearchMode(PostType.PATH);
- }, [setSearchMode]);
- return (
-
-
-
- );
-}
diff --git a/apps/web/src/app/main/path/components/DeptInfo.tsx b/apps/web/src/app/main/path/components/DeptInfo.tsx
deleted file mode 100755
index ed6510b..0000000
--- a/apps/web/src/app/main/path/components/DeptInfo.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { BookOutlined, EyeOutlined, TeamOutlined } from "@ant-design/icons";
-import { Typography } from "antd";
-import { PostDto } from "@nice/common";
-
-const { Title, Text } = Typography;
-const DeptInfo = ({ post }: { post: PostDto }) => {
- return (
-
-
-
- {post?.depts && post?.depts?.length > 0 ? (
-
- {post?.depts?.length > 1
- ? `${post.depts[0].name}等`
- : post?.depts?.[0]?.name}
-
- ) : (
-
- 未设置单位
-
- )}
-
- {post && (
-
-
- 浏览量
-
- {`${post?.views || 0}`}
-
- {post?.studentIds && post?.studentIds?.length > 0 && (
-
-
- {`${post?.studentIds?.length || 0}`}
-
- )}
-
- )}
-
- );
-};
-
-export default DeptInfo;
diff --git a/apps/web/src/app/main/path/components/PathListContainer.tsx b/apps/web/src/app/main/path/components/PathListContainer.tsx
deleted file mode 100755
index 4e7ade6..0000000
--- a/apps/web/src/app/main/path/components/PathListContainer.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import PostList from "@web/src/components/models/course/list/PostList";
-import { useMainContext } from "../../layout/MainProvider";
-import { PostType, Prisma } from "@nice/common";
-import PostCard from "@web/src/components/models/post/PostCard";
-import PathCard from "@web/src/components/models/post/SubPost/PathCard";
-
-export function PathListContainer() {
- const { searchCondition, termsCondition } = useMainContext();
- return (
- <>
- }
- params={{
- pageSize: 12,
- where: {
- type: PostType.PATH,
- ...termsCondition,
- ...searchCondition,
- },
- }}
- cols={4}>
- >
- );
-}
-export default PathListContainer;
diff --git a/apps/web/src/app/main/path/components/TermInfo.tsx b/apps/web/src/app/main/path/components/TermInfo.tsx
deleted file mode 100755
index 21fed6d..0000000
--- a/apps/web/src/app/main/path/components/TermInfo.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import { Tag } from "antd";
-import { PostDto, TaxonomySlug, TermDto } from "@nice/common";
-
-const TermInfo = ({ terms = [] }: { terms?: TermDto[] }) => {
- return (
-
- {terms && terms?.length > 0 ? (
-
- {terms
- ?.sort((a, b) =>
- String(a?.taxonomy?.id || "").localeCompare(
- String(b?.taxonomy?.id || "")
- )
- )
- ?.map((term: any) => {
- return (
-
- {term.name}
-
- );
- })}
-
- ) : (
-
-
- {"未设置分类"}
-
-
- )}
-
- );
-};
-
-export default TermInfo;
diff --git a/apps/web/src/app/main/path/editor/page.tsx b/apps/web/src/app/main/path/editor/page.tsx
deleted file mode 100755
index 2c0b8b0..0000000
--- a/apps/web/src/app/main/path/editor/page.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import MindEditor from "@web/src/components/common/editor/MindEditor";
-import { PostDetailProvider } from "@web/src/components/models/course/detail/PostDetailContext";
-import { useParams } from "react-router-dom";
-
-export default function PathEditorPage() {
- const { id } = useParams();
- return (
-
- ;
-
- );
-}
diff --git a/apps/web/src/app/main/path/page.tsx b/apps/web/src/app/main/path/page.tsx
deleted file mode 100755
index 542689b..0000000
--- a/apps/web/src/app/main/path/page.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { useEffect } from "react";
-import BasePostLayout from "../layout/BasePost/BasePostLayout";
-import { useMainContext } from "../layout/MainProvider";
-import PathListContainer from "./components/PathListContainer";
-import { PostType } from "@nice/common";
-import { PostDetailProvider } from "@web/src/components/models/course/detail/PostDetailContext";
-import { useParams } from "react-router-dom";
-
-export default function PathPage() {
- const { setSearchMode } = useMainContext();
- useEffect(() => {
- setSearchMode(PostType.PATH);
- }, [setSearchMode]);
- const { id } = useParams();
- return (
-
-
-
- );
-}
diff --git a/apps/web/src/app/main/search/components/SearchContainer.tsx b/apps/web/src/app/main/search/components/SearchContainer.tsx
deleted file mode 100755
index 292d9b5..0000000
--- a/apps/web/src/app/main/search/components/SearchContainer.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import PostList from "@web/src/components/models/course/list/PostList";
-import { useMainContext } from "../../layout/MainProvider";
-import PostCard from "@web/src/components/models/post/PostCard";
-import { PostType } from "@nice/common";
-import CourseCard from "@web/src/components/models/post/SubPost/CourseCard";
-import PathCard from "@web/src/components/models/post/SubPost/PathCard";
-const POST_TYPE_COMPONENTS = {
- [PostType.COURSE]: CourseCard,
- [PostType.PATH]: PathCard,
-};
-export default function SearchListContainer() {
- const { searchCondition, termsCondition, searchMode } = useMainContext();
-
- return (
- <>
- {
- const Component =
- POST_TYPE_COMPONENTS[post.type] || PostCard;
- return ;
- }}
- params={{
- pageSize: 12,
- where: {
- type: searchMode === "both" ? undefined : searchMode,
- ...termsCondition,
- ...searchCondition,
- },
- }}
- cols={4}>
- >
- );
-}
diff --git a/apps/web/src/app/main/search/page.tsx b/apps/web/src/app/main/search/page.tsx
deleted file mode 100755
index cfb6153..0000000
--- a/apps/web/src/app/main/search/page.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { useEffect } from "react";
-import BasePostLayout from "../layout/BasePost/BasePostLayout";
-import SearchListContainer from "./components/SearchContainer";
-import { useMainContext } from "../layout/MainProvider";
-
-export default function SearchPage() {
- const { setShowSearchMode, setSearchValue } = useMainContext();
- useEffect(() => {
- setShowSearchMode(true);
- return () => {
- setShowSearchMode(false);
- setSearchValue("");
- };
- }, [setShowSearchMode]);
- return (
-
-
-
- );
-}
diff --git a/apps/web/src/app/main/self/courses/page.tsx b/apps/web/src/app/main/self/courses/page.tsx
deleted file mode 100755
index 36b358f..0000000
--- a/apps/web/src/app/main/self/courses/page.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-export default function MyCoursePage() {
- return (
-
- My Course Page
-
- )
-}
\ No newline at end of file
diff --git a/apps/web/src/app/main/self/profiles/page.tsx b/apps/web/src/app/main/self/profiles/page.tsx
deleted file mode 100755
index 70ac75b..0000000
--- a/apps/web/src/app/main/self/profiles/page.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function ProfilesPage() {
- return <>Profiles>
-}
\ No newline at end of file
diff --git a/apps/web/src/app/main/staffpage/page.tsx b/apps/web/src/app/main/staffpage/page.tsx
new file mode 100644
index 0000000..7170da7
--- /dev/null
+++ b/apps/web/src/app/main/staffpage/page.tsx
@@ -0,0 +1,260 @@
+import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
+import { api, useStaff } from "@nice/client";
+import { Button, Form, Input, Modal, Select, Table } from "antd";
+import { StaffDto } from "@nice/common";
+import { useEffect, useState } from "react";
+import toast from "react-hot-toast";
+
+export default function StaffMessage() {
+ const initialValues = {
+ username: "",
+ deptId: "",
+ absent: "是",
+ };
+ const { create, update } = useStaff();
+ const [searchName, setSearchName] = useState("");
+ const { data: staffs, isLoading } = api.staff.findMany.useQuery({
+ where: {
+ username: {
+ contains: searchName
+ }
+ }
+ });
+ console.log(staffs);
+ const [form] = Form.useForm();
+ const [visible, setVisible] = useState(false);
+ const [editingRecord, setEditingRecord] = useState(null);
+ const colnums = [
+ {
+ title: "姓名",
+ dataIndex: "username",
+ key: "username",
+ },
+ {
+ title: "部门",
+ dataIndex: "deptId",
+ key: "deptId",
+ },
+ {
+ title: "在位",
+ dataIndex: "absent",
+ key: "absent",
+ render: (_, record) => (
+
+ )
+ },
+ {
+ title: "操作",
+ key: "action",
+ render: (_, record) => (
+
+ ),
+ }
+ ];
+
+ const handleNew = () => {
+ form.setFieldsValue(initialValues);
+ setVisible(true);
+ }
+
+ useEffect(() => {
+ if (editingRecord) {
+ form.setFieldsValue(editingRecord);
+ console.log(editingRecord);
+ }
+ }, [editingRecord]);
+
+ const handleEdit = (record) => {
+ setEditingRecord(record);
+ form.setFieldsValue(editingRecord);
+ setVisible(true);
+ };
+
+ const handleOk = async () => {
+ const values = await form.getFieldsValue();
+ const orderValue = values.order ? parseFloat(values.order) : null;
+ console.log(values.username);
+ try {
+ if (editingRecord && editingRecord.id) {
+ // console.log(editingRecord);
+ const result = await update.mutateAsync(
+ {
+ where: {
+ id: editingRecord.id,
+ },
+ data: {
+ username: values.username,
+ deptId: values.deptId,
+ order: orderValue,
+ updatedAt: new Date()
+ }
+ }
+ );
+ // console.log(result);
+ } else {
+ await create.mutateAsync(
+ {
+ data: {
+ username: values.username,
+ deptId: values.deptId,
+ order: orderValue,
+ createdAt: new Date(),
+ showname: values.username,
+ }
+ }
+ );
+ }
+ toast.success("保存成功");
+ setVisible(false);
+ } catch (error) {
+ toast.error("保存失败");
+ throw error;
+ }
+ };
+
+ const handleCancel = () => {
+ setVisible(false);
+ };
+
+ const handleSearch = (e) => {
+ setSearchName(e.target.value);
+ };
+
+ return (
+
+ );
+}
+
diff --git a/apps/web/src/routes/index.tsx b/apps/web/src/routes/index.tsx
index e48165d..85a7d84 100755
--- a/apps/web/src/routes/index.tsx
+++ b/apps/web/src/routes/index.tsx
@@ -6,25 +6,10 @@ import {
useParams,
} from "react-router-dom";
import ErrorPage from "../app/error";
-import WithAuth from "../components/utils/with-auth";
import LoginPage from "../app/login";
import HomePage from "../app/main/home/page";
-import { CourseDetailPage } from "../app/main/course/detail/page";
-import { CourseBasicForm } from "../components/models/course/editor/form/CourseBasicForm";
-import CourseContentForm from "../components/models/course/editor/form/CourseContentForm/CourseContentForm";
-import CourseEditorLayout from "../components/models/course/editor/layout/CourseEditorLayout";
-import { MainLayout } from "../app/main/layout/MainLayout";
-import CoursesPage from "../app/main/courses/page";
-import PathPage from "../app/main/path/page";
-import { adminRoute } from "./admin-route";
-import PathEditorPage from "../app/main/path/editor/page";
-
-import { CoursePreview } from "../app/main/course/preview/page";
-import MyLearningPage from "../app/main/my-learning/page";
-import MyDutyPage from "../app/main/my-duty/page";
-import MyPathPage from "../app/main/my-path/page";
-import SearchPage from "../app/main/search/page";
-import MyDutyPathPage from "../app/main/my-duty-path/page";
+import StaffMessage from "../app/main/staffpage/page";
+import MainLayout from "../app/main/layout/MainLayout";
interface CustomIndexRouteObject extends IndexRouteObject {
name?: string;
breadcrumb?: string;
@@ -60,103 +45,15 @@ export const routes: CustomRouteObject[] = [
children: [
{
index: true,
- element: ,
+ element: ,
},
{
- path: "path",
- children: [
- {
- index: true,
- element: ,
- },
- {
- path: "editor/:id?",
- element: (
-
- ),
- },
- ],
- },
- {
- path: "courses",
- element: ,
- },
- {
- path: "my-path",
- element: (
-
-
-
- ),
- },
- {
- path: "my-duty-path",
- element: (
-
-
-
- ),
- },
- {
- path: "my-duty",
- element: (
-
-
-
- ),
- },
- {
- path: "my-learning",
- element: (
-
-
-
- ),
- },
- {
- path: "search",
- element: ,
- },
- {
- path: "course/:id?/detail/:lectureId?", // 使用 ? 表示 id 参数是可选的
- element: ,
+ path: "/staff",
+ element: ,
},
],
},
-
- {
- path: "course",
- children: [
- {
- path: ":id?/editor",
- element: (
-
-
-
- ),
- children: [
- {
- index: true,
- element: (
-
-
-
- ),
- },
-
- {
- path: "content",
- element: (
-
-
-
- ),
- },
- ],
- },
- ],
- },
- adminRoute,
+
],
},
{