黄琪勇 1 年之前
父节点
当前提交
8526cd339b
共有 33 个文件被更改,包括 1043 次插入383 次删除
  1. 30 0
      src/api/curriculum.api.ts
  2. 23 0
      src/api/homePage.api.ts
  3. 6 6
      src/config/menus.ts
  4. 1 1
      src/hooks/useDialogConfirm/dialogConfirm.vue
  5. 0 0
      src/img/curriculum/Band.png
  6. 二进制
      src/img/curriculum/DEMO.png
  7. 二进制
      src/img/curriculum/LIVE.png
  8. 二进制
      src/img/curriculum/PRACTICE.png
  9. 二进制
      src/img/curriculum/Vip.png
  10. 二进制
      src/img/curriculum/qd1.png
  11. 二进制
      src/img/curriculum/qd2.png
  12. 二进制
      src/img/curriculum/qt1.png
  13. 二进制
      src/img/curriculum/qt2.png
  14. 二进制
      src/img/curriculum/ts1.png
  15. 二进制
      src/img/curriculum/ts2.png
  16. 二进制
      src/img/curriculum/ts3.png
  17. 二进制
      src/img/curriculum/xs.png
  18. 二进制
      src/img/homePage/back.png
  19. 二进制
      src/img/homePage/bg.png
  20. 二进制
      src/img/homePage/bg1.png
  21. 1 2
      src/router/modules.ts
  22. 27 6
      src/views/curriculum/components/curriculumList/curriculumList_gym.vue
  23. 0 0
      src/views/curriculum/components/curriculumList/curriculumList_gyt.vue
  24. 0 2
      src/views/curriculum/components/curriculumList_gym/index.ts
  25. 0 2
      src/views/curriculum/components/curriculumList_gyt/index.ts
  26. 3 3
      src/views/curriculum/curriculum.vue
  27. 31 0
      src/views/curriculum/curriculumDetail.vue
  28. 340 0
      src/views/homePage/components/curriculum/curriculum_gym.vue
  29. 231 0
      src/views/homePage/components/curriculum/curriculum_gyt.vue
  30. 348 0
      src/views/homePage/homePage.vue
  31. 0 180
      src/views/homePage/homePage_gym.vue
  32. 0 181
      src/views/homePage/homePage_gyt.vue
  33. 2 0
      src/views/homePage/index.ts

+ 30 - 0
src/api/curriculum.api.ts

@@ -0,0 +1,30 @@
+import { httpAxios_gym, httpAxios_gyt } from "@/api/ApiInstance"
+
+/** 管乐迷 */
+
+// 首页课程
+export const queryLessonCourseware_gym = (type: string) => {
+   return httpAxios_gym.axioseRquest({
+      method: "post",
+      url: "/api-teacher/lessonCourseware/queryLessonCourseware",
+      data: {
+         query: {
+            subjectId: type,
+            page: 1,
+            rows: 9999
+         }
+      }
+   })
+}
+
+/**
+ * 管乐团
+ */
+
+// 获取课程详情
+export const getCourseScheduleDetail_gyt = (id: string) => {
+   return httpAxios_gyt.axioseRquest({
+      method: "get",
+      url: "/api-teacher/courseSchedule/detail/" + id
+   })
+}

+ 23 - 0
src/api/homePage.api.ts

@@ -0,0 +1,23 @@
+import { httpAxios_gym, httpAxios_gyt } from "@/api/ApiInstance"
+
+/** 管乐迷 */
+
+// 首页课程
+export const getRecentCourseSchedule_gym = (id?: string) => {
+   return httpAxios_gym.axioseRquest({
+      method: "post",
+      url: `/api-teacher/teacherCourseSchedule/getRecentCourseSchedule${id ? "?courseId=" + id : ""}`
+   })
+}
+
+/**
+ * 管乐团
+ */
+
+// 首页课程
+export const getRemind_gyt = () => {
+   return httpAxios_gyt.axioseRquest({
+      method: "post",
+      url: "/api-teacher/courseSchedule/remind"
+   })
+}

+ 6 - 6
src/config/menus.ts

