瀏覽代碼

作品类型调整

XW 1 年之前
父節點
當前提交
09fb3c2a8f

+ 143 - 55
Contest/contest.client/src/view/myactivity/MyActivity.vue

@@ -199,39 +199,71 @@
                                             </div>
                                         </div>
                                     </template>
+                                    <template v-if="lessonSokrates.url">
+                                        <div class="file-show">
+                                            作品:
+                                            <span @click="lookSokrates()" style="color: #0c66c3; cursor: pointer;">{{ lessonSokrates.uploadName }}</span>
+                                        </div>
+                                    </template>
                                     <template v-if="contest?.upload && contest.upload.actState === 'going' && !contest?.upload.captainUpload || contest?.upload.captainUpload && isLeader">
-                                        <el-upload class="upload-demo" ref="refUpload" :file-list="fileList" :accept="accept" drag multiple :on-change="handleChange" :auto-upload="false" action="">
-                                            <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
-                                            <div class="el-upload__text">
-                                                上传作品
-                                            </div>
-                                            <template #tip>
-                                                <div class="tag-box">
-                                                    <el-tag :type="contest?.upload.captainUpload ? 'warning' : 'success'" disable-transitions effect="dark">
-                                                        {{ contest?.upload.captainUpload ? '队长统一上传' : '个人上传' }}
-                                                    </el-tag>
-                                                    <template v-if="contest?.upload.type === 'file'">
-                                                        <el-tag type="success" disable-transitions v-for="(item, index) in contest?.upload.fileType" :key="index">
-                                                            {{ item }}
-                                                        </el-tag>
-                                                    </template>
-                                                    <template v-else-if="contest?.upload.type === 'lesson'">
-                                                        <el-tag type="success" disable-transitions>
-                                                            必须上传视频
-                                                        </el-tag>
-                                                    </template>
+                                        <template v-if="contest.upload.uploadType.length">
+                                            <el-radio-group v-model="radioFileType">
+                                                <el-radio v-for="(item, index) in contest.upload.uploadType" :key="index" :label="item" size="large">
+                                                    {{ item === 'file' ? '文件' : item === 'sokrates' ? '苏格拉底影片' : '课例' }}
+                                                </el-radio>
+                                            </el-radio-group>
+                                        </template>
+                                        <template v-if="radioFileType === 'file' || contest.upload.type === 'file'">
+                                            <el-upload class="upload-demo" ref="refUpload" :file-list="fileList" :accept="accept" drag multiple :on-change="handleChange" :auto-upload="false" action="">
+                                                <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
+                                                <div class="el-upload__text">
+                                                    上传作品
                                                 </div>
-                                            </template>
-                                            <template #file="UploadFile">
-                                                <p class="file-list-box">
-                                                    <span>{{ UploadFile.file.name }}</span>
-                                                    <el-icon v-show="!isUpload" size="20" @click="handleRemove(UploadFile.file)"><Close /></el-icon>
-                                                </p>
-                                                <p class="file-list-progress">
-                                                    <el-progress :percentage="UploadFile.file.progress" :status="UploadFile.file.progress === 100 ? 'success' : ''" />
-                                                </p>
-                                            </template>
-                                        </el-upload>
+                                                <template #tip>
+                                                    <div class="tag-box">
+                                                        <el-tag :type="contest?.upload.captainUpload ? 'warning' : 'success'" disable-transitions effect="dark">
+                                                            {{ contest?.upload.captainUpload ? '队长统一上传' : '个人上传' }}
+                                                        </el-tag>
+                                                        <template v-if="radioFileType === 'file' || contest?.upload.type === 'file'">
+                                                            <el-tag type="success" disable-transitions v-for="(item, index) in contest?.upload.fileType" :key="index">
+                                                                {{ item }}
+                                                            </el-tag>
+                                                        </template>
+                                                        <!-- <template v-else>
+                                                            <el-tag type="success" disable-transitions>
+                                                                必须上传视频
+                                                            </el-tag>
+                                                        </template> -->
+                                                    </div>
+                                                </template>
+                                                <template #file="UploadFile">
+                                                    <p class="file-list-box">
+                                                        <span>{{ UploadFile.file.name }}</span>
+                                                        <el-icon v-show="!isUpload" size="20" @click="handleRemove(UploadFile.file)"><Close /></el-icon>
+                                                    </p>
+                                                    <p class="file-list-progress">
+                                                        <el-progress :percentage="UploadFile.file.progress" :status="UploadFile.file.progress === 100 ? 'success' : ''" />
+                                                    </p>
+                                                </template>
+                                            </el-upload>
+                                        </template>
+                                        <template v-else>
+                                            <el-form :model="sokratesForm" label-width="auto" style="margin-top: 20px;">
+                                                <el-form-item label="作品名称">
+                                                    <el-input v-model="sokratesForm.name" />
+                                                </el-form-item>
+                                                <el-form-item label="作品链接" v-show="radioFileType === 'sokrates'">
+                                                    <el-input v-model="sokratesForm.link" />
+                                                    <span>
+                                                        <el-icon color="#ba6b26"><Warning /></el-icon>
+                                                        请确保作品已在苏格拉底平台公开
+                                                    </span>
+                                                </el-form-item>
+                                                <el-form-item label="课例ID" v-show="radioFileType === 'lesson'">
+                                                    <el-input v-model="sokratesForm.course" />
+                                                </el-form-item>
+                                            </el-form>
+                                        </template>
                                         <el-button type="success" @click="uploadFile()" v-show="!isUpload">
                                             上传
                                         </el-button>
@@ -343,6 +375,7 @@ let nowYear = ref('')
 let scopeVal = ref('')
 let publishVal = ref('')
 let uploadName = ref('')
+let radioFileType = ref('')
 let searShow = ref(false)
 let skModule = ref(true)
 let isLeader = ref(false)
@@ -364,7 +397,9 @@ let contest = ref({})
 let research = ref({}) //教研
 let training = ref({}) //研修
 let previewFile = ref({})
+let lessonSokrates = ref({url: ''})
 let scoreData = ref({detailScore: []})
+let sokratesForm = ref({name: '', link: '', course: ''})
 
 const refUpload = ref(HTMLElement)
 const cipher = ref({})
@@ -411,6 +446,8 @@ function getListInfo(info, index) {
     actIndex.value = index
     actInfo.value = {attachment: []}
     uploadList.value = []
+    lessonSokrates.value = {url: ''}
+    sokratesForm.value = {name: '', link: '', course: ''}
     fileList.value = []
     accept.value = ''
     uploadName.value = ''
@@ -430,7 +467,7 @@ function getListInfo(info, index) {
             })
             actInfo.value = res.activity
             ruleTree.value = res.reviewRule?.trees || []
