Browse Source

Merge branch 'develop' of http://163.228.141.122:3000/TEAMMODEL/TEAMModelOS into develop

黄贺彬 3 months ago
parent
commit
3f8ea9c710

+ 1 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/api/http.js

@@ -148,7 +148,7 @@ axios.interceptors.response.use(response => {
         sessionStorage.setItem('loginOut', error.config.url + ':API401,重新登录')
         sessionStorage.setItem('APIInfo', JSON.stringify(error))
         console.log('loginOut', error.config.url + ':API401,重新登录');
-        window.location.href = '/login/adminPage'
+        window.location.href = '/login/student'
         app.$message({
             type: 'error',
             message: 'http.error401'

+ 6 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/api/index.js

@@ -132,4 +132,10 @@ export default {
     saveStuExamPaper: function(data) {
         return post('/student/submit-subject-result', data)
     },
+    submitResult: function(data) {
+        return post('/student/submit-subject-result', data)
+    },
+    submitMusic: function(data) {
+        return post('/student/submit-music-ai-result', data)
+    },
 }

+ 2 - 2
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/router/router.js

@@ -8,11 +8,11 @@ let identity = sessionStorage.getItem('identity')
 const routes = [
     {
         path: '/',
-        redirect: '/login/admin',
+        redirect: '/login/student',
     },
     {
         path: '/login',
-        redirect: identity === 'student' ? '/login/student' : '/login/admin',
+        redirect: '/login/student',
         component: () => import("@/view/login/Index.vue"),
         children: [
             {

+ 21 - 5
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/admin/ActivityManage.vue

@@ -58,9 +58,9 @@
                             <span class="paper-extType" style="border-color: #88a1d8; color: #9fa91d;" v-if="evaluationClient.type === 'Art'">
                                 艺术评测
                             </span>
-                            <div class="short-code">
+                            <!-- <div class="short-code">
                                 <el-button size="mini">暂时隐藏页面</el-button>
-                            </div>
+                            </div> -->
                         </div>
                         <span>{{ evaluationClient.name }}
                             <span v-show="needUpdate.status" style="font-size: 16px; font-weight: normal; margin-left: 60px;">
@@ -195,7 +195,7 @@
                         </el-tab-pane>
                     </el-tabs>
                 </template>
-                <div v-else>暂无活动</div>
+                <div v-else style="text-align: center; margin-top: 18%; font-size: 36px; width: 100%;">暂无活动</div>
             </el-main>
         </el-container>
         <el-dialog title="请输入开卷码" width="30%" :visible.sync="isInputOpen" :close-on-click-modal="false" :close-on-press-escape="false" :show-close="false">
@@ -231,7 +231,9 @@
                     <span style="margin-right: 30px;">时间类型:{{ !item.countdownType ? '无' : item.countdownType === 1 ? '统一作答时长' : '学生个人作答时长' }}</span>
                     <span v-show="item.countdownType">作答时长:{{ item.duration }}</span>
                 </p>
-                <el-button @click="getExamRoundInfo(item.id, true)" style="float: right;">查看详情</el-button>
+                <div style="text-align: right;">
+                    <el-button @click="getExamRoundInfo(item.id, true)" size="mini">查看详情</el-button>
+                </div>
             </div>
         </el-dialog>
         <div class="open-evaluation" v-if="showErrorMsgs">
@@ -903,8 +905,15 @@ export default {
                     this.studentListShow = res.results.map(item => {
                         // 后续要重新处理状态
                         item.isAnswer = item.finished ? 2 : item.pushed ? 1 : 0 //0未开始  1正在作答  2已完成
+                        item.subjectResults = item.subjectResults.map(sub => {
+                            sub.paperProgress = sub.finished ? 100 : 0
+                            return sub
+                        })
                         return item
                     })
+                    this.studentListShow = this.studentListShow.sort((a, b) => {
+                        return a.studentId - b.studentId
+                    })
                     this.$forceUpdate()
                 } else {
                     this.$message({
@@ -944,6 +953,7 @@ export default {
                             type: 'success'
                         });
                         this.onSelectAct(this.curIndex)
+                        sessionStorage.removeItem(this.evaluationClient.id)
                     }
                 } else {
                     this.$message({
@@ -1017,9 +1027,15 @@ export default {
                     this.studentListShow = res.results.map(item => {
                         // 后续要重新处理状态
                         item.isAnswer = item.finished ? 2 : item.pushed ? 1 : 0 //0未开始  1正在作答  2已完成
-                        // item.subject = item.subjectResults
+                        item.subjectResults = item.subjectResults.map(sub => {
+                            sub.paperProgress = sub.finished ? 100 : 0
+                            return sub
+                        })
                         return item
                     })
+                    this.studentListShow = this.studentListShow.sort((a, b) => {
+                        return a.studentId - b.studentId
+                    })
                 }
             }).finally(() => {
                 if(isDialog) this.isLoading.close()

+ 2 - 2
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/student/ActivityAnswer.vue

@@ -524,7 +524,7 @@ export default {
                                         that.checkers.push([])
                                     }
                                 }
-                                that.diffSeconds = JSON.parse(localStorage.getItem("time")) || 10
+                                that.diffSeconds = JSON.parse(localStorage.getItem("time")) || 0
                                 that.costTime = JSON.parse(localStorage.getItem("costTime")) || 0
                                 // that.showExam = jsonData.item
                                 r(jsonData.item)
@@ -601,7 +601,7 @@ export default {
                     settingId: this.setting.id,
                 }
                 this.$api.saveStuExamPaper(params).then(res => {
-                    if (res.classResult) {
+                    if (res.code === 200) {
                         this.$message({
                             message: '作答信息提交成功!',
                             type: 'success'

+ 43 - 45
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/student/ActivityInfo.vue

@@ -23,13 +23,13 @@
                     <span>{{ activityInfo.name }}</span>
                 </div>
                 <div class="base-info">
-                    <p>
+                    <!-- <p>
                         <i class="el-icon-user"></i>
                         课程老师:<span>罗老师</span>
-                    </p>
+                    </p> -->
                     <p>
                         <i class="el-icon-postcard"></i>
-                        学生名单:<span>2021级3班</span>
+                        学生名单:<span>{{ activityInfo.className }}</span>
                     </p>
                     <p>
                         <i class="el-icon-user"></i>
@@ -54,7 +54,7 @@
             </template>
             <template v-if="activityInfo.type === 'Art' && activityInfo.progress === 'going'">
                 <div class="art-content" v-if="subjectList.length">
-                    <div class="subject-content" v-for="item in subjectList" :key="item.id">
+                    <div class="subject-content" v-for="item in subjectList" :key="item.subjectId">
                         <p class="subject-title">{{ item.subjectName }}</p>
                         <div class="paper-answer" v-if="item.paperId">
                             <div class="scoreboard">
@@ -69,47 +69,12 @@
                                     <i class="el-icon-yiwancheng answer-type" style="font-size: 50px; color: #01adff;"></i>
                                 </div>
                             </div>
-                            <template v-if="item.musicAIResult">
-                                <div v-for="(hw, index) in item.homework" :key="index">
-                                    <template v-if="hw">
-                                        <template v-if="hw.subject === 'subject_music' && hw.quotaId === 'quota_22'">
-                                            <div class="scoreboard">
-                                                <!-- <div v-if="hw.overTime && !hw.isAnswer" class="to-answer"> -->
-                                                    <div class="to-answer">
-                                                    <i class="el-icon-warning-outline"></i>
-                                                    <span style="margin-left: 5px;">已结束</span>
-                                                    <i class="el-icon-weizuoda answer-type" style="font-size: 50px;"></i>
-                                                </div>
-                                            </div>
-                                                <div class="scoreboard">
-                                                <!-- <div v-else-if="!hw.overTime && hw.isAnswer" class="to-answer"> -->
-                                                    <div class="to-answer">
-                                                    <i class="el-icon-gougou1" style="color: green;"></i>
-                                                    <span style="margin-left: 5px;">已完成作答</span>
-                                                    <i class="el-icon-yiwancheng answer-type" style="font-size: 50px; color: #01adff;"></i>
-                                                </div></div>
-                                                <div class="scoreboard">
-                                                <!-- <div v-else-if="hw.overTime && hw.isAnswer" class="to-answer"> -->
-                                                    <div class="to-answer">
-                                                    <i class="el-icon-dianji" style="font-size: 35px; color: #03966a;"></i>
-                                                    <span style="color: #03966a; margin-left: 10px; font-size: 25px;">查看详情</span>
-                                                </div></div>
-                                                <!-- <div v-else class="to-answer"> -->
-                                                    <div class="scoreboard">
-                                                    <div class="to-answer">
-                                                    <i class="el-icon-dianji" style="font-size: 35px; color: #03966a;"></i>
-                                                    <span style="color: #03966a; margin-left: 10px; font-size: 25px;">开始演唱</span>
-                                                    <i class="el-icon-weizuoda answer-type" style="font-size: 50px;"></i>
-                                                </div>
-                                            </div>
-                                        </template>
-                                    </template>
-                                </div>
-                            </template>
+                            <ZhiYinView ref="art" v-if="item.subjectId === 'subject_music' && musicAIResult.actId" :musicInfo="musicAIResult"></ZhiYinView>
                         </div>
                         <div v-else class="paper-answer">
                             暂无科目相关内容
                         </div>
+                        
                     </div>
                 </div>
             </template>
@@ -119,7 +84,12 @@
 
 <script>
 import {jwtDecode} from 'jwt-decode'
+import ZhiYinView from './ZhiYinView.vue'
+
 export default {
+    components: {
+        ZhiYinView
+    },
     data() {
         return {
             isLoadQues: false,
@@ -162,6 +132,9 @@ export default {
             },
             nowtime: null, //服务器时间
             setting: undefined,
+            musicAIResult: {
+                actId: '',
+            },
         }
     },
     async created() {
@@ -178,6 +151,15 @@ export default {
         this.userInfo.schPicture = schoolInfo.picture
         this.getActivityInfo()
     },
+    mounted () {
+        this.$nextTick(() => {
+            window.addEventListener('message', e => {
+                if(e.data === 'closeReview' || e.data === 'singComplete') {
+                    this.$refs['art'][0].setArtScore(e.data)
+                }
+            })
+        })
+    },
     methods: {
         getNowTime() {
             return new Promise((resolve, reject) => {
@@ -193,8 +175,18 @@ export default {
                     res.evaluationClient.endTime = this.$tools.getDate(res.evaluationClient.etime, 'year')
                     res.evaluationClient.progress = this.timeStatus(res.evaluationClient.stime, res.evaluationClient.etime)
                     this.activityInfo = res.evaluationClient
+                    this.activityInfo.className = ''
                     this.subjectList = res.evaluationClient.subjects
                     this.setting = res.setting
+                    if(res.evaluationClient.music) {
+                        this.musicAIResult.actId = res.evaluationClient.id
+                        this.musicAIResult.taskId = res.evaluationClient.music.taskId
+                        this.musicAIResult.musicId = res.evaluationClient.music.questionId
+                        this.musicAIResult.sub = this.userInfo.sub
+                        this.musicAIResult.azp = this.userInfo.azp
+                        this.musicAIResult.overTime = this.nowtime > res.evaluationClient.etime
+                        this.musicAIResult.settingId = res.setting.id
+                    }
                     this.getResult()
                 } else {
                     this.loading.close()
@@ -202,6 +194,11 @@ export default {
                         message: '当前无评测可以作答',
                         type: 'warning'
                     });
+                    setTimeout(() => {
+                        this.$router.push({
+                            path: "/login/student"
+                        });
+                    }, 1000)
                 }
             })
         },
@@ -218,6 +215,7 @@ export default {
             this.$api.stuGetResult(params).then(res => {
                 if(res.code === 200) {
                     this.studentResult = res.studentResult
+                    this.musicAIResult.finished = res.studentResult.musicAIResult?.finished
                     this.subjectList = this.subjectList.map(item => {
                         let subjectResult = res.studentResult.subjectResults.find(subject => subject.subjectId === item.subjectId)
                         item.finished = subjectResult ? subjectResult.finished : ''
@@ -225,6 +223,7 @@ export default {
                         item.paperName = subjectResult ? subjectResult.paperName : ''
                         return item
                     })
+                    this.activityInfo.className = res.studentResult.className
                 }
             }).finally(() => {
                 this.loading.close()
@@ -243,10 +242,9 @@ export default {
             localStorage.setItem("evaluationInfo", encodeURIComponent(JSON.stringify(evaluationInfo)))
             localStorage.setItem("setting", encodeURIComponent(JSON.stringify(this.setting)))
 
-            // 存储一个字段:该艺术评测是否要乱序作答
-            // getExamInfo 可能会有,就不用localStorage,如果用localStorage,要注意退出作答时清除之前的artExam
-            // 还需后端返回
-            // localStorage.setItem("artExamIsOrder", encodeURIComponent(JSON.stringify(art.examInfo[0].isOrder)))
+            // 存储一个字段:该艺术评测是否要乱序作答 disorder
+            let subj = this.activityInfo.subjects.find(item => item.subjectId === subjectInfo.subjectId)
+            localStorage.setItem("artExamIsOrder", encodeURIComponent(JSON.stringify(subj?.disorder || 0)))
             this.$router.push({path: '/studentAns'})
         },
         loginOut() {

+ 173 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/student/ZhiYinView.vue

@@ -0,0 +1,173 @@
+<template>
+    <div class="scoreboard zhiyin-view">
+        <template>
+            <h4 v-if="musicInfo.overTime && !musicInfo.finished" style="padding: 25px;">
+                <i class="el-icon-warning warm-icon" style="font-size: 18px; color: orange; margin-right: 5px;"></i>
+                <span class="warm-hint">
+                    已结束
+                </span>
+                <i class="el-icon-weizuoda" style="font-size: 50px; margin-left: 50px;"></i>
+            </h4>
+            <h4 v-else-if="!musicInfo.overTime && musicInfo.finished" style="padding: 25px;">
+                <i class="el-icon-gougou1 warm-icon" style="color: green;"></i>
+                已完成作答
+                <i class="el-icon-yiwancheng" style="font-size: 50px; color: #01adff; margin-left: 50px;"></i>
+            </h4>
+            <div v-else-if="musicInfo.overTime && musicInfo.finished">
+                <h4 style="width: 100%; font-size: 25px; font-weight: 800; padding: 17px; cursor: pointer;" @click="zyModule('aqd')">
+                    <i class="el-icon-dianji" style="font-size: 30px; color: #03966a;"></i>
+                    <span style="color: #03966a;cursor: pointer; margin-left: 10px;">查看详情</span>
+                </h4>
+            </div>
+            <div v-else>
+                <div style="width: 100%; font-size: 25px; font-weight: 800; padding: 17px; cursor: pointer;" @click="toSong">
+                    <i class="el-icon-dianji" style="font-size: 30px; color: #03966a;"></i>
+                    <span style="color: #03966a; margin-left: 10px;">开始演唱</span>
+                    <i class="el-icon-weizuoda" style="font-size: 50px; margin-left: 50px;"></i>
+                </div>
+            </div>
+        </template>
+        <el-dialog class="open-zhiyin" width="30%" :visible.sync="openSong" fullscreen :close-on-click-modal="false" :close-on-press-escape="false" :show-close="false">
+            <div class="bg-box" v-if="openSong">
+                <iframe :src="openUrl" class="song-iframe" allow='microphone;camera;' frameborder="0" width="100%" height="100%"></iframe>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import { h } from 'vue';
+
+export default {
+    props: {
+        musicInfo: {
+            type: Object,
+            default: undefined
+        },
+    },
+    data() {
+        return {
+            openSong: false,
+            openUrl: '',
+        }
+    },
+    methods: {
+        toSong() {// 链接
+            // window.open(this.openUrl, '_blank');
+            this.$confirm('开始作答后将无法关闭弹窗,一直到作答完成,是否开始作答?', '提示', {
+                confirmButtonText: '是',
+                cancelButtonText: '否',
+                type: 'warning',
+                center: true
+            }).then(() => {
+                    this.zyModule('aq')
+                    this.openSong = true
+            }).catch(() => {
+            });
+        },
+        // 查看智音作答详情
+        zyModule(busType, isUrl) {
+            // const url = this.$store.state.config.srvAdrType === 'test' ? 'https://tstamesopen.aimusic.art' : 'https://amesopen.aimusic.art'
+            const url = 'https://musicopen.winteach.cn'
+            // 智音提供的APP_ID
+            const appid = '8a68f563f3384662acbc268336b98ae2'
+            //第三方token
+            const thirdToken = localStorage.getItem('stu_auth_token')
+            let data = {
+                // 业务类型 aqd为答题详情
+                busType,
+                // questionId: this.hwInfo.musicId,
+                thirdAnswerId: `${this.musicInfo.actId}::${this.musicInfo.taskId}::${this.musicInfo.sub}`,
+            }
+            if (busType === 'aq') {
+                data.questionId = this.musicInfo.musicId
+                this.maskClosable = false
+            } else {
+                this.maskClosable = true
+            }
+            const base64Data = encodeURIComponent(window.btoa(JSON.stringify(data)))
+            const backUrl = url + '?appid=' + appid + '&data=' + base64Data + '&thirdToken=' + thirdToken
+            // 只需要地址链接
+            if (isUrl) {
+                return backUrl
+            } else {
+                this.openUrl = backUrl
+                this.openSong = true
+            }
+        },
+        setArtScore(message) {
+            // 点击×,取消作答
+            if(message === 'closeReview') {
+                this.$message({
+                    message: '取消作答!',
+                    type: 'warning'
+                });
+                this.openSong = false
+                return
+            } else if(message === 'singComplete') {
+                /* let params = {
+                    acId: this.hwInfo.id,
+                    subject: this.hwInfo.subject,
+                    artId: this.getItemTitle.id,
+                    quotaId: this.hwInfo.quotaId,
+                    classId: this.getItemTitle.classIds[0], //行政班一个学生只会存在一个班级
+                    isAnswer: 1,
+                    url: '', //智音作答详情
+                }
+                params.url = this.zyModule('aqd', true) */
+                let params = {
+                    evaluationId: this.musicInfo.actId,
+                    finished: 1,
+                    taskId: this.musicInfo.taskId,
+                    questionId: this.musicInfo.musicId,
+                    costTime: 1, //不计时
+                    settingId: this.musicInfo.settingId,
+                }
+                // 返回智音详情链接
+                this.$api.submitMusic(params).then(res => {
+                    this.musicInfo.finished = 1
+                    this.$message({
+                        message: '作答完成',
+                        type: 'success'
+                    });
+                    this.openSong = false
+                })
+            }
+        },
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.zhiyin-view {
+    margin-top: 30px;
+}
+</style>
+
+<style lang="less">
+.open-zhiyin {
+    .el-dialog__header {
+        padding: 0;
+    }
+    .el-dialog__body {
+        height: 100%;
+        padding: 0;
+    }
+    .bg-box {
+        background-image: url("zhiyin.png");
+        background-size: cover;
+        background-position: center;
+        width: 100%;
+        height: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+
+        .song-iframe {
+            width: 72%;
+            height: 84%;
+            border-radius: 5px;
+        }
+    }
+}
+</style>

BIN
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/student/zhiyin.png