夏泽霖“git config --global user.name 夏泽霖“ il y a 2 ans
Parent
commit
08cb323dce

+ 9 - 0
package-lock.json

@@ -29,6 +29,7 @@
         "react-scripts": "5.0.1",
         "sass": "^1.71.1",
         "sass-loader": "^14.1.1",
+        "swiper": "^11.0.7",
         "typescript": "^4.9.5",
         "web-vitals": "^2.1.4",
         "zustand": "^4.5.1"
@@ -16927,6 +16928,14 @@
         "boolbase": "~1.0.0"
       }
     },
+    "node_modules/swiper": {
+      "version": "11.0.7",
+      "resolved": "https://registry.npmmirror.com/swiper/-/swiper-11.0.7.tgz",
+      "integrity": "sha512-cDfglW1B6uSmB6eB6pNmzDTNLmZtu5bWWa1vak0RU7fOI9qHjMzl7gVBvYSl34b0RU2N11HxxETJqQ5LeqI1cA==",
+      "engines": {
+        "node": ">= 4.7.0"
+      }
+    },
     "node_modules/symbol-tree": {
       "version": "3.2.4",
       "resolved": "https://r2.cnpmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",

+ 1 - 0
package.json

@@ -24,6 +24,7 @@
     "react-scripts": "5.0.1",
     "sass": "^1.71.1",
     "sass-loader": "^14.1.1",
+    "swiper": "^11.0.7",
     "typescript": "^4.9.5",
     "web-vitals": "^2.1.4",
     "zustand": "^4.5.1"

BIN
src/image/ArrowLeft.png


BIN
src/image/ArrowRight.png


+ 1 - 1
src/layout/Layout/Layout.tsx

@@ -24,7 +24,7 @@ const items = [
 
 // 简单的三段式布局
 const Layout: React.FC<LayoutProps> = ({ children }) => {
-  const [current, setCurrent] = useState(['work']);
+  const [current, setCurrent] = useState(['square']);
 
   function onChange({ key }: { key: string }) {
     setCurrent([key]);

+ 63 - 0
src/pages/CourseSquare/component/Banner/Banner.tsx

@@ -0,0 +1,63 @@
+import {Swiper, SwiperSlide, SwiperClass} from "swiper/react";
+import ArrowLeft from "../../../../image/ArrowLeft.png";
+import ArrowRight from "../../../../image/ArrowRight.png"
+import "./index.scss"
+import {useRef} from "react";
+
+export function Banner() {
+    const current = useRef<SwiperClass>()
+
+
+    function onClickPre() {
+        current.current.slidePrev()
+    }
+
+    function onClickNext() {
+        current.current.slideNext()
+    }
+
+    return <div className="swiper-banner">
+        <Swiper
+            slidesPerView={1}
+            onSlideChange={() => console.log('slide change')}
+            onSwiper={(swiper: SwiperClass) => current.current = swiper}
+            loop
+            autoplay
+        >
+            <div className="arrow left">
+                <img src={ArrowLeft} className="arrow-image" alt="" onClick={onClickPre}/>
+            </div>
+            <div className="arrow top">
+                <img src={ArrowRight} className="arrow-image" alt="" onClick={onClickNext}/>
+            </div>
+            <SwiperSlide className="slide-items">
+                <img
+                    src="https://cdn.pixabay.com/photo/2024/03/04/16/44/barberry-8612696_960_720.jpg"
+                    alt=""
+                    className="slider-image"
+                />
+            </SwiperSlide>
+            <SwiperSlide className="slide-items">
+                <img
+                    src="https://cdn.pixabay.com/photo/2023/11/24/17/22/pigeon-8410348_1280.jpg"
+                    alt=""
+                    className="slider-image"
+                />
+            </SwiperSlide>
+            <SwiperSlide className="slide-items">
+                <img
+                    src="https://cdn.pixabay.com/photo/2024/01/29/13/00/rabbit-8539830_960_720.jpg"
+                    alt=""
+                    className="slider-image"
+                />
+            </SwiperSlide>
+            <SwiperSlide className="slide-items">
+                <img
+                    src="https://cdn.pixabay.com/photo/2024/02/05/10/48/red-kite-8554201_960_720.jpg"
+                    alt=""
+                    className="slider-image"
+                />
+            </SwiperSlide>
+        </Swiper>
+    </div>
+}

+ 46 - 0
src/pages/CourseSquare/component/Banner/index.scss

@@ -0,0 +1,46 @@
+
+.swiper-banner {
+  width: 1000px;
+  margin: 0 auto;
+  height: 400px;
+  border-radius: 10px;
+  overflow: hidden;
+  position: relative;
+
+  .slide-items {
+    box-sizing: border-box;
+    height: 400px;
+  }
+
+  .slider-image {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+  }
+
+  .arrow {
+    position: absolute;
+    z-index: 999;
+    width: 30px;
+    height: 30px;
+    top: 50%;
+    transform: translateY(-50%);
+    cursor: pointer;
+
+
+    & img {
+      width: 100%;
+      height: 100%;
+      background-color: rgba(107, 107, 107, 0.24);
+      border-radius: 100px;
+    }
+
+    &.left {
+      left: 20px;
+    }
+
+    &.top {
+      right: 20px;
+    }
+  }
+}

+ 48 - 0
src/pages/CourseSquare/component/Course/index.scss

@@ -0,0 +1,48 @@
+.course-content {
+  width: 80%;
+  margin: 40px auto 0 auto;
+  position: relative;
+
+  .course-item {
+    border: solid 1px #e1e1e1;
+    height: 250px;
+    border-radius: 10px;
+    box-sizing: border-box;
+    cursor: pointer;
+  }
+
+  .arrow-image {
+    position: absolute;
+    width: 30px;
+    top: 50%;
+    transform: translateY(-50%);
+    cursor: pointer;
+
+    &.left {
+      left: -50px;
+    }
+
+    &.right {
+      right: -50px;
+      transform: translateY(-50%) rotate(180deg);
+    }
+  }
+
+  .course-swiper {
+    margin-top: 20px;
+    border-radius: 10px;
+  }
+
+  .item-image {
+    height: 80px;
+  }
+
+  .item-text {
+    border-top: solid 1px #e1e1e1;
+    padding: 10px;
+    box-sizing: border-box;
+    display: flex;
+    gap: 10px;
+    flex-direction: column;
+  }
+}

+ 108 - 0
src/pages/CourseSquare/component/Course/index.tsx

@@ -0,0 +1,108 @@
+import "./index.scss"
+import {Swiper, SwiperSlide} from "swiper/react";
+import React, {useRef} from "react";
+import ArrowFrom from "@/image/arrow.png";
+import {SwiperClass} from "swiper/swiper-react";
+
+
+interface CourseInterface {
+    title: string,
+    onChange: (value: any) => void
+}
+
+export function Course({title, onChange}: CourseInterface) {
+    const current = useRef<SwiperClass>()
+
+    function onClickPre() {
+        current.current.slidePrev()
+    }
+
+    function onClickNext() {
+        current.current.slideNext()
+    }
+
+    return <div className="course-content">
+        <div className="arrow left">
+            <img src={ArrowFrom} className="arrow-image left" alt="" onClick={onClickPre}/>
+        </div>
+        <div className="arrow top">
+            <img src={ArrowFrom} className="arrow-image right" alt="" onClick={onClickNext}/>
+        </div>
+        <div className="header-title">
+            {title}
+        </div>
+        <div className="course-swiper">
+            <Swiper
+                spaceBetween={50}
+                slidesPerView={5}
+                onSwiper={(swiper: SwiperClass) => current.current = swiper}
+            >
+                <SwiperSlide className="course-item" onClick={onChange.bind(null, {})}>
+                    <div className="item-image">
+
+                    </div>
+                    <div className="item-text">
+                        <div className="item-text-title">
+                            英文论文写作
+                        </div>
+                        <div className="item-text-desc">
+                            任课老师:XXX
+                        </div>
+                    </div>
+                </SwiperSlide>
+                <SwiperSlide className="course-item" onClick={onChange.bind(null, {})}>
+                    <div className="item-image">
+
+                    </div>
+                    <div className="item-text">
+                        <div className="item-text-title">
+                            英文论文写作
+                        </div>
+                        <div className="item-text-desc">
+                            任课老师:XXX
+                        </div>
+                    </div>
+                </SwiperSlide>
+                <SwiperSlide className="course-item" onClick={onChange.bind(null, {})}>
+                    <div className="item-image">
+
+                    </div>
+                    <div className="item-text">
+                        <div className="item-text-title">
+                            英文论文写作
+                        </div>
+                        <div className="item-text-desc">
+                            任课老师:XXX
+                        </div>
+                    </div>
+                </SwiperSlide>
+                <SwiperSlide className="course-item" onClick={onChange.bind(null, {})}>
+                    <div className="item-image">
+
+                    </div>
+                    <div className="item-text">
+                        <div className="item-text-title">
+                            英文论文写作
+                        </div>
+                        <div className="item-text-desc">
+                            任课老师:XXX
+                        </div>
+                    </div>
+                </SwiperSlide>
+                <SwiperSlide className="course-item" onClick={onChange.bind(null, {})}>
+                    <div className="item-image">
+
+                    </div>
+                    <div className="item-text">
+                        <div className="item-text-title">
+                            英文论文写作
+                        </div>
+                        <div className="item-text-desc">
+                            任课老师:XXX
+                        </div>
+                    </div>
+                </SwiperSlide>
+            </Swiper>
+        </div>
+    </div>
+}

+ 50 - 0
src/pages/CourseSquare/component/CourseDetails/index.scss

@@ -0,0 +1,50 @@
+.course-details {
+  width: 800px;
+  margin: 0 auto;
+
+
+  .course-details-info {
+    padding: 20px;
+    box-sizing: border-box;
+    border-radius: 7px;
+    border: solid 1px #d0d0d0;
+    display: flex;
+    gap: 20px;
+
+    .course-details-image {
+      width: 350px;
+      background-color: #d9d9d9;
+      height: 200px;
+      border-radius: 7px;
+    }
+
+    .course-details-text {
+      display: flex;
+      flex-direction: column;
+      gap: 15px;
+    }
+
+    .title {
+      font-size: 18px;
+    }
+  }
+
+  .course-tabs {
+    border: solid 1px #d0d0d0;
+    padding: 20px;
+    margin-top: 30px;
+    border-radius: 7px;
+
+    .ant-tabs-tab-active {
+      & .ant-tabs-tab-btn {
+        color: #406621 !important;
+      }
+    }
+
+    .ant-tabs-ink-bar-animated {
+      background-color: #406621 !important;
+    }
+  }
+
+
+}

+ 113 - 0
src/pages/CourseSquare/component/CourseDetails/index.tsx

@@ -0,0 +1,113 @@
+import "./index.scss"
+import {Avatar, Table, Tabs} from "antd";
+import React from "react";
+
+
+export function CourseInfo() {
+    return <div>
+        课程简介
+    </div>
+}
+
+
+export function CourseWorkList() {
+    const dataSource = [
+        {
+            desc: '1',
+            publisher: '胡彦斌',
+            date: 32,
+        },
+        {
+            desc: '2',
+            publisher: '胡彦祖',
+            date: 42,
+        },
+    ];
+
+
+    const columns = [
+        {
+            title: '作业描述',
+            dataIndex: 'desc',
+            key: 'desc',
+        },
+        {
+            title: '发布人',
+            dataIndex: 'publisher',
+            key: 'publisher',
+        },
+        {
+            title: '截止日期',
+            dataIndex: 'date',
+            key: 'date',
+        },
+        {
+            title: '详情',
+            dataIndex: 'details',
+            key: 'details',
+            render: () => <Avatar size={32}/>,
+        },
+        {
+            title: '写作',
+            dataIndex: 'writing',
+            key: 'writing',
+            render: () => <Avatar size={32}/>,
+        },
+    ];
+
+
+    return <div>
+        {
+            <Table
+                dataSource={dataSource}
+                columns={columns}
+                pagination={false}
+                // @ts-ignore
+                rowKey={(key, index) => index}
+            />
+        }
+    </div>
+}
+
+export function CourseDetails() {
+    const items = [
+        {
+            label: `课程简介`,
+            key: '课程简介',
+            children: <CourseInfo/>,
+        },
+        {
+            label: `作业列表`,
+            key: '作业列表',
+            children: <CourseWorkList/>
+        }
+    ]
+
+    return <div className="course-details">
+        <div className="course-details-info">
+            <div className="course-details-image">
+
+            </div>
+            <div className="course-details-text">
+                <div className="title">
+                    (课程名称)
+                </div>
+                <div className="item">
+                    任课老师:
+                </div>
+                <div className="item">
+                    目标学生:
+                </div>
+                <div className="item">
+                    起止时间:
+                </div>
+            </div>
+        </div>
+        <div className="course-tabs">
+            <Tabs
+                defaultValue="课程简介"
+                items={items}
+            />
+        </div>
+    </div>
+}

+ 6 - 0
src/pages/CourseSquare/index.scss

@@ -0,0 +1,6 @@
+.course {
+  padding: 20px;
+  box-sizing: border-box;
+  height: 100%;
+  overflow: auto;
+}

+ 28 - 0
src/pages/CourseSquare/index.tsx

@@ -0,0 +1,28 @@
+import 'swiper/css';
+import "./index.scss"
+import {Banner} from "./component/Banner/Banner"
+import {Course} from "@/pages/CourseSquare/component/Course";
+import {useState} from "react";
+import {CourseDetails} from "@/pages/CourseSquare/component/CourseDetails";
+
+/**
+ * 课程广场
+ * @constructor
+ */
+export function CourseSquare() {
+    const [current, setCurrent] = useState()
+
+    return <div className="course">
+        {
+            !current ?
+                <>
+                    <Banner/>
+                    <Course title="课程广场" onChange={setCurrent}/>
+                    <Course title="我的课程" onChange={setCurrent}/>
+                </> :
+                <CourseDetails/>
+        }
+
+
+    </div>
+}

+ 17 - 11
src/pages/Home/Home.tsx

@@ -1,20 +1,26 @@
-import { MyHomework } from "@/pages/Home/component/MyHomework";
+import {MyHomework} from "@/pages/Home/component/MyHomework";
 import TeachersHomeWork from "./component/TeachersHomeWork";
 import "./index.scss";
+import {CourseSquare} from "@/pages/CourseSquare";
 
 interface HomeProps {
-  current: string;
+    current: string;
 }
 
-function Home({ current }: HomeProps) {
-  const state: "teachers" | "student" = "student";
-  return (
-    <div className="home-container">
-      {current === "work" &&
-        // @ts-ignore
-        (state === "teachers" ? <TeachersHomeWork /> : <MyHomework />)}
-    </div>
-  );
+function Home({current}: HomeProps) {
+    const state: "teachers" | "student" = "student";
+
+    console.log(current)
+    return (
+        <div className="home-container">
+            {current === "work" &&
+                // @ts-ignore
+                (state === "teachers" ? <TeachersHomeWork/> : <MyHomework/>)}
+            {
+                current === "square" && <CourseSquare/>
+            }
+        </div>
+    );
 }
 
 export default Home;

+ 5 - 0
yarn.lock

@@ -10043,6 +10043,11 @@ svgo@^2.7.0:
     picocolors "^1.0.0"
     stable "^0.1.8"
 
+swiper@^11.0.7:
+  version "11.0.7"
+  resolved "https://registry.npmmirror.com/swiper/-/swiper-11.0.7.tgz"
+  integrity sha512-cDfglW1B6uSmB6eB6pNmzDTNLmZtu5bWWa1vak0RU7fOI9qHjMzl7gVBvYSl34b0RU2N11HxxETJqQ5LeqI1cA==
+
 symbol-tree@^3.2.4:
   version "3.2.4"
   resolved "https://r2.cnpmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz"