林旭祥 8 kuukautta sitten
vanhempi
commit
d2e258ce33

+ 10 - 1
src/api/module/common.ts

@@ -58,7 +58,7 @@ export default {
     });
   },
 
-  //获取测试数据
+  //获取测试数据列表
   reportList: (data: any) => {
     return req({
       url: '/report/index',
@@ -67,6 +67,15 @@ export default {
     });
   },
 
+  //获取测试数据明细
+  reportDetails: (data: any) => {
+    return req({
+      url: '/exam/search',
+      method: 'get',
+      data: data
+    });
+  },
+
   //获取工作站列表
   allExams: (data: any) => {
     return req({

BIN
src/assets/images/ranking/btn-left.png


BIN
src/assets/images/ranking/btn-right.png


+ 1 - 1
src/components/FaceWindow/index.vue

@@ -105,7 +105,7 @@ defineExpose({
   .confirmDiaWindow {
     width: 23.5%;
     height: 43.4%;
-    border-radius: 29px;
+    border-radius: 1.6rem;
     opacity: 1;
     background: radial-gradient(122% 126% at 97% 6%, #35FFC6 0%, #00FFE8 100%);
     text-align: center;

+ 440 - 0
src/components/ReportWindow/index.vue

@@ -0,0 +1,440 @@
+<template>
+  <transition :enter-active-class="proxy?.animate.mask.enter" :leave-active-class="proxy?.animate.mask.leave">
+    <div class="mask" v-if="reportWindow.show"></div>
+  </transition>
+  <transition :enter-active-class="proxy?.animate.dialog.enter" :leave-active-class="proxy?.animate.dialog.leave">
+    <div class="reportWindow" v-if="reportWindow.show" @click.self="close">
+      <div class="box">
+        <div class="left">
+          <div class="left-top">
+            <div class="left-top-center">
+              <div class="pic" v-if="faceCheckStu.face_pic || faceCheckStu.logo_url"> <img
+                  :src="faceCheckStu.face_pic || faceCheckStu.logo_url" /></div>
+              <div class="pic" v-else>
+                <img src="@/assets/images/test/profilePicture.png" />
+              </div>
+              <div class="name">
+                {{ faceCheckStu.student_name }}
+              </div>
+              <div class="className" v-if="faceCheckStu.class_name">{{ faceCheckStu.class_name }}</div>
+            </div>
+          </div>
+          <div class="left-bottom">
+            <div class="left-bottom-title">测试结果</div>
+            <div class="left-bottom-content">
+            </div>
+          </div>
+        </div>
+        <div class="right">
+          <div class="right-top">
+            <div class="btn">
+              <div class="li" :class="{ 'select': currentTab == 1 }" @click="getChoose(1)">
+                <div>视频</div>
+              </div>
+              <div class="li" :class="{ 'select': currentTab == 2 }" @click="getChoose(2)">
+                <div>图片</div>
+              </div>
+            </div>
+            <div class="close" @click="close"></div>
+          </div>
+          <div class="content">
+            <div class="video" v-show="currentTab == 1 ? true : false">
+              <!--视频开始-->
+              <video v-for="(item, index) in reportDetails.video_urls" :key="index"
+                style="width: 100%; object-fit: fill" :src="item"
+                :poster="item?.replace('  ', '') + '?x-oss-process=video/snapshot,t_100,f_jpg,w_0,h_0,ar_auto'"
+                controls>
+                您的浏览器不支持 video 标签。
+              </video>
+              <!--视频结束-->
+            </div>
+            <div class="pic" v-show="currentTab == 2 ? true : false">
+              <!--图片开始-->
+              <swiper ref="refSwiper" :slides-per-view="1" :slides-per-group="1" :space-between="0">
+                <swiper-slide v-for="(item, index) in reportDetails.image_urls" :key="index">
+                  <img :src="item" />
+                </swiper-slide>
+              </swiper>
+              <!--图片结束-->
+            </div>
+          </div>
+          <div class="right-bottom">
+            <div class="column">
+              <div class="title">点评</div>
+              <div class="note">{{ reportDetails._comments?.toString() }}</div>
+            </div>
+            <div class="column">
+              <div class="title">建议</div>
+              <div class="note">{{ reportDetails._recommends?.toString() }}</div>
+            </div>
+            <div class="column column2">
+              <div class="title2">数据查看</div>
+              <div class="erweima">
+                <img src="@/assets/images/login/erweima.png" />
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </transition>
+</template>
+<script setup lang="ts">
+import { Swiper, SwiperSlide } from 'swiper/vue';
+import 'swiper/css';
+import dataDictionary from "@/utils/dataDictionary"
+const { proxy } = getCurrentInstance() as any;
+const emit = defineEmits(['returnData']);
+const data = reactive<any>({
+  reportWindow: {
+    show: false,
+  }, type: "",
+  faceCheckStu: {},
+  reportDetails: {},
+  currentTab: 2
+});
+
+const { reportWindow, type, faceCheckStu, reportDetails, currentTab } = toRefs(data);
+
+/**
+ * 当天成绩列表
+*/
+const getReportDetails = () => {
+  reportDetails.value = {};
+  let params: any = {
+    exam_name: type.value,
+    result_id_info: faceCheckStu.value.result_id_info,
+    student_ids: faceCheckStu.value.student_id
+  };
+  proxy?.$http.common.reportDetails(params).then((res: any) => {
+    if (res.data.length > 0) {
+      reportDetails.value = res.data[0];
+    }
+  });
+};
+
+//选择图片或视频
+const getChoose = (data: any) => {
+  currentTab.value = data;
+};
+
+
+//打开
+const open = (typeData: any, data: any) => {
+  type.value = typeData;
+  faceCheckStu.value = data;
+  getReportDetails();
+  reportWindow.value.show = true;
+  emit('returnData', reportWindow.value.show);
+};
+
+//关闭
+const close = () => {
+  faceCheckStu.value = data;
+  reportWindow.value.show = false;
+  emit('returnData', reportWindow.value.show);
+};
+
+onMounted(() => {
+})
+
+//暴露给父组件用
+defineExpose({
+  open,
+  close,
+})
+</script>
+<style lang="scss" scoped>
+.mask {
+  position: fixed;
+  height: 100vh;
+  width: 100vw;
+  top: 0;
+  left: 0;
+  background: rgba(0, 0, 0, 0.78);
+  z-index: 998;
+}
+
+.reportWindow {
+  position: fixed;
+  height: 100vh;
+  width: 100vw;
+  top: 0;
+  left: 0;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #FFFFFF;
+  z-index: 999;
+
+  .box {
+    width: 75%;
+    height: 77.5vh;
+    border-radius: 1.6rem;
+    background: linear-gradient(60deg, #092941 -85%, #2A484B 96%);
+    box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.3);
+    padding: 20px;
+    display: flex;
+    justify-content: space-between;
+
+    .left {
+      width: 24%;
+      display: flex;
+      align-items: flex-start;
+      flex-direction: column;
+
+      .left-top {
+        width: 100%;
+        height: 34.5vh;
+        border-radius: 1.6rem;
+        background: radial-gradient(122% 126% at 97% 6%, #35FFC6 0%, #00FFE8 100%);
+        text-align: center;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-bottom: 13px;
+        flex-shrink: 0;
+
+        .left-top-center {
+          .pic {
+            width: 18vh;
+            height: 18vh;
+            border-radius: 50%;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            overflow: hidden;
+            margin: 0 auto 2vh auto;
+            box-sizing: border-box;
+            border: 0.44rem solid rgba(26, 41, 58, 0.6315);
+
+            img {
+              width: 100%;
+            }
+          }
+
+          .name {
+            width: 100%;
+            color: #1A293A;
+            font-size: 2.21rem;
+            padding: 0 0.3rem;
+            border-radius: 1.2rem;
+            background: radial-gradient(96% 96% at 2% 32%, #FFFFFF 0%, #FCFDFD 54%, #E1E4E7 100%);
+            box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.9046), inset 0px 3px 6px 0px rgba(0, 0, 0, 0.0851);
+          }
+
+          .className {
+            padding-top: 5px;
+            color: #1A293A;
+            font-size: 1.5rem;
+          }
+        }
+      }
+
+      .left-bottom {
+        height: 100%;
+        width: 100%;
+        background: radial-gradient(96% 96% at 2% 32%, #FFFFFF 0%, #FCFDFD 54%, #E1E4E7 100%);
+        display: flex;
+        display: flex;
+        align-items: flex-start;
+        flex-direction: column;
+        border-radius: 1.6rem;
+        overflow: hidden;
+
+        .left-bottom-title {
+          width: 100%;
+          font-size: 1.38rem;
+          color: #060C10;
+          padding: 10px 20px;
+          box-sizing: border-box;
+        }
+
+        .left-bottom-content {
+          width: 100%;
+          height: 100%;
+          padding: 0 10px 20px 10px;
+          box-sizing: border-box;
+          overflow-y: scroll;
+
+          &::-webkit-scrollbar {
+            width: 8px;
+          }
+
+          &::-webkit-scrollbar-thumb {
+            border-width: 2px;
+            border-radius: 4px;
+            border-style: dashed;
+            border-color: transparent;
+            background: #00FFE8;
+            background-clip: padding-box;
+          }
+
+          &::-webkit-scrollbar-button:hover {
+            border-radius: 5px;
+            background: rgba(26, 62, 78, 1);
+          }
+        }
+      }
+    }
+
+    .right {
+      width: calc(100% - 24%);
+
+      .right-top {
+        color: #ffffff;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 16px;
+
+        .btn {
+          display: flex;
+          width: 42%;
+          height: 3.6rem;
+          line-height: 3.6rem;
+          font-size: 1.65rem;
+          margin: 0 auto;
+          border-radius: 1.8rem;
+          font-size: 2rem;
+          text-align: center;
+          color: #1A293A;
+          background: #ACACAC;
+          overflow: hidden;
+
+          .li {
+            width: 50%;
+            text-align: center;
+            cursor: pointer;
+          }
+
+          .select {
+            border-radius: 1.8rem;
+            box-shadow: inset 0px 1px 0px 2px rgba(255, 255, 255, 0.5577);
+            background: radial-gradient(50% 181% at 163% 0%, #35FFC6 0%, #00FFE8 100%);
+          }
+        }
+
+        .close {
+          width: 3.2rem;
+          height: 3.2rem;
+          box-sizing: border-box;
+          border: 1px solid #979797;
+          background-image: url("@/assets/images/common/close.png");
+          background-position: center;
+          background-repeat: no-repeat;
+          background-size: 45% 45%;
+          background-color: rgba(216, 216, 216, 0.8);
+          border-radius: 50%;
+          transition: all 0.5s;
+          cursor: pointer;
+
+          &:hover {
+            transform: rotate(180deg);
+            background-color: rgba(216, 216, 216, 1);
+          }
+        }
+      }
+
+      .content {
+        padding: 0 3.2rem;
+        margin-bottom: 10px;
+        line-height: 0;
+        text-align: center;
+        $maxHeight: calc(77.5vh - 40px - 3.2rem - 16px - 13vh - 2rem);
+
+        .video {
+          video {
+            max-height: $maxHeight;
+            max-width: 100%;
+          }
+        }
+
+        .pic {
+          width: 100%;
+          height: 100%;
+          border: 1px solid #13ED84;
+          border-radius: 1.6rem;
+          background: linear-gradient(60deg, #092941 -85%, #2A484B 96%);
+          overflow: hidden;
+
+          img {
+            max-height: $maxHeight;
+            max-width: 100%;
+          }
+        }
+      }
+
+      .right-bottom {
+        padding: 0 3.2rem;
+        display: flex;
+        justify-content: space-between;
+
+        .column {
+          width: 38%;
+
+          .title {
+            font-size: 1.54rem;
+            color: #13ED84;
+            margin-bottom: 10px;
+            position: relative;
+
+            &::after {
+              content: "";
+              width: calc(100% - 3.8rem);
+              height: 1px;
+              background: #13ED84;
+              position: absolute;
+              right: 0;
+              bottom: 0.4rem;
+            }
+          }
+
+          .title2 {
+            font-size: 1.1rem;
+            color: #ffffff;
+            text-align: center;
+            margin-bottom: 10px;
+          }
+
+          .note {
+            font-size: 1.1rem;
+            color: #FFFFFF;
+            line-height: 1.5rem;
+            height: 13vh;
+            overflow-y: scroll;
+
+            &::-webkit-scrollbar {
+              width: 8px;
+            }
+
+            &::-webkit-scrollbar-thumb {
+              border-width: 2px;
+              border-radius: 4px;
+              border-style: dashed;
+              border-color: transparent;
+              background: #00FFE8;
+              background-clip: padding-box;
+            }
+
+            &::-webkit-scrollbar-button:hover {
+              border-radius: 5px;
+              background: rgba(26, 62, 78, 1);
+            }
+          }
+        }
+
+        .column2 {
+          width: 14%;
+        }
+
+        .erweima {
+          img {
+            width: 100%;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 1 - 3
src/types/components.d.ts

@@ -8,10 +8,8 @@ export {}
 declare module 'vue' {
   export interface GlobalComponents {
     ChooseStudent: typeof import('./../components/ChooseStudent/index.vue')['default']
-    copy: typeof import('./../components/OptionWindow copy/index.vue')['default']
     ElAvatar: typeof import('element-plus/es')['ElAvatar']
     ElButton: typeof import('element-plus/es')['ElButton']
-    ElDialog: typeof import('element-plus/es')['ElDialog']
     ElInput: typeof import('element-plus/es')['ElInput']
     ElOption: typeof import('element-plus/es')['ElOption']
     ElPagination: typeof import('element-plus/es')['ElPagination']
@@ -22,8 +20,8 @@ declare module 'vue' {
     FaceWindow: typeof import('./../components/FaceWindow/index.vue')['default']
     Header: typeof import('./../components/Header/index.vue')['default']
     MultipleItem: typeof import('./../components/MultipleItem/index.vue')['default']
-    OptionTest: typeof import('./../components/OptionTest/index.vue')['default']
     OptionWindow: typeof import('./../components/OptionWindow/index.vue')['default']
+    ReportWindow: typeof import('./../components/ReportWindow/index.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
   }

+ 26 - 31
src/views/ranking/index.vue

@@ -33,12 +33,11 @@
                   <div class="gradeTitle">{{ item.label }}</div>
                   <ul :ref="(el: any) => { multipleItemRef(el, item.value) }" @scroll="getScroll($event, item.value)">
                     <li :data-items="JSON.stringify(items)" v-for="items in item.list" :key="items.student_id"
-                      @click="showPerson(items)">
+                      @click="openReport(items)">
                       <div class="left">
                         <i class="pai"
                           :class="{ 'pai1': items.rank == 1, 'pai2': items.rank == 2, 'pai3': items.rank == 3 }">{{
                             items.rank }}</i>
-
                         <div class="userInfo">
                           <div class="touxiang">
                             <img v-if="items.logo_url" :src="items.logo_url" />
@@ -75,7 +74,7 @@
             <!--学生排行榜-->
             <div class="main-a-center" v-if="studentTop.length">
               <div class="item" :class="{ one: index == 0, two: index == 1, three: index == 2 }"
-                @click="showPerson(item)" v-for="(item, index) in studentTop" :key="index">
+                @click="openReport(item)" v-for="(item, index) in studentTop" :key="index">
                 <div class="touxiang">
                   <img v-if="item.logo_url" :src="item.logo_url" />
                   <img v-else :src="logo" />
@@ -107,7 +106,7 @@
               <div class="columns" v-for="(item, index) in studentList" :key="index">
                 <transition name="fade" mode="out-in">
                   <ul v-if="item.length">
-                    <li v-for="(items, indexs) in item" :key="indexs" @click="showPerson(items)">
+                    <li v-for="(items, indexs) in item" :key="indexs" @click="openReport(items)">
                       <div class="txt">
                         <i>{{ items.rank }}</i>
                         <div class="studentName">{{ items.student_name }}</div>
@@ -166,16 +165,7 @@
           </div>
         </div>
       </div>
-
-
-      <el-dialog :custom-class="'custom-dialog compare-dialog'" :visible.sync="isShowPerson"
-        :before-close="closePerson">
-        <!-- <div>
-          <PersonDetail ref="personDetail" :type="projectObj.exam_name" :displayType="1" @close="closePerson"
-            @delRefresh="getData" />
-        </div> -->
-      </el-dialog>
-
+      <ReportWindow ref="reportWindowRef" @returnData="returnData" />
     </div>
   </div>
 </template>
@@ -192,6 +182,7 @@ dayjs.extend(weekOfYear)
 const { proxy } = getCurrentInstance() as any;
 const router = useRouter();
 const refSwiper = ref();
+const reportWindowRef = ref();
 
 const data = reactive<any>({
   pageType: 1,//1年级排名2班级排名
@@ -217,7 +208,6 @@ const data = reactive<any>({
   currentClass: {},
   classIdKeyObj: {},
   choiceClassWindow: false,
-  isShowPerson: false,
   date: {
     type: 0, //1周2月3季度
     start: "",
@@ -273,7 +263,6 @@ const {
   currentClass,
   classIdKeyObj,
   choiceClassWindow,
-  isShowPerson,
   date,
   debounceTime,
   swiperOption
@@ -751,13 +740,19 @@ const setDate = () => {
 };
 
 //查看详情
-const showPerson = (data: any) => {
-
+const openReport = (data: any) => {
+  reportWindowRef.value.open(projectObj.value.exam_name, data);
 };
 
-//关闭弹窗
-const closePerson = () => {
-
+//监听窗口事件
+const returnData = (data: any) => {
+  console.log("111", data)
+  if (data == true) {
+    getStopPlaying(60 * 5);
+  }
+  if (data == false) {
+    getStopPlaying();
+  }
 };
 
 /**
@@ -1131,30 +1126,30 @@ $waiPadding: 6.51rem;
 
       .btn-left {
         cursor: pointer;
-        width: 20px;
-        height: 60px;
+        width: 16px;
+        height: 16px;
         margin-left: 0px;
         background: url("@/assets/images/ranking/btn-left.png") center center no-repeat;
-        background-size: 15px 29px;
+        background-size: 100% 100%;
         flex-shrink: 0;
         position: absolute;
         left: 0;
         top: 50%;
-        margin-top: -30px;
+        margin-top: -8px;
       }
 
       .btn-right {
         cursor: pointer;
-        width: 20px;
-        height: 60px;
+        width: 16px;
+        height: 16px;
         margin-right: 0px;
         background: url("@/assets/images/ranking/btn-right.png") center center no-repeat;
-        background-size: 15px 29px;
+        background-size: 100% 100%;
         flex-shrink: 0;
         position: absolute;
         right: 0;
         top: 50%;
-        margin-top: -30px;
+        margin-top: -8px;
       }
 
 
@@ -1247,6 +1242,7 @@ $waiPadding: 6.51rem;
                   background: #ffffff;
                   margin-left: 10px;
                   margin-right: 13px;
+                  flex-shrink: 0;
 
                   img {
                     border-radius: 50%;
@@ -1367,7 +1363,7 @@ $waiPadding: 6.51rem;
     width: 100%;
     display: flex;
     align-items: center;
-    border-top: 1px solid #979797;
+    border-top: 1px solid #48677E;
     overflow: hidden;
     box-sizing: border-box;
     padding: 0 2vh;
@@ -1426,7 +1422,6 @@ $waiPadding: 6.51rem;
   }
 }
 
-
 .choiceClass {
   width: calc(100% - ($waiPadding * 2));
   position: absolute;

+ 27 - 24
src/views/train/multiple.vue

@@ -1,10 +1,11 @@
 <template>
   <div>
-    <Header @confirmExit="confirmExit"></Header>      <transition :enter-active-class="proxy?.animate.dialog.enter" :leave-active-class="proxy?.animate.dialog.leave">
-        <div class="time" v-show="[42].includes(examState)">{{
-          time.countdownNum
-          }}</div>
-      </transition>
+    <Header @confirmExit="confirmExit"></Header>
+    <transition :enter-active-class="proxy?.animate.dialog.enter" :leave-active-class="proxy?.animate.dialog.leave">
+      <div class="time" v-show="[42].includes(examState)">{{
+        time.countdownNum
+      }}</div>
+    </transition>
     <div class="main">
 
       <div class="testBox"
@@ -472,24 +473,26 @@ onUnmounted(() => {
 
 <style scoped lang="scss">
 $waiPadding: 6.51rem;
-  .time {
-    width: 20vh;
-    height: 20vh;
-    line-height: 20vh;
-    border-radius: 50%;
-    color: #FF9402;
-    font-size: 8vh;
-    text-align: center;
-    background-image: url("@/assets/images/test/time.png");
-    background-position: center;
-    background-repeat: no-repeat;
-    background-size: 100% 100%;
-    position: absolute;
-    right: 50%;
-    top: -4vh;
-    margin-right: -10vh;
-    font-family: 'Saira-BlackItalic';
-  }
+
+.time {
+  width: 20vh;
+  height: 20vh;
+  line-height: 20vh;
+  border-radius: 50%;
+  color: #FF9402;
+  font-size: 8vh;
+  text-align: center;
+  background-image: url("@/assets/images/test/time.png");
+  background-position: center;
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  position: absolute;
+  right: 50%;
+  top: -4vh;
+  margin-right: -10vh;
+  font-family: 'Saira-BlackItalic';
+}
+
 .main {
   width: calc(100% - ($waiPadding * 2));
   height: 78vh;
@@ -526,7 +529,7 @@ $waiPadding: 6.51rem;
   .confirmDiaWindow {
     width: 23.5%;
     height: 43.4%;
-    border-radius: 29px;
+    border-radius: 1.6rem;
     opacity: 1;
     background: rgba(255, 255, 255, 0.01);
     box-sizing: border-box;

+ 3 - 3
src/views/train/test.vue

@@ -21,7 +21,7 @@
               :leave-active-class="proxy?.animate.dialog.leave">
               <div class="time" v-show="needStart && [42].includes(examState)">{{
                 time.countdownNum
-              }}</div>
+                }}</div>
             </transition>
             <div class="tips" v-if="examState == 41">
               <img v-if="parameter.gesture" src="@/assets/images/test/ready1.png" />
@@ -756,7 +756,7 @@ $waiPadding: 6.51rem;
       .top-left {
         width: 37.4%;
         height: 100%;
-        border-radius: 29px;
+        border-radius: 1.6rem;
         background: radial-gradient(122% 126% at 97% 6%, #35FFC6 0%, #00FFE8 100%);
         text-align: center;
         display: flex;
@@ -805,7 +805,7 @@ $waiPadding: 6.51rem;
       .top-right {
         width: 62%;
         height: 100%;
-        border-radius: 29px;
+        border-radius: 1.6rem;
         opacity: 1;
         background: #ffffff;
         box-sizing: border-box;