@@ -3,9 +3,9 @@
 // 管乐团
 export const menus_gyt: menuType[] = [
    {
-      path: "/homePage_gyt",
-      component: "homePage_gyt",
-      title: "管乐团首页",
+      path: "/homePage",
+      component: "homePage",
+      title: "首页",
       icon: "",
       meta: {
          routeType: "layout"
@@ -47,9 +47,9 @@ export const menus_gyt: menuType[] = [
 // 管乐迷
 export const menus_gym: menuType[] = [
    {
-      path: "/homePage_gym",
-      component: "homePage_gym",
-      title: "管乐迷首页",
+      path: "/homePage",
+      component: "homePage",
+      title: "首页",
       icon: "",
       meta: {
          routeType: "layout"

+ 1 - 1
src/hooks/useDialogConfirm/dialogConfirm.vue

@@ -84,7 +84,7 @@ function ok() {
       display: flex;
       align-items: center;
       justify-content: center;
-      padding: 0 20px;
+      padding: 0 18px 0 22px;
       overflow: hidden;
       .text {
          font-size: 20px;

+ 0 - 0
src/img/curriculum/type.png → src/img/curriculum/Band.png


二进制
src/img/curriculum/DEMO.png


二进制
src/img/curriculum/LIVE.png


二进制
src/img/curriculum/PRACTICE.png


二进制
src/img/curriculum/Vip.png


二进制
src/img/curriculum/qd1.png


二进制
src/img/curriculum/qd2.png


二进制
src/img/curriculum/qt1.png


二进制
src/img/curriculum/qt2.png


二进制
src/img/curriculum/ts1.png


二进制
src/img/curriculum/ts2.png


二进制
src/img/curriculum/ts3.png


二进制
src/img/curriculum/xs.png


二进制
src/img/homePage/back.png


二进制
src/img/homePage/bg.png


二进制
src/img/homePage/bg1.png


+ 1 - 2
src/router/modules.ts

@@ -1,6 +1,5 @@
 export default {
-   homePage_gym: () => import("@/views/homePage/homePage_gym.vue"),
-   homePage_gyt: () => import("@/views/homePage/homePage_gyt.vue"),
+   homePage: () => import("@/views/homePage/homePage.vue"), // 首页
    cloudTextbooks: () => import("@/views/cloudTextbooks"), // 云教材
    coursewarePlay: () => import("@/views/coursewarePlay"), // 播放器
    curriculum: () => import("@/views/curriculum") // 课表

+ 27 - 6
src/views/curriculum/components/curriculumList_gym/curriculumList_gym.vue → src/views/curriculum/components/curriculumList/curriculumList_gym.vue

@@ -18,7 +18,7 @@
       <div class="curriculumName">
          <div class="leftCon">
             <img class="xxImg" src="@/img/curriculum/xx.png" />
-            <img class="typeImg" src="@/img/curriculum/type.png" />
+            <img class="typeImg" src="@/img/curriculum/Band.png" />
             <div class="className">
                <ellipsisScroll :title="'乐团课·单簧管进阶提高体验课'" />
             </div>
@@ -40,7 +40,7 @@
             </div>
             <div>上课学生:陈琪</div>
          </div>
-         <div class="operate">
+         <div class="operate" @click="handleClickDetail">
             <div>查看详情</div>
             <img class="jtImg" src="@/img/curriculum/jt.png" />
          </div>
@@ -60,7 +60,7 @@
       <div class="curriculumName">
          <div class="leftCon">
             <img class="xxImg" src="@/img/curriculum/xx.png" />
-            <img class="typeImg" src="@/img/curriculum/type.png" />
+            <img class="typeImg" src="@/img/curriculum/Band.png" />
             <div class="className">
                <ellipsisScroll :title="'乐团课·单簧管进阶提高体验课'" />
             </div>
@@ -102,7 +102,7 @@
       <div class="curriculumName">
          <div class="leftCon">
             <img class="xxImg" src="@/img/curriculum/xx.png" />
-            <img class="typeImg" src="@/img/curriculum/type.png" />
+            <img class="typeImg" src="@/img/curriculum/Band.png" />
             <div class="className">
                <ellipsisScroll :title="'乐团课·单簧管进阶提高体验课'" />
             </div>
@@ -144,7 +144,7 @@
       <div class="curriculumName">
          <div class="leftCon">
             <img class="xxImg" src="@/img/curriculum/xx.png" />
-            <img class="typeImg" src="@/img/curriculum/type.png" />
+            <img class="typeImg" src="@/img/curriculum/Band.png" />
             <div class="className">
                <ellipsisScroll :title="'乐团课·单簧管进阶提高体验课'" />
             </div>
@@ -174,7 +174,25 @@
    </div>
 </template>
 
-<script setup lang="ts"></script>
+<script setup lang="ts">
+import modalFrame from "@/plugin/modalFrame"
+import curriculumDetail from "../../curriculumDetail.vue"
+
+function handleClickDetail() {
+   //点击跳转详情
+   modalFrame({
+      template: curriculumDetail,
+      width: 989,
+      height: 760,
+      btnShow: [],
+      // modalData: {
+      //    //id
+      // },
+      maskClose: true,
+      className: "curriculumDetail"
+   })
+}
+</script>
 
 <style lang="scss" scoped>
 .curriculumList_gym {
@@ -292,6 +310,9 @@
          .adressBox {
             display: flex;
             align-items: center;
+            & > div:nth-child(1) {
+               flex-shrink: 0;
+            }
             .adress {
                max-width: 620px;
                overflow: hidden;

+ 0 - 0
src/views/curriculum/components/curriculumList_gyt/curriculumList_gyt.vue → src/views/curriculum/components/curriculumList/curriculumList_gyt.vue


+ 0 - 2
src/views/curriculum/components/curriculumList_gym/index.ts

@@ -1,2 +0,0 @@
-import curriculumList_gym from "./curriculumList_gym.vue"
-export default curriculumList_gym

+ 0 - 2
src/views/curriculum/components/curriculumList_gyt/index.ts

@@ -1,2 +0,0 @@
-import curriculumList_gyt from "./curriculumList_gyt.vue"
-export default curriculumList_gyt

+ 3 - 3
src/views/curriculum/curriculum.vue

@@ -10,7 +10,7 @@
             <div class="calendarCon"><myCalendar v-model="value" /></div>
             <div class="curriculumCon">
                <ElScrollbar class="listElScrollbar">
-                  <component :is="userStoreHook.roles === 'GYM' ? curriculumList_gyt : curriculumList_gym" />
+                  <component :is="userStoreHook.roles === 'GYM' ? curriculumList_gym : curriculumList_gyt" />
                </ElScrollbar>
             </div>
          </ElScrollbar>
@@ -24,8 +24,8 @@ import myCalendar from "@/components/myCalendar"
 import { ref, watchEffect } from "vue"
 import navContainer from "@/businessComponents/navContainer"
 import userStore from "@/store/modules/user"
-import curriculumList_gym from "./components/curriculumList_gym"
-import curriculumList_gyt from "./components/curriculumList_gyt"
+import curriculumList_gym from "./components/curriculumList/curriculumList_gym"
+import curriculumList_gyt from "./components/curriculumList/curriculumList_gyt"
 
 const userStoreHook = userStore()
 const navs = [

+ 31 - 0
src/views/curriculum/curriculumDetail.vue

@@ -0,0 +1,31 @@
+<!--
+* @FileDescription: 课程详情
+* @Author: 黄琪勇
+* @Date:2024-04-01 16:27:48
+-->
+<template>
+   <div class="curriculumDetail"></div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style lang="scss" scoped>
+.curriculumDetail {
+   width: 100%;
+   height: 100%;
+}
+</style>
+<style lang="scss">
+.h-modalFrame.curriculumDetail {
+   /* prettier-ignore */
+   --modalFrameTitHeight: 0PX;
+   .modalFrameBox {
+      background: linear-gradient(180deg, #ffdd5d 0%, #ffb93b 100%);
+      border-radius: 57px;
+      box-shadow: none;
+      .modalFrameTitle {
+         display: none;
+      }
+   }
+}
+</style>

+ 340 - 0
src/views/homePage/components/curriculum/curriculum_gym.vue

@@ -0,0 +1,340 @@
+<!--
+* @FileDescription: 管乐迷课表
+* @Author: 黄琪勇
+* @Date:2024-03-29 17:31:26
+-->
+<template>
+   <div class="curriculum_gym">
+      <div class="head">
+         <div class="timeBox">
+            <img class="timeImg" src="@/img/curriculum/sj.png" />
+            <div class="time">{{ classData.classDate && format(classData.classDate) }}</div>
+         </div>
+         <div class="operateBox">
+            <template v-if="classData.status === 'UNDERWAY' && !classData.coursewareDetailId">
+               <img class="dangerImg" src="@/img/curriculum/jg.png" />
+               <div class="operateBtn">配置课件</div>
+            </template>
+            <template v-else-if="classData.status === 'NOT_START'">
+               <div class="noStart">未开始</div>
+            </template>
+            <template v-else-if="classData.status === 'UNDERWAY'">
+               <div class="ing">进行中</div>
+            </template>
+            <template v-else>
+               <div class="end">已结束</div>
+            </template>
+         </div>
+      </div>
+      <div class="timeTitBox">
+         {{ classData.startClassTime && format(classData.startClassTime, "hh:ii") }}-{{
+            classData.endClassTime && format(classData.endClassTime, "hh:ii")
+         }}
+      </div>
+      <div class="classNameBox">
+         <img class="xxImg" :src="classData.teachMode === 'ONLINE' ? require('@/img/curriculum/xs.png') : require('@/img/curriculum/xx.png')" />
+         <img class="typeImg" :src="require(`@/img/curriculum/${classImgType[classData.type as keyof typeof classImgType]}.png`)" />
+         <div class="className">
+            <ellipsisScroll :title="`${classNameType[classData.type as keyof typeof classNameType]}·${classData.name}`" />
+         </div>
+      </div>
+      <div class="addressCon">
+         <div class="adressBox">
+            <div>上课地点:</div>
+            <div class="adress">
+               <ellipsisScroll :title="classData.teachMode === 'ONLINE' ? '网络教室' : classData.schoolName" />
+            </div>
+         </div>
+         <div class="adressBox">
+            <div>上课学生:</div>
+            <div class="adress">
+               <ellipsisScroll :title="classData.studentNames" />
+            </div>
+         </div>
+      </div>
+      <div class="stateBox">
+         <div>
+            <img
+               :src="
+                  classData.signInStatusEnum === 1
+                     ? require('@/img/curriculum/qd1.png')
+                     : classData.signInStatusEnum === 0
+                     ? require('@/img/curriculum/qd2.png')
+                     : require('@/img/curriculum/qd.png')
+               "
+            />
+            <div :class="[classData.signInStatusEnum === 1 ? 'signIn' : classData.signInStatusEnum === 0 && 'abnormalSignIn']">
+               {{ classData.signInStatusEnum === 1 ? "正常签到" : classData.signInStatusEnum === 0 ? "异常签到" : "未签到" }}
+            </div>
+         </div>
+         <div>
+            <img
+               :src="
+                  classData.signOutStatusEnum === 1
+                     ? require('@/img/curriculum/qt1.png')
+                     : classData.signOutStatusEnum === 0
+                     ? require('@/img/curriculum/qt2.png')
+                     : require('@/img/curriculum/qt.png')
+               "
+            />
+            <div :class="[classData.signOutStatusEnum === 1 ? 'signOut' : classData.signOutStatusEnum === 0 && 'abnormalSignOut']">
+               {{ classData.signOutStatusEnum === 1 ? "正常签退" : classData.signOutStatusEnum === 0 ? "异常签退" : "未签退" }}
+            </div>
+         </div>
+      </div>
+      <div class="btnCon">
+         <div class="btnDetail">查看详情</div>
+         <div class="btnGoClass" v-if="classData.status === 'UNDERWAY'" @click="handleStartClass(classData.id)">开始上课</div>
+      </div>
+   </div>
+</template>
+
+<script setup lang="ts">
+import { format } from "@/libs/tools"
+import { getRecentCourseSchedule_gym } from "@/api/homePage.api"
+import { httpAjaxErrMsg } from "@/plugin/httpAjax"
+import useDialogConfirm from "@/hooks/useDialogConfirm"
+
+defineProps<{
+   classData: Record<string, any>
+}>()
+
+enum classImgType { //Band:乐团课 vip:vip课 PRACTICE:网管课 DEMO:试听课 LIVE:直播课
+   SINGLE = "Band",
+   MIX = "Band",
+   HIGH = "Band",
+   COMPREHENSIVE = "Band",
+   ENLIGHTENMENT = "Band",
+   TRAINING = "Band",
+   TRAINING_SINGLE = "Band",
+   TRAINING_MIX = "Band",
+   CLASSROOM = "Band",
+   HIGH_ONLINE = "Band",
+   MUSIC_NETWORK = "Band",
+   VIP = "Vip",
+   COMM = "Vip",
+   PRACTICE = "PRACTICE",
+   DEMO = "DEMO",
+   LIVE = "LIVE"
+}
+enum classNameType { //Band:乐团课 vip:vip课 PRACTICE:网管课 DEMO:试听课 LIVE:直播课
+   SINGLE = "乐团课",
+   MIX = "乐团课",
+   HIGH = "乐团课",
+   COMPREHENSIVE = "乐团课",
+   ENLIGHTENMENT = "乐团课",
+   TRAINING = "乐团课",
+   TRAINING_SINGLE = "乐团课",
+   TRAINING_MIX = "乐团课",
+   CLASSROOM = "乐团课",
+   HIGH_ONLINE = "乐团课",
+   MUSIC_NETWORK = "乐团课",
+   VIP = "VIP课",
+   COMM = "VIP课",
+   PRACTICE = "网管课",
+   DEMO = "试听课",
+   LIVE = "直播课"
+}
+
+function handleStartClass(id: string) {
+   httpAjaxErrMsg(getRecentCourseSchedule_gym, id).then(res => {
+      if (res.code === 200) {
+         const { signInStatusEnum, isCallNames, coursewareDetailId, startClassTime, endClassTime } = res.data
+         if (signInStatusEnum === 3) {
+            useDialogConfirm({
+               headImg: require("@/img/curriculum/ts2.png"),
+               text: `您当前${format(startClassTime, "hh:ii")}-${format(endClassTime, "hh:ii")}的课程暂未签到,为避免考勤异常,请到APP进行签到。`,
+               btnShow: [true]
+            })
+            return
+         }
+         if (!isCallNames) {
+            useDialogConfirm({
+               headImg: require("@/img/curriculum/ts1.png"),
+               text: `您当前${format(startClassTime, "hh:ii")}-${format(endClassTime, "hh:ii")}的课程暂未点名,请到APP进行点名。`,
+               btnShow: [true]
+            })
+            return
+         }
+         if (!coursewareDetailId) {
+            useDialogConfirm({
+               headImg: require("@/img/curriculum/ts3.png"),
+               text: `该课程未配置课件,请配置课件。`,
+               btnShow: [true]
+            })
+            return
+         }
+      }
+   })
+}
+</script>
+
+<style lang="scss" scoped>
+.curriculum_gym {
+   padding: 0 30px;
+   .head {
+      padding-top: 25px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .timeBox {
+         display: flex;
+         align-items: center;
+         .timeImg {
+            width: 28px;
+            height: 28px;
+         }
+         .time {
+            margin-left: 8px;
+            font-weight: 500;
+            font-size: 24px;
+            color: #777777;
+         }
+      }
+      .operateBox {
+         display: flex;
+         align-items: center;
+         .dangerImg {
+            width: 24px;
+            height: 24px;
+         }
+         .operateBtn {
+            margin-left: 10px;
+            font-weight: 500;
+            font-size: 24px;
+            color: #f44541;
+            cursor: pointer;
+            &:hover {
+               opacity: $opacity-hover;
+            }
+         }
+         .noStart {
+            font-weight: 500;
+            font-size: 24px;
+            color: #777777;
+         }
+         .ing {
+            font-weight: 500;
+            font-size: 24px;
+            color: #f67146;
+         }
+         .end {
+            font-weight: 500;
+            font-size: 20px;
+            color: #aaaaaa;
+         }
+      }
+   }
+   .timeTitBox {
+      text-align: center;
+      margin-top: 68px;
+      font-family: DINAlternate, DINAlternate;
+      font-weight: bold;
+      font-size: 52px;
+      color: #f67146;
+   }
+   .classNameBox {
+      margin-top: 46px;
+      width: 100%;
+      display: flex;
+      align-items: center;
+      .xxImg {
+         flex-shrink: 0;
+         width: 46px;
+         height: 24px;
+      }
+      .typeImg {
+         flex-shrink: 0;
+         margin-left: 6px;
+         width: 55px;
+         height: 24px;
+      }
+      .className {
+         flex-grow: 1;
+         overflow: hidden;
+         margin-left: 6px;
+         font-weight: 600;
+         font-size: 24px;
+         color: #333333;
+      }
+   }
+   .addressCon {
+      margin-top: 16px;
+      width: 100%;
+      & > div {
+         font-weight: 500;
+         font-size: 18px;
+         color: #777777;
+      }
+      & > div:nth-child(2) {
+         margin-top: 14px;
+      }
+      .adressBox {
+         display: flex;
+         align-items: center;
+         & > div:nth-child(1) {
+            flex-shrink: 0;
+         }
+         .adress {
+            overflow: hidden;
+         }
+      }
+   }
+   .stateBox {
+      margin-top: 48px;
+      display: flex;
+      justify-content: space-between;
+      & > div {
+         width: 216px;
+         height: 65px;
+         background: #f2f2f2;
+         border-radius: 18px;
+         display: flex;
+         justify-content: center;
+         align-items: center;
+         & > img {
+            width: 27px;
+            height: 27px;
+         }
+         & > div {
+            margin-left: 6px;
+            font-weight: 500;
+            font-size: 22px;
+            color: #aaaaaa;
+            &.signIn,
+            &.signOut {
+               color: #01c199;
+            }
+            &.abnormalSignIn,
+            &.abnormalSignOut {
+               color: #ff0000;
+            }
+         }
+      }
+   }
+   .btnCon {
+      margin-top: 58px;
+      display: flex;
+      .btnGoClass,
+      .btnDetail {
+         flex-grow: 1;
+         height: 74px;
+         background: linear-gradient(180deg, #ffffff 0%, #ffdbc1 100%);
+         box-shadow: 4px 5px 0px 0px rgba(236, 102, 52, 0.45), inset 0px -7px 3px 0px rgba(254, 163, 138, 0.46);
+         border-radius: 37px;
+         font-weight: 500;
+         font-size: 24px;
+         color: #f67146;
+         line-height: 74px;
+         text-align: center;
+         cursor: pointer;
+         &:hover {
+            opacity: $opacity-hover;
+         }
+      }
+      .btnGoClass {
+         margin-left: 20px;
+      }
+   }
+}
+</style>

+ 231 - 0
src/views/homePage/components/curriculum/curriculum_gyt.vue

@@ -0,0 +1,231 @@
+<!--
+* @FileDescription: 管乐团课表
+* @Author: 黄琪勇
+* @Date:2024-03-29 17:31:26
+-->
+<template>
+   <div class="curriculum_gyt">
+      <div class="head">
+         <div class="timeBox">
+            <img class="timeImg" src="@/img/curriculum/sj.png" />
+            <div class="time">{{ classData.classDate && format(classData.classDate) }}</div>
+         </div>
+         <div class="operateBox">
+            <template v-if="classData.status === 'ING' && !classData.lessonCoursewareId">
+               <img class="dangerImg" src="@/img/curriculum/jg.png" />
+               <div class="operateBtn">配置课件</div>
+            </template>
+            <template v-else-if="classData.status === 'NOT_START'">
+               <div class="noStart">未开始</div>
+            </template>
+            <template v-else-if="classData.status === 'ING'">
+               <div class="ing">进行中</div>
+            </template>
+            <template v-else>
+               <div class="end">已结束</div>
+            </template>
+         </div>
+      </div>
+      <div class="timeTitBox">
+         {{ classData.startTime && format(classData.startTime, "hh:ii") }}-{{ classData.endTime && format(classData.endTime, "hh:ii") }}
+      </div>
+      <div class="nameTitBox">
+         <ellipsisScroll :title="`${classData.className}-${classData.teacherName}`" />
+      </div>
+      <div class="schoolTitBox">
+         <ellipsisScroll :title="classData.orchestraName" />
+      </div>
+      <div class="stateBox">
+         <div>
+            <img :src="classData.signIn ? require('@/img/curriculum/qd1.png') : require('@/img/curriculum/qd.png')" />
+            <div :class="{ signIn: classData.signIn }">{{ classData.signIn ? "正常签到" : "未签到" }}</div>
+         </div>
+         <div>
+            <img :src="classData.signOut ? require('@/img/curriculum/qt1.png') : require('@/img/curriculum/qt.png')" />
+            <div :class="{ signOut: classData.signOut }">{{ classData.signOut ? "正常签退" : "未签退" }}</div>
+         </div>
+      </div>
+      <div class="btnCon">
+         <div class="btnDetail">查看详情</div>
+         <div class="btnGoClass" v-if="classData.status === 'ING'" @click="handleStartClass(classData.id)">开始上课</div>
+      </div>
+   </div>
+</template>
+
+<script setup lang="ts">
+import { format } from "@/libs/tools"
+import { getCourseScheduleDetail_gyt } from "@/api/curriculum.api"
+import { httpAjaxErrMsg } from "@/plugin/httpAjax"
+import useDialogConfirm from "@/hooks/useDialogConfirm"
+
+defineProps<{
+   classData: Record<string, any>
+}>()
+
+function handleStartClass(id: string) {
+   httpAjaxErrMsg(getCourseScheduleDetail_gyt, id).then(res => {
+      if (res.code === 200) {
+         const { signIn, rollCall, lessonCoursewareId, startTime, endTime } = res.data
+         if (!signIn) {
+            useDialogConfirm({
+               headImg: require("@/img/curriculum/ts2.png"),
+               text: `您当前${format(startTime, "hh:ii")}-${format(endTime, "hh:ii")}的课程暂未签到,为避免考勤异常,请到APP进行签到。`,
+               btnShow: [true]
+            })
+            return
+         }
+         if (!rollCall) {
+            useDialogConfirm({
+               headImg: require("@/img/curriculum/ts1.png"),
+               text: `您当前${format(startTime, "hh:ii")}-${format(endTime, "hh:ii")}的课程暂未点名,请到APP进行点名。`,
+               btnShow: [true]
+            })
+            return
+         }
+         if (!lessonCoursewareId) {
+            useDialogConfirm({
+               headImg: require("@/img/curriculum/ts3.png"),
+               text: `该课程未配置课件,请配置课件。`,
+               btnShow: [true]
+            })
+            return
+         }
+      }
+   })
+}
+</script>
+
+<style lang="scss" scoped>
+.curriculum_gyt {
+   padding: 0 30px;
+   .head {
+      padding-top: 25px;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      .timeBox {
+         display: flex;
+         align-items: center;
+         .timeImg {
+            width: 28px;
+            height: 28px;
+         }
+         .time {
+            margin-left: 8px;
+            font-weight: 500;
+            font-size: 24px;
+            color: #777777;
+         }
+      }
+      .operateBox {
+         display: flex;
+         align-items: center;
+         .dangerImg {
+            width: 24px;
+            height: 24px;
+         }
+         .operateBtn {
+            margin-left: 10px;
+            font-weight: 500;
+            font-size: 24px;
+            color: #f44541;
+            cursor: pointer;
+            &:hover {
+               opacity: $opacity-hover;
+            }
+         }
+         .noStart {
+            font-weight: 500;
+            font-size: 24px;
+            color: #777777;
+         }
+         .ing {
+            font-weight: 500;
+            font-size: 24px;
+            color: #f67146;
+         }
+         .end {
+            font-weight: 500;
+            font-size: 20px;
+            color: #aaaaaa;
+         }
+      }
+   }
+   .timeTitBox {
+      text-align: center;
+      margin-top: 68px;
+      font-family: DINAlternate, DINAlternate;
+      font-weight: bold;
+      font-size: 52px;
+      color: #f67146;
+   }
+   .nameTitBox {
+      margin-top: 34px;
+      font-weight: 600;
+      font-size: 25px;
+      color: #333333;
+      text-align: center;
+      overflow: hidden;
+   }
+   .schoolTitBox {
+      margin-top: 32px;
+      font-weight: 500;
+      font-size: 22px;
+      color: #777777;
+      text-align: center;
+      overflow: hidden;
+   }
+   .stateBox {
+      margin-top: 76px;
+      display: flex;
+      justify-content: space-between;
+      & > div {
+         width: 216px;
+         height: 65px;
+         background: #f2f2f2;
+         border-radius: 18px;
+         display: flex;
+         justify-content: center;
+         align-items: center;
+         & > img {
+            width: 27px;
+            height: 27px;
+         }
+         & > div {
+            margin-left: 6px;
+            font-weight: 500;
+            font-size: 22px;
+            color: #aaaaaa;
+            &.signIn,
+            &.signOut {
+               color: #01c199;
+            }
+         }
+      }
+   }
+   .btnCon {
+      margin-top: 58px;
+      display: flex;
+      .btnGoClass,
+      .btnDetail {
+         flex-grow: 1;
+         height: 74px;
+         background: linear-gradient(180deg, #ffffff 0%, #ffdbc1 100%);
+         box-shadow: 4px 5px 0px 0px rgba(236, 102, 52, 0.45), inset 0px -7px 3px 0px rgba(254, 163, 138, 0.46);
+         border-radius: 37px;
+         font-weight: 500;
+         font-size: 24px;
+         color: #f67146;
+         line-height: 74px;
+         text-align: center;
+         cursor: pointer;
+         &:hover {
+            opacity: $opacity-hover;
+         }
+      }
+      .btnGoClass {
+         margin-left: 20px;
+      }
+   }
+}
+</style>

+ 348 - 0
src/views/homePage/homePage.vue

@@ -0,0 +1,348 @@
+<!--
+* @FileDescription: 首页
+* @Author: 黄琪勇
+* @Date:2024-03-29 17:20:39
+-->
+<template>
+   <navContainer class="homePageNav" :headImg="headImg" :navs="navs">
+      <div class="homePage">
+         <ElScrollbar class="elScrollbar">
+            <div class="classTypes">
+               <div
+                  class="classType"
+                  v-for="item in userStoreHook.roles === 'GYM' ? classTypes_gym : classTypes_gyt"
+                  :key="item.name"
+                  @click="handleRouter(item.url)"
+               >
+                  <img :src="item.img" />
+                  <div>{{ item.name }}</div>
+               </div>
+            </div>
+            <div class="courseBoard" :class="{ isEmpty: isEmptyClassData && !classDataLoading }">
+               <div class="details">
+                  <div class="head">
+                     <div class="leftCon">
+                        <div class="line"></div>
+                        <div class="title">下次课程</div>
+                     </div>
+                     <img class="rightRouter" @click="handleRouter('/curriculum')" src="@/img/homePage/back.png" />
+                  </div>
+                  <el-skeleton class="elSkeleton" :loading="classDataLoading">
+                     <template #template>
+                        <el-skeleton-item class="elSkeletonItem" variant="p" />
+                        <el-skeleton-item class="elSkeletonItem" variant="p" />
+                        <el-skeleton-item class="elSkeletonItem" variant="h1" />
+                        <el-skeleton-item class="elSkeletonItem" variant="h1" />
+                        <div class="elSkeletonBtnCon">
+                           <el-skeleton-item class="elSkeletonItem" variant="button" />
+                           <el-skeleton-item class="elSkeletonItem" variant="button" />
+                        </div>
+                        <el-skeleton-item class="elSkeletonItem" variant="button" />
+                     </template>
+                     <template #default>
+                        <component
+                           v-if="!isEmptyClassData"
+                           :classData="classData"
+                           :is="userStoreHook.roles === 'GYM' ? curriculum_gym : curriculum_gyt"
+                        />
+                        <el-empty v-else class="empty" :image="require('@/img/layout/empty1.png')" description="您还没有待上课程哦~" />
+                     </template>
+                  </el-skeleton>
+               </div>
+            </div>
+         </ElScrollbar>
+      </div>
+   </navContainer>
+</template>
+<script setup lang="ts">
+import navContainer from "@/businessComponents/navContainer"
+import { useRouter } from "vue-router"
+import { ref, computed } from "vue"
+import useDialogConfirm from "@/hooks/useDialogConfirm"
+import userStore from "@/store/modules/user"
+import curriculum_gym from "./components/curriculum/curriculum_gym.vue"
+import curriculum_gyt from "./components/curriculum/curriculum_gyt.vue"
+import { getRemind_gyt, getRecentCourseSchedule_gym } from "@/api/homePage.api"
+import { httpAjax } from "@/plugin/httpAjax"
+
+const userStoreHook = userStore()
+const router = useRouter()
+
+const headImg = {
+   img: require("@/img/homePage/home.png")
+}
+const navs = [
+   {
+      name: "主页"
+   }
+]
+const classTypes_gym = [
+   {
+      img: require("@/img/homePage/kb.png"),
+      name: "课表",
+      url: "/curriculum"
+   },
+   {
+      img: require("@/img/homePage/xl.png"),
+      name: "训练",
+      url: ""
+   },
+   {
+      img: require("@/img/homePage/jdcp.png"),
+      name: "进度测评",
+      url: ""
+   },
+   {
+      img: require("@/img/homePage/xltj.png"),
+      name: "训练统计",
+      url: ""
+   },
+   {
+      img: require("@/img/homePage/yjl.png"),
+      name: "云教练",
+      url: ""
+   },
+   {
+      img: require("@/img/homePage/yjc.png"),
+      name: "云教程",
+      url: "/cloudTextbooks"
+   }
+]
+const classTypes_gyt = [
+   {
+      img: require("@/img/homePage/kb.png"),
+      name: "课表",
+      url: "/curriculum"
+   },
+   {
+      img: require("@/img/homePage/xl.png"),
+      name: "课后作业",
+      url: ""
+   },
+   {
+      img: require("@/img/homePage/jdzc.png"),
+      name: "阶段自测",
+      url: ""
+   },
+   {
+      img: require("@/img/homePage/xltj.png"),
+      name: "练习情况",
+      url: ""
+   },
+   {
+      img: require("@/img/homePage/yjl.png"),
+      name: "云练习",
+      url: ""
+   },
+   {
+      img: require("@/img/homePage/yjc.png"),
+      name: "云教材",
+      url: "/cloudTextbooks"
+   }
+]
+
+const classData = ref<Record<string, any>>({})
+const classDataLoading = ref(true)
+const isEmptyClassData = computed(() => {
+   return !Object.keys(classData.value).length
+})
+handleClassData()
+function handleClassData() {
+   if (userStoreHook.roles === "GYM") {
+      classDataLoading.value = true
+      httpAjax(getRecentCourseSchedule_gym).then(res => {
+         classDataLoading.value = false
+         if (res.code === 200) {
+            classData.value = res.data || {}
+         }
+      })
+   } else {
+      classDataLoading.value = true
+      httpAjax(getRemind_gyt).then(res => {
+         classDataLoading.value = false
+         if (res.code === 200) {
+            classData.value = res.data || {}
+         }
+      })
+   }
+}
+
+function handleRouter(url?: string) {
+   url
+      ? router.push(url)
+      : useDialogConfirm({
+           headImg: require("@/img/homePage/ts.png"),
+           text: "该功能暂未开放,请敬请期待哦~",
+           btnShow: [true]
+        })
+}
+</script>
+<style lang="scss" scoped>
+.homePageNav.navContainer {
+   &:deep(.navCon) {
+      .navImg {
+         margin-left: 50px;
+         > img {
+            width: 91px;
+            height: 92px;
+            top: 70%;
+         }
+      }
+      .nav {
+         font-size: 28px;
+         font-family: AlimamaFangYuanTiVF, AlimamaFangYuanTiVF;
+         &:last-child {
+            margin-right: 30px;
+         }
+      }
+   }
+}
+.homePage {
+   width: 100%;
+   height: 100%;
+   & > :deep(.elScrollbar) {
+      .el-scrollbar__view {
+         width: 100%;
+         display: flex;
+         padding: 50px 50px 0;
+      }
+      .el-scrollbar__wrap {
+         overflow-x: hidden;
+      }
+      .el-scrollbar__bar.is-vertical {
+         width: 4px;
+         right: 0;
+      }
+   }
+   .classTypes {
+      flex-grow: 1;
+      display: flex;
+      flex-wrap: wrap;
+      justify-content: space-between;
+      height: 729px;
+      align-content: space-between;
+      .classType {
+         background: #feffff;
+         box-shadow: 0px 2px 14px 0 #f1e3cc;
+         border-radius: 34px;
+         width: 360px;
+         height: 350px;
+         display: flex;
+         justify-content: center;
+         align-items: center;
+         flex-direction: column;
+         cursor: pointer;
+         padding: 44px 53px;
+         &:hover {
+            transform: scale(1.02);
+            box-shadow: 0px 2px 14px 0px #e4d7c2;
+         }
+         > div {
+            margin-top: 10px;
+            font-family: AlimamaFangYuanTiVF, AlimamaFangYuanTiVF;
+            font-weight: bold;
+            font-size: 28px;
+            color: #393939;
+         }
+         > img {
+            width: 100%;
+         }
+      }
+   }
+   .courseBoard {
+      flex-shrink: 0;
+      margin-left: 50px;
+      margin-top: -35px;
+      width: 572px;
+      height: 764px;
+      background: url("@/img/homePage/bg1.png") no-repeat;
+      background-size: 100% 100%;
+      position: relative;
+      &.isEmpty {
+         background: url("@/img/homePage/bg.png") no-repeat;
+         background-size: 100% 100%;
+      }
+      .details {
+         width: 100%;
+         position: absolute;
+         top: 88px;
+         left: 0;
+         padding: 0 30px;
+         .head {
+            height: 81px;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 0 30px;
+            .leftCon {
+               display: flex;
+               align-items: center;
+               .line {
+                  width: 8px;
+                  height: 28px;
+                  background: linear-gradient(180deg, #ffcb35 0%, #fea60a 100%), #ff6a67;
+                  border-radius: 7px;
+               }
+               .title {
+                  margin-left: 12px;
+                  font-family: AlimamaFangYuanTiVF, AlimamaFangYuanTiVF;
+                  font-weight: bold;
+                  font-size: 28px;
+                  color: #994d1c;
+               }
+            }
+            .rightRouter {
+               width: 38px;
+               height: 38px;
+               cursor: pointer;
+            }
+         }
+         .elSkeleton {
+            padding: 0 30px;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            > .elSkeletonItem {
+               &:nth-child(1) {
+                  margin-top: 25px;
+                  height: 34px;
+               }
+               &:nth-child(2) {
+                  width: 50%;
+                  margin-top: 58px;
+                  height: 60px;
+               }
+               &:nth-child(3) {
+                  margin-top: 34px;
+               }
+               &:nth-child(4) {
+                  margin-top: 34px;
+               }
+               &:nth-child(6) {
+                  width: 100%;
+                  height: 74px;
+                  margin-top: 58px;
+               }
+            }
+            .elSkeletonBtnCon {
+               width: 100%;
+               margin-top: 76px;
+               display: flex;
+               justify-content: space-between;
+               > .elSkeletonItem {
+                  width: 216px;
+                  height: 65px;
+               }
+            }
+         }
+         :deep(.empty) {
+            margin-top: 114px;
+            padding: 0;
+            .el-empty__image {
+               width: 360px;
+            }
+         }
+      }
+   }
+}
+</style>

+ 0 - 180
src/views/homePage/homePage_gym.vue

@@ -1,180 +0,0 @@
-<!--
-* @FileDescription: 管乐迷首页
-* @Author: 黄琪勇
-* @Date:2024-03-20 17:26:35
--->
-<template>
-   <navContainer class="homePageNav" :headImg="headImg" :navs="navs">
-      <div class="homePage">
-         <ElScrollbar class="elScrollbar">
-            <div class="classTypes">
-               <div class="classType" v-for="item in classTypes" :key="item.name" @click="handleRouter(item.url)">
-                  <img :src="item.img" />
-                  <div>{{ item.name }}</div>
-               </div>
-            </div>
-            <div class="courseBoard">
-               <div class="details">
-                  <el-empty class="empty" :image="require('@/img/layout/empty1.png')" description="您还没有待上课程哦~" />
-               </div>
-            </div>
-         </ElScrollbar>
-      </div>
-   </navContainer>
-</template>
-
-<script setup lang="ts">
-import navContainer from "@/businessComponents/navContainer"
-import { useRouter } from "vue-router"
-import useDialogConfirm from "@/hooks/useDialogConfirm"
-
-const router = useRouter()
-
-const headImg = {
-   img: require("@/img/homePage/home.png")
-}
-const navs = [
-   {
-      name: "主页"
-   }
-]
-const classTypes = [
-   {
-      img: require("@/img/homePage/kb.png"),
-      name: "课表",
-      url: "/curriculum"
-   },
-   {
-      img: require("@/img/homePage/xl.png"),
-      name: "训练",
-      url: ""
-   },
-   {
-      img: require("@/img/homePage/jdcp.png"),
-      name: "进度测评",
-      url: ""
-   },
-   {
-      img: require("@/img/homePage/xltj.png"),
-      name: "训练统计",
-      url: ""
-   },
-   {
-      img: require("@/img/homePage/yjl.png"),
-      name: "云教练",
-      url: ""
-   },
-   {
-      img: require("@/img/homePage/yjc.png"),
-      name: "云教程",
-      url: "/cloudTextbooks"
-   }
-]
-
-function handleRouter(url?: string) {
-   url
-      ? router.push(url)
-      : useDialogConfirm({
-           headImg: require("@/img/homePage/ts.png"),
-           text: "该功能暂未开放,请敬请期待哦~",
-           btnShow: [true]
-        })
-}
-</script>
-<style lang="scss" scoped>
-.homePageNav.navContainer {
-   &:deep(.navCon) {
-      .navImg {
-         margin-left: 50px;
-         > img {
-            width: 91px;
-            height: 92px;
-            top: 70%;
-         }
-      }
-      .nav {
-         font-size: 28px;
-         font-family: AlimamaFangYuanTiVF, AlimamaFangYuanTiVF;
-         &:last-child {
-            margin-right: 30px;
-         }
-      }
-   }
-}
-.homePage {
-   width: 100%;
-   height: 100%;
-   & > :deep(.elScrollbar) {
-      .el-scrollbar__view {
-         width: 100%;
-         display: flex;
-         padding: 50px 50px 0;
-      }
-      .el-scrollbar__wrap {
-         overflow-x: hidden;
-      }
-      .el-scrollbar__bar.is-vertical {
-         width: 4px;
-         right: 0;
-      }
-   }
-   .classTypes {
-      flex-grow: 1;
-      display: flex;
-      flex-wrap: wrap;
-      justify-content: space-between;
-      height: 729px;
-      align-content: space-between;
-      .classType {
-         background: #feffff;
-         box-shadow: 0px 2px 14px 0 #f1e3cc;
-         border-radius: 34px;
-         width: 360px;
-         height: 350px;
-         display: flex;
-         justify-content: center;
-         align-items: center;
-         flex-direction: column;
-         cursor: pointer;
-         padding: 44px 53px;
-         &:hover {
-            transform: scale(1.02);
-            box-shadow: 0px 2px 14px 0px #e4d7c2;
-         }
-         > div {
-            margin-top: 10px;
-            font-family: AlimamaFangYuanTiVF, AlimamaFangYuanTiVF;
-            font-weight: bold;
-            font-size: 28px;
-            color: #393939;
-         }
-         > img {
-            width: 100%;
-         }
-      }
-   }
-   .courseBoard {
-      flex-shrink: 0;
-      margin-left: 50px;
-      margin-top: -35px;
-      width: 572px;
-      height: 764px;
-      background: url("@/img/homePage/bg.png") no-repeat;
-      background-size: 100% 100%;
-      position: relative;
-      .details {
-         width: 100%;
-         position: absolute;
-         display: flex;
-         justify-content: center;
-         align-items: center;
-         top: 248px;
-         :deep(.empty) {
-            .el-empty__image {
-               width: 360px;
-            }
-         }
-      }
-   }
-}
-</style>

+ 0 - 181
src/views/homePage/homePage_gyt.vue

@@ -1,181 +0,0 @@
-<!--
-* @FileDescription: 管乐迷首页
-* @Author: 黄琪勇
-* @Date:2024-03-20 17:26:35
--->
-<template>
-   <navContainer class="homePageNav" :headImg="headImg" :navs="navs">
-      <div class="homePage">
-         <ElScrollbar class="elScrollbar">
-            <div class="classTypes">
-               <div class="classType" v-for="item in classTypes" :key="item.name" @click="handleRouter(item.url)">
-                  <img :src="item.img" />
-                  <div>{{ item.name }}</div>
-               </div>
-            </div>
-            <div class="courseBoard">
-               <div class="details">
-                  <el-empty class="empty" :image="require('@/img/layout/empty1.png')" description="您还没有待上课程哦~" />
-               </div>
-            </div>
-         </ElScrollbar>
-      </div>
-   </navContainer>
-</template>
-
-<script setup lang="ts">
-import navContainer from "@/businessComponents/navContainer"
-import { useRouter } from "vue-router"
-import useDialogConfirm from "@/hooks/useDialogConfirm"
-
-const router = useRouter()
-
-const headImg = {
-   img: require("@/img/homePage/home.png")
-}
-const navs = [
-   {
-      name: "主页"
-   }
-]
-const classTypes = [
-   {
-      img: require("@/img/homePage/kb.png"),
-      name: "课表",
-      url: "/curriculum"
-   },
-   {
-      img: require("@/img/homePage/xl.png"),
-      name: "课后作业",
-      url: ""
-   },
-   {
-      img: require("@/img/homePage/jdzc.png"),
-      name: "阶段自测",
-      url: ""
-   },
-   {
-      img: require("@/img/homePage/xltj.png"),
-      name: "练习情况",
-      url: ""
-   },
-   {
-      img: require("@/img/homePage/yjl.png"),
-      name: "云练习",
-      url: ""
-   },
-   {
-      img: require("@/img/homePage/yjc.png"),
-      name: "云教材",
-      url: "/cloudTextbooks"
-   }
-]
-
-function handleRouter(url?: string) {
-   url
-      ? router.push(url)
-      : useDialogConfirm({
-           headImg: require("@/img/homePage/ts.png"),
-           text: "该功能暂未开放,请敬请期待哦~",
-           btnShow: [true]
-        })
-}
-</script>
-
-<style lang="scss" scoped>
-.homePageNav.navContainer {
-   &:deep(.navCon) {
-      .navImg {
-         margin-left: 50px;
-         > img {
-            width: 91px;
-            height: 92px;
-            top: 70%;
-         }
-      }
-      .nav {
-         font-size: 28px;
-         font-family: AlimamaFangYuanTiVF, AlimamaFangYuanTiVF;
-         &:last-child {
-            margin-right: 30px;
-         }
-      }
-   }
-}
-.homePage {
-   width: 100%;
-   height: 100%;
-   & > :deep(.elScrollbar) {
-      .el-scrollbar__view {
-         width: 100%;
-         display: flex;
-         padding: 50px 50px 0;
-      }
-      .el-scrollbar__wrap {
-         overflow-x: hidden;
-      }
-      .el-scrollbar__bar.is-vertical {
-         width: 4px;
-         right: 0;
-      }
-   }
-   .classTypes {
-      flex-grow: 1;
-      display: flex;
-      flex-wrap: wrap;
-      justify-content: space-between;
-      height: 729px;
-      align-content: space-between;
-      .classType {
-         background: #feffff;
-         box-shadow: 0px 2px 14px 0 #f1e3cc;
-         border-radius: 34px;
-         width: 360px;
-         height: 350px;
-         display: flex;
-         justify-content: center;
-         align-items: center;
-         flex-direction: column;
-         cursor: pointer;
-         padding: 44px 53px;
-         &:hover {
-            transform: scale(1.02);
-            box-shadow: 0px 2px 14px 0px #e4d7c2;
-         }
-         > div {
-            margin-top: 10px;
-            font-family: AlimamaFangYuanTiVF, AlimamaFangYuanTiVF;
-            font-weight: bold;
-            font-size: 28px;
-            color: #393939;
-         }
-         > img {
-            width: 100%;
-         }
-      }
-   }
-   .courseBoard {
-      flex-shrink: 0;
-      margin-left: 50px;
-      margin-top: -35px;
-      width: 572px;
-      height: 764px;
-      background: url("@/img/homePage/bg.png") no-repeat;
-      background-size: 100% 100%;
-      position: relative;
-      .details {
-         width: 100%;
-         position: absolute;
-         display: flex;
-         justify-content: center;
-         align-items: center;
-         top: 248px;
-         :deep(.empty) {
-            .el-empty__image {
-               width: 360px;
-            }
-         }
-      }
-   }
-}
-</style>

+ 2 - 0
src/views/homePage/index.ts

@@ -0,0 +1,2 @@
+import homePage from "./homePage.vue"
+export default homePage