-            if(res.contest?.upload.type === 'file') accept.value = res.contest?.upload.fileType.map(item => '.' + item).join()
+            if(res.contest?.upload.type === 'file' || res.contest?.upload.uploadType.includes('file')) accept.value = res.contest?.upload.fileType.map(item => '.' + item).join()
             let nowDate = new Date().getTime()
             res.contest.modules.forEach((item, index) => {
                 res.contest[item].actState = nowDate < res.contest[item].stime ? 'notStart' : (nowDate > res.contest[item].etime ? 'finish' : 'going')
@@ -440,6 +477,7 @@ function getListInfo(info, index) {
             })
             contestStep.value = index === -1 ? 4 : (!index && res.contest.upload.actState === 'going' ? 1 : index)
             contest.value = res.contest
+            radioFileType.value = res.contest?.upload.uploadType.length ? res.contest?.upload.uploadType[0] : ''
             contestScores.value = res.contestScores || []
             research.value = res.research
             training.value = res.training
@@ -468,10 +506,13 @@ function getEnroll() {
                 })
                 let sasUrl = await proxy.$api.blobSasRCW({name: actInfo.value.owner, role: 'teacher' })
                 if(res.enroll.upload) {
-                    uploadList.value = res.enroll.upload.files.map(item => {
+                    let arr = res.enroll.upload.uploadType.includes('file') ? res.enroll.upload.complexes.map(item => item.uploadFile) : res.enroll.upload.files
+                    uploadList.value = arr.map(item => {
                         item.urlShow = sasUrl.url + '/' + actInfo.value.owner + item.blob + '?' + sasUrl.sas
                         return item
                     })
+                    lessonSokrates.value = (res.enroll.upload.uploadType.length && !res.enroll.upload.uploadType.includes('file')) ? res.enroll.upload.complexes[0]?.lessonSokrates : {url: ''}
+                    lessonSokrates.value.uploadName = res.enroll.upload.name
                 }
                 /* memberData.value.push(Object.fromEntries(field))
                 memberData.value[0].identity = res.enroll.contest.leader
@@ -646,7 +687,15 @@ function handleChange(file, files) {
         files.splice(fileList.value.length, 1)
         return
     }
-    if(file.size > 100 * 1024 * 1024) {
+    if(file.raw.type.includes('video') && file.size > 2 * 1024 * 1024 * 1024) {
+        ElMessage({
+            type: 'warning',
+            message: '视频大小不能超过2GB!'
+        })
+        files.splice(fileList.value.length, 1)
+        return
+    }
+    if(!file.raw.type.includes('video') && file.size > 100 * 1024 * 1024) {
         ElMessage({
             type: 'warning',
             message: '文件大小不能超过100MB!'
@@ -727,25 +776,36 @@ function deleteBlobPrefix(code, path) {
 }
 
 async function uploadFile() {
-    if(!fileList.value.length) {
+    if(radioFileType.value != 'file' && (!sokratesForm.value.name || (radioFileType.value === 'sokrates' && !sokratesForm.value.link) || (radioFileType.value === 'lesson' && !sokratesForm.value.course))) {
+        ElMessage({
+            type: 'warning',
+            message: '请完善信息'
+        })
+        return
+    }
+    if(radioFileType.value === 'file' && !fileList.value.length) {
         ElMessage({
             type: 'warning',
             message: '请先选择文件!'
         })
         return
     }
-    if(contest.value.upload.type === 'lesson' && !fileList.value.find(item => item.raw.type === 'video/mp4')) {
+    /* if((contest.value.upload.type === 'lesson' || radioFileType.value === 'lesson') && !fileList.value.find(item => item.raw.type === 'video/mp4')) {
         ElMessage({
             type: 'warning',
             message: '必须上传视频!'
         })
         return
+    } */
+    if(radioFileType.value === 'file') {
+        uploadDia.value = true
+    } else {
+        startUpload()
     }
-    uploadDia.value = true
 }
 
 async function startUpload() {
-    if(!uploadName.value) {
+    if(radioFileType.value === 'file' && !uploadName.value) {
         ElMessage({
             type: 'warning',
             message: '请输入作品集名称'
@@ -754,36 +814,49 @@ async function startUpload() {
     }
     isUpload.value = true
     uploadDia.value = false
-    let blobList = await uploadBlob()
-    if(!blobList) {
-        ElMessage({
-            type: 'warning',
-            message: '上传失败'
-        })
-        isUpload.value = false
-        return
+    let blobList = undefined
+    if(radioFileType.value === 'file') {
+        blobList = await uploadBlob()
+        if(!blobList) {
+            ElMessage({
+                type: 'warning',
+                message: '上传失败'
+            })
+            isUpload.value = false
+            return
+        }
     }
     let params = {
         grant_type: 'upload-contest',
         activityId: actInfo.value.id,
         uploadData: {
-            type: contest.value.upload.type,
-            name: uploadName.value,
+            // type: contest.value.upload.type,
+            name: radioFileType.value === 'file' ? uploadName.value : sokratesForm.value.name,
+            complexes: []
         },
     }
     // 暂不考虑这种情况,因为创建活动时必须填写报名模块
-    /* if(!contest.value.modules.incldes('sign')) {
+    /* if(!contest.value.modules.includes('sign')) {
         // 活动没有报名模块,直接上传作品
         params.uploadData.schoolId
         params.uploadData.schoolName
         params.uploadData.schoolPicture
     } */
-    if(contest.value.upload.type === 'file') {
+    // 统一改为 complexes:[{type: 'file'/'sokrates'/'lesson', ('sokrates'/'lesson'使用)lessonSokrates: {url: ''}, ('file'使用)uploadFile: {}}]
+    /* if(contest.value.upload.type === 'file') {
         params.uploadData.files = blobList
     } else if(contest.value.upload.type === 'lesson') {
         params.uploadData.lessons = blobList
     } else {
         params.uploadData.sokrates = []
+    } */
+    if(radioFileType.value === 'file' || contest.value.upload.type === 'file') {
+        params.uploadData.complexes = blobList.map(item => {
+            return {type: 'file', uploadFile: item}
+        })
+    } else {
+        // 课例需再处理
+        params.uploadData.complexes = [{type: radioFileType.value, lessonSokrates: {url: sokratesForm.value.link}}]
     }
     proxy.$api.teaContest(params).then(async res => {
         if(res.code === 200) {
@@ -791,11 +864,19 @@ async function startUpload() {
                 type: 'success',
                 message: '上传成功'
             })
-            let sasUrl = await proxy.$api.blobSasRCW({name: actInfo.value.owner, role: 'teacher' })
-            uploadList.value = blobList.map(item => {
-                item.urlShow = sasUrl.url + '/' + actInfo.value.owner + item.blob + '?' + sasUrl.sas
-                return item
-            })
+            if(radioFileType.value === 'file') {
+                let sasUrl = await proxy.$api.blobSasRCW({name: actInfo.value.owner, role: 'teacher' })
+                uploadList.value = blobList.map(item => {
+                    item.urlShow = sasUrl.url + '/' + actInfo.value.owner + item.blob + '?' + sasUrl.sas
+                    return item
+                })
+                lessonSokrates.value = {url: ''}
+            } else {
+                lessonSokrates.value = params.uploadData.complexes[0].lessonSokrates
+                lessonSokrates.value.uploadName = params.uploadData.name
+                uploadList.value = []
+            }
+            sokratesForm.value = {name: '', link: '', course: ''}
             fileList.value = []
         } else {
             ElMessage({
@@ -892,6 +973,13 @@ function onFilterClear() {
     getListInfo(actListShow.value[0], 0)
 }
 
+function lookSokrates() {
+    // 查看苏格拉底单点登录页面所需字段,在此处重新拼接
+    // https://account.teammodel.cn/?callback=https%3A%2F%2Fsokrates.teammodel.cn%2Fauth%2Flogin%2Fcallback-habook%3Fto%3DaHR0cHM6Ly9zb2tyYXRlcy50ZWFtbW9kZWwuY24vZXhoaWJpdGlvbi90YmF2aWRlbyMvY29udGVudC81MDk1Mz9ncm91cElkcz0xNDImY2hhbm5lbElkPTEzMQ%3D%3D
+    let url = "https://account.teammodel.cn/?callback=" + 'https://sokrates.teammodel.cn/auth/login/callback-habook' + '?to=' + btoa(lessonSokrates.value.url)
+    window.open(url, '_blank')
+}
+
 watch(nowYear, (newValue, oldValue) => {
     getActList()
 })

+ 22 - 7
Contest/contest.client/src/view/myactivity/MyReview.vue

@@ -63,7 +63,7 @@
                                                     学科:{{ workInfo.subject }}
                                                 </p>
                                             </div>
-                                            <div class="review-header-works">
+                                            <div class="review-header-works" v-if="workInfo.files.length">
                                                 <div class="works-list">
                                                     <el-scrollbar>
                                                         <div v-for="(item, index) in workInfo.files" :key="index" @click="changeFile(item, index)" :class="['files-list', {'active-file': fileIndex === index}]">
@@ -88,6 +88,10 @@
                                                     </div>
                                                 </div>
                                             </div>
+                                            <div v-else-if="workInfo.link">
+                                                作品:
+                                                <span @click="lookSokrates()" style="color: #0c66c3; cursor: pointer;;">{{ workInfo.link.uploadName }}</span>
+                                            </div>
                                         </div>
                                         <div style="text-align: right; margin: 10px 20px;" v-show="workList.length && workList.length != 1">
                                             <el-button type="info" @click="changeWork()" v-show="workIndex">上一位</el-button>
@@ -223,7 +227,7 @@ let reviewScore = ref(null)
 let workList = ref([])
 let workIndex = ref(0)
 // 展示作品信息
-let workInfo = ref({})
+let workInfo = ref({files: [], link: undefined})
 // 作品信息
 let workInfoShow = ref({})
 let fileIndex = ref(0)
@@ -252,7 +256,7 @@ function getTaskList() {
                 item.isFinish = nowTime >= item.etime
                 return item
             })
-            getListInfo(taskList.value[0], 0)
+            if(taskList.value.length) getListInfo(taskList.value[0], 0)
         }
     })
 }
@@ -312,7 +316,9 @@ function getUploadInfo(info) {
         proxy.$api.getTaskList(params).then(res => {
             if(res?.upload) {
                 info.files = []
-                res.upload.files.map(item => {
+                info.link = {url: ''}
+                let arr = res.upload.uploadType.includes('file') ? res.upload.complexes.map(item => item.uploadFile) : res.upload.files
+                arr.map(item => {
                     item.urlShow = actInfo.value.url + item.url + '?' + actInfo.value.sas
                     if(item.type === 'video') {
                         info.files.unshift(item)
@@ -320,16 +326,18 @@ function getUploadInfo(info) {
                         info.files.push(item)
                     }
                 })
+                info.link = (res.upload.uploadType.length && !res.upload.uploadType.includes('file')) ? res.upload.complexes[0].lessonSokrates : {url: ''}
+                info.link.uploadName = res.upload.name
                 workInfo.value = info
                 // changeFile(workInfo.value.files[0], 0)
                 fileIndex.value = 0
-                fileInfo.value = workInfo.value.files[0]
+                if(res.upload.uploadType.includes('file')) fileInfo.value = workInfo.value.files[0]
             }
         })
     } else {
         workInfo.value = info
         fileIndex.value = 0
-        fileInfo.value = workInfo.value.files[0]
+        if(res.upload.uploadType.includes('file')) fileInfo.value = workInfo.value.files[0]
     }
 }
 
@@ -351,7 +359,7 @@ function saveScore() {
         // 排查细项打分时,是否有遗漏(可以打0分)
         notScore = checkNotScore(ruleInfo.value.trees)
     } else {
-        notScore = reviewScore.value
+        notScore = !reviewScore.value
     }
     if(notScore) {
         ElMessage({
@@ -457,6 +465,13 @@ function startWork() {
     getUploadInfo(workInfo.value)
     scoring.value = false
 }
+
+function lookSokrates() {
+    // 查看苏格拉底单点登录页面所需字段,在此处重新拼接
+    // https://account.teammodel.cn/?callback=https%3A%2F%2Fsokrates.teammodel.cn%2Fauth%2Flogin%2Fcallback-habook%3Fto%3DaHR0cHM6Ly9zb2tyYXRlcy50ZWFtbW9kZWwuY24vZXhoaWJpdGlvbi90YmF2aWRlbyMvY29udGVudC81MDk1Mz9ncm91cElkcz0xNDImY2hhbm5lbElkPTEzMQ%3D%3D
+    let url = "https://account.teammodel.cn/?callback=" + 'https://sokrates.teammodel.cn/auth/login/callback-habook' + '?to=' + btoa(workInfo.value.link.url)
+    window.open(url, '_blank')
+}
 </script>
 
 <style lang="less" scoped>