From 5f00696dfb25bc90034448ceb634ed1ef256681a Mon Sep 17 00:00:00 2001 From: qiyunfeng-create <1940665526@qq.com> Date: 星期四, 21 八月 2025 21:13:35 +0800 Subject: [PATCH] Merge branch 'master' of http://182.92.203.7:2001/r/xiehe_website --- src/views/classManage/jobDetail.vue | 840 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 840 insertions(+), 0 deletions(-) diff --git a/src/views/classManage/jobDetail.vue b/src/views/classManage/jobDetail.vue new file mode 100644 index 0000000..b893184 --- /dev/null +++ b/src/views/classManage/jobDetail.vue @@ -0,0 +1,840 @@ +<template> + <div class="classManagePage-box"> + <div class="classManagePage-nav"> + <el-breadcrumb :separator-icon="ArrowRight"> + <el-breadcrumb-item>鎴戠殑鐝骇</el-breadcrumb-item> + <el-breadcrumb-item>{{ classInfo?.name }}</el-breadcrumb-item> + <el-breadcrumb-item>浣滀笟绠$悊璇︽儏</el-breadcrumb-item> + </el-breadcrumb> + </div> + <div class="classManagePage-content"> + <div class="backBtn"> + <el-button @click="goBack()" type="primary" link> + <el-icon style="margin-right: 5px"><ArrowLeftBold /></el-icon> 杩斿洖 + </el-button> + </div> + <div class="contentBox"> + <div class="content-tab-box"> + <div class="content-header"> + <div class="selectState"> + <span>鐘舵�侊細</span> + <el-select placeholder="鍏ㄩ儴" v-model="workState" @change="selectChangeState"> + <el-option + v-for="item in options" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> + </div> + <div class="searchBox" v-if="workState != 'WaitSubmit'"> + <!-- <el-input + v-model="searchKey" + clearable + @clear="searchData" + placeholder="璇疯緭鍏ュ叧閿瓧" + > + <template #append> + <el-button type="primary" @click="searchData" class="searchBtn" :icon="Search" /> + </template> + </el-input> --> + </div> + </div> + <div class="content-list-box"> + <el-table + :data="tableData" + border + max-height="600px" + style="width: 100%" + :header-cell-class-name="'headerCellClassName'" + v-loading="tableLoading" + v-if="workState != 'WaitSubmit'" + > + <el-table-column label="搴忓彿" prop="id" width="60"> </el-table-column> + <el-table-column label="濮撳悕" #default="scope" width="150"> + <span>{{ scope.row.appUser?.userInfo?.name }}</span> + </el-table-column> + <el-table-column label="鐘舵��" prop="state" #default="scope"> + <span v-if="scope.row.state == 'WaitCheck'" style="color: #409eff">鏈壒鏀�</span> + <span v-if="scope.row.state == 'Normal'" style="color: #67c23a">宸叉壒鏀�</span> + <span v-if="scope.row.state == 'WaitSubmit'" style="color: red">鏈彁浜�</span> + </el-table-column> + <el-table-column label="寰楀垎" #default="scope"> + <span v-if="scope.row.result > 0">{{ scope.row.result }}</span> + <span v-else>{{ scope.row.totalScore }}</span> + </el-table-column> + <el-table-column label="鍗曢�夐" v-if="singleChoiceLength > 0"> + <el-table-column + v-for="(item, index) in singleChoiceLength" + :key="index" + :label="item" + > + <template #default="scope"> + <span v-if="scope.row.singleChoiceArr[index]?.score == 0" style="color: red"> + {{ scope.row.singleChoiceArr[index]?.answer }} + </span> + <span v-else style="color: #67c23a"> + {{ scope.row.singleChoiceArr[index]?.answer }} + </span> + </template> + </el-table-column> + </el-table-column> + <el-table-column label="澶氶�夐" v-if="multipleChoiceLength > 0"> + <el-table-column + v-for="(item, index) in multipleChoiceLength" + :key="index" + :label="item" + > + <template #default="scope"> + <span v-if="scope.row.judgeArr[index]?.score == 0" style="color: red"> + {{ scope.row.multipleChoiceArr[index]?.answer.join(',') }} + </span> + <span v-else style="color: #67c23a"> + {{ scope.row.multipleChoiceArr[index]?.answer.join(',') }} + </span> + </template> + </el-table-column> + </el-table-column> + <el-table-column label="鍒ゆ柇棰�" v-if="judgeLength > 0"> + <el-table-column v-for="(item, index) in judgeLength" :key="index" :label="item"> + <template #default="scope"> + <span v-if="scope.row.judgeArr[index]?.score == 0" style="color: red"> + {{ scope.row.judgeArr[index]?.answer }} + </span> + <span v-else style="color: #67c23a"> + {{ scope.row.judgeArr[index]?.answer }} + </span> + </template> + </el-table-column> + </el-table-column> + <el-table-column label="濉┖棰橈紙鍒嗭級" v-if="completionLength > 0"> + <el-table-column + v-for="(item, index) in completionLength" + :key="index" + :label="item" + > + <template #default="scope"> + <span v-if="scope.row.completionArr[index]?.score == 0" style="color: red"> + {{ scope.row.completionArr[index]?.score }} + </span> + <span v-else style="color: #67c23a"> + {{ scope.row.completionArr[index]?.score }} + </span> + </template> + </el-table-column> + </el-table-column> + <el-table-column label="涓昏棰橈紙鍒嗭級" v-if="otherLength > 0"> + <el-table-column v-for="(item, index) in otherLength" :key="index" :label="item"> + <template #default="scope"> + <span v-if="scope.row.otherArr[index]?.score == 0" style="color: red"> + {{ scope.row.otherArr[index]?.score }} + </span> + <span v-else style="color: #67c23a"> + {{ scope.row.otherArr[index]?.score }} + </span> + </template> + </el-table-column> + </el-table-column> + <el-table-column label="鎿嶄綔" width="150" #default="scope"> + <el-button + link + v-if="scope.row.state != 'Normal'" + style="color: #409eff" + @click="openDialog(scope.row)" + > + 鍒ゆ柇涓昏棰� + </el-button> + <el-button link v-if="scope.row.state == 'Normal'"> -- </el-button> + </el-table-column> + </el-table> + <el-table + :data="dataList" + border + v-else + max-height="600px" + style="width: 100%" + :header-cell-class-name="'headerCellClassName'" + v-loading="pages.loading" + > + <el-table-column prop="index" label="搴忓彿" width="70" /> + <el-table-column prop="appUserId" label="瀛﹀彿" width="150" /> + <el-table-column label="濮撳悕" width="400"> + <template #default="scope"> + <div class="userBox"> + <el-avatar + style="margin-right: 10px" + v-if="scope.row.appUser.icon" + :size="35" + :src="scope.row.appUser.icon" + /> + <el-avatar + style="margin-right: 10px" + :size="35" + v-if="!scope.row.appUser.icon" + :icon="UserFilled" + /> + <span v-if="scope.row.appUser.name">{{ scope.row.appUser.name }}</span> + </div> + </template> + </el-table-column> + <el-table-column prop="createDate" label="鍔犲叆鐝骇鏃堕棿" /> + <el-table-column label="鎿嶄綔" width="220" #default="scope"> + <el-button link style="color: red" @click="remindWork(scope.row)"> + 鍌氦浣滀笟 + </el-button> + </el-table-column> + </el-table> + <div class="pageBox"> + <el-pagination + v-model:current-page="pages.currentPage" + :page-size="pages.pageSize" + :size="'small'" + :disabled="pages.count <= 1" + layout="total, prev, pager, next" + :total="pages.count" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + </div> + <!-- 涓昏棰樺垽鏂� --> + <el-dialog + class="customDialog" + title="鍒ゆ柇涓昏棰�" + v-model="otherVisible" + destroy-on-close + width="800" + :before-close="close" + > + <div class="pubContent"> + <questionDom + :question-list="otherQuestions" + :is-judge="true" + @judge-update="judgeUpdate" + /> + </div> + </el-dialog> + </div> + </div> + </div> +</template> +<script setup lang="ts"> +import { useRoute, useRouter } from 'vue-router' +import { inject, onMounted, reactive, ref } from 'vue' +import { Search, UserFilled, ArrowRight } from '@element-plus/icons-vue' +import { ElMessage } from 'element-plus' +import questionDom from './components/questionDom.vue' +import moment from 'moment' + +const route: any = useRoute() +const router = useRouter() +const classInfo = JSON.parse(route.query.classInfo) +const MG: any = inject('MG') +const config: any = inject('config') +const tool: any = inject('toolClass') + +// 浣滀笟璇︽儏 +const workState = ref('all') +const searchKey = ref('') +const cmsDatas: any = ref([]) +const tableData: any = ref([]) +const tableLoading = ref(true) +const singleChoiceLength = ref(0) +const multipleChoiceLength = ref(0) +const judgeLength = ref(0) +const completionLength = ref(0) +const otherLength = ref(0) +const otherVisible = ref(false) +const otherQuestions: any = ref([]) // 涓昏棰� +const cacheDate: any = ref([]) +const currentWorkId = ref(null) // 褰撳墠浣滀笟id +const dataList: any = ref([]) // 鏈彁浜ゅ垪琛� +const options = ref([ + { + label: '鍏ㄩ儴', + value: 'all' + }, + { + label: '鏈壒鏀�', + value: 'WaitCheck' + }, + { + label: '宸叉壒鏀�', + value: 'Normal' + }, + { + label: '鏈彁浜�', + value: 'WaitSubmit' + } +]) + +let pages = reactive({ + currentPage: 1, + page: 1, + pageSize: 15, + count: 0, + loading: true +}) + +const questionKey = [ + 'Name', + 'Embedded_QuestionBank_AnalysisCon', + 'Embedded_QuestionBank_Answer', + 'Embedded_QuestionBank_Difficulty', + 'Embedded_QuestionBank_KnowledgePoint', + 'Embedded_QuestionBank_Option', + 'Embedded_QuestionBank_OptionStyle', + 'Embedded_QuestionBank_QuestionType', + 'Embedded_QuestionBank_Score', + 'Embedded_QuestionBank_Stem', + 'Embedded_QuestionBank_StemStyle' +] + +// 鍒嗛〉 +const handleSizeChange = (val: number) => { + pages.pageSize = val + if (workState.value != 'WaitSubmit') { + getTaskDetail() + } else { + getUnSubmitList() + } +} + +const handleCurrentChange = (val: number) => { + pages.page = val + pages.currentPage = val + if (workState.value != 'WaitSubmit') { + getTaskDetail() + } else { + getUnSubmitList() + } +} + +onMounted(() => { + getTaskCmsList() +}) + +// 鐘舵�佹敼鍙� +const selectChangeState = (item: any) => { + workState.value = item + if (item == 'WaitSubmit') { + // const data = [{ field: 'State', value: 'Normal', subFilters: [] }] + getUnSubmitList() + } else { + const data = item != 'all' ? [{ field: 'State', value: item, subFilters: [] }] : [] + getTaskDetail(data) + } +} + +const openDialog = (item: any) => { + otherVisible.value = true + currentWorkId.value = item.id +} + +// 鑾峰彇璇︽儏 +const getTaskDetail = (filter?: any, search?: any) => { + const filterList = filter ?? [] + const searchList = search ?? [] + tableLoading.value = true + const data = { + start: (pages.page - 1) * pages.pageSize, + size: pages.pageSize, + taskId: classInfo?.taskWorkId, + classId: classInfo?.id, + filterList, + searchList + } + MG.edu + .getTaskSubmitList(data) + .then((res: any) => { + pages.loading = false + pages.count = res.totalSize + cacheDate.value = [] + // 棰樺簱棰樼洰绫诲瀷 + const questionTypeList = [ + { name: '绠�绛旈', totalScore: 0, value: 'shortAnswer', data: [] }, + { name: '璁鸿堪棰�', totalScore: 0, value: 'discuss', data: [] }, + { name: '杩炵嚎棰�', totalScore: 0, value: 'matching', data: [] }, + { name: '鍒嗙被棰�', totalScore: 0, value: 'classification', data: [] } + ] + try { + let list: any = [] + res.datas.forEach((item: any) => { + const parentData = { + feedBack: item.feedBack, + id: item.id, + result: item.result, + type: item.type, + state: item.state, + submit: item.submit, + updateTaskSubmitCmsItemRequests: [] + } + item.singleChoiceName = '鍗曢�夐' + item.singleChoiceArr = [] + item.multipleChoiceName = '澶氶�夐' + item.multipleChoiceArr = [] + item.judgeName = '鍒ゆ柇棰�' + item.judgeArr = [] + item.completionName = '濉┖棰�' + item.completionArr = [] + item.otherName = '涓昏棰�' + item.otherArr = [] + item.totalScore = 0 + const submitData = deduplicateArray(item.submitAndCmsItemLinks, 'cmsItemId') + submitData.forEach((citem: any) => { + const obj = cmsDatas.value.find((i: any) => i.id == citem.cmsItemId) + item.totalScore += citem.score + if (citem.answer != '') { + if (obj.questionType == 'singleChoice') { + citem.answer = JSON.parse(citem.answer) ?? '-' + item.singleChoiceArr.push(citem) + } else if (obj.questionType == 'multipleChoice') { + citem.answer = JSON.parse(citem.answer) ?? '-' + item.multipleChoiceArr.push(citem) + } else if (obj.questionType == 'judge') { + citem.answer = JSON.parse(citem.answer) ?? '-' + item.judgeArr.push(citem) + } else if (obj.questionType == 'completion') { + citem.answer = JSON.parse(citem.answer) ?? '-' + item.completionArr.push(citem) + } else { + obj.score = citem.score + obj.answer = citem.answer + obj.updateId = citem.id + obj.parentId = item.id + item.otherArr.push(citem) + list.push(obj) + } + } + }) + cacheDate.value.push(parentData) + }) + list.forEach((item: any) => { + const index = findIndexByValue(questionTypeList, item.questionType) + if (index > -1) { + questionTypeList[index].data.push(item) + if (item.score) { + questionTypeList[index].totalScore += item.score + } + } + }) + otherQuestions.value = questionTypeList.filter((item) => item.data.length > 0) + const lenghtArr = [...res.datas] + singleChoiceLength.value = lenghtArr.reduce( + (max: any, obj: any) => Math.max(max, obj.singleChoiceArr.length), + 0 + ) + multipleChoiceLength.value = lenghtArr.reduce( + (max: any, obj: any) => Math.max(max, obj.multipleChoiceArr.length), + 0 + ) + judgeLength.value = lenghtArr.reduce( + (max: any, obj: any) => Math.max(max, obj.judgeArr.length), + 0 + ) + completionLength.value = lenghtArr.reduce( + (max: any, obj: any) => Math.max(max, obj.completionArr.length), + 0 + ) + otherLength.value = lenghtArr.reduce( + (max: any, obj: any) => Math.max(max, obj.otherArr.length), + 0 + ) + tableLoading.value = false + tableData.value = res.datas + } catch (err) { + tableLoading.value = false + console.log(err) + } + }) + .catch((err: any) => { + console.log(err) + }) +} + +// 鑾峰彇浠诲姟涓嬬殑璧勬簮鍒楄〃 +const getTaskCmsList = () => { + tableLoading.value = true + const data = { + start: 0, + size: 999, + searchList: [], + taskId: classInfo?.taskWorkId, // taskData?.id + path: String(classInfo?.taskCmsId), //taskData?.rootCmsItemId + type: '*', + keys: questionKey + } + MG.edu + .getTaskCmsItem(data) + .then((res: any) => { + for (let i = 0; i < res.datas.length; i++) { + let item = res.datas[i] + item.index = i + 1 + // 澶勭悊瀛楁 + if (questionKey != null) { + for (let fieldKey of questionKey) { + if (item.datas[fieldKey]) { + const values = JSON.parse(item.datas[fieldKey]) + if (values.length > 0) { + // 鐢ㄥ瓧娈靛悕澶勭悊杩斿洖鐨勫瓧娈靛�� + if (values[0].Value) { + item[fieldKey] = values[0].Value + } else if (values[0].Data) { + item[fieldKey] = values[0].Data.Value + } else if (!values[0].Value && values[0].FileList?.length > 0) { + item[fieldKey] = values[0].FileList + } else { + item[fieldKey] = '-' + } + } + } + } + } + } + cmsDatas.value = changeQuestionData(res.datas) + tableLoading.value = false + }) + .catch((e: any) => { + ElMessage({ + message: '鍒楄〃鑾峰彇澶辫触', + type: 'error' + }) + tableLoading.value = false + console.log(e) + }) +} + +// 澶勭悊棰樼洰鏁版嵁缁撴瀯 +const changeQuestionData = (res: any) => { + try { + let list = [] + list = res?.map((item: any) => { + try { + if (item.Embedded_QuestionBank_Stem) { + item.questionStem = JSON.parse(item.Embedded_QuestionBank_Stem) + } + if ( + item.Embedded_QuestionBank_Option && + item.Embedded_QuestionBank_Option.indexOf('[') > -1 + ) { + item.questionOption = JSON.parse(item.Embedded_QuestionBank_Option) + } + if ( + item.Embedded_QuestionBank_Answer && + item.Embedded_QuestionBank_Answer.indexOf('[') > -1 + ) { + item.Embedded_QuestionBank_Answer = JSON.parse(item.Embedded_QuestionBank_Answer) + } + return { + ...item, + questionType: item.Embedded_QuestionBank_QuestionType, + questionAnalysisCon: item.Embedded_QuestionBank_AnalysisCon, + questionAnswer: item.Embedded_QuestionBank_Answer, + customAnswer: null + } + } catch (error) { + console.log(item) + } + }) + getTaskDetail() + return list + } catch (error) { + console.log(error) + return [] + } +} + +const findIndexByValue = (res: any, type: string) => { + for (let i = 0; i < res.length; i++) { + if (res[i].value == type) { + return i + } + } + return -1 // 濡傛灉鏈壘鍒帮紝鍒欒繑鍥� -1 +} + +// 鑾峰彇鏈彁浜や换鍔″垪琛� +const getUnSubmitList = (filter?: any, search?: any) => { + const filterList = filter ?? [] + const searchList = search ?? [] + const data = { + start: (pages.page - 1) * pages.pageSize, + size: pages.pageSize, + taskId: classInfo?.taskWorkId, + classId: classInfo?.id, + filterList, + searchList + } + MG.edu + .getUnSubmitList(data) + .then((res: any) => { + const { datas, totalSize } = res + pages.loading = false + pages.count = totalSize + if (datas.length > 0) { + dataList.value = datas.map((item: any, index: number) => { + const userInfo = item.appUser?.infoList[0] ?? null + item.appUser.name = userInfo.name + item.appUser.icon = userInfo.icon + return { + ...item, + index: index + 1, + createDate: moment(item.createDate).format('YYYY-MM-DD'), + appUserId: item.appUser.id + } + }) + pages.count = totalSize + } + }) + .catch((err: any) => { + console.log(err) + }) +} + +// 鍏抽棴 +const close = () => { + otherVisible.value = false +} + +// 涓昏棰樻彁浜� +const judgeUpdate = (item: any) => { + const listData = [...cacheDate.value] + let judgeScore = 0 + if (item) { + const requestData = { + classId: classInfo?.id, + requests: [] + } + const data = JSON.parse(item) + listData.forEach((citem: any) => { + const strData = data.find((i: any) => i.parentId == citem.id) + if (strData) { + citem.updateTaskSubmitCmsItemRequests = data.map((uitem: any) => { + judgeScore += uitem.score + return { + linkId: uitem.updateId, + score: uitem.score, + answer: uitem.answer, + state: 'Normal', + comments: 'judge' + } + }) + } + }) + let dataobj = null + dataobj = listData.find((litem) => litem.id == currentWorkId.value) + dataobj.state = 'Normal' + dataobj.result = dataobj.result + judgeScore + requestData.requests = [dataobj] + MG.edu + .updateTaskSubmit(requestData) + .then((res: any) => { + if (res) { + otherVisible.value = false + getTaskDetail() + } + }) + .catch((err: any) => { + console.log(err) + }) + } +} + +//鏁扮粍鍘婚噸 +const deduplicateArray = (arr: any, idKey: string) => { + const seen: any = {} + const deduplicatedArray = arr.filter((item: any) => { + const id = item[idKey] + if (!seen[id]) { + seen[id] = true + return true + } + return false + }) + + return deduplicatedArray +} + +// 鍌氦浣滀笟 +const remindWork = (item: any) => { + const content = classInfo?.name + '鐝�' + item.appUser.name + '鍚屽锛岃鍙婃椂鎻愪氦浣滀笟' + const data = { + description: '', + icon: '', + state: 'Normal', + topicIdOrRefCode: String(sessionStorage.messageId), + name: '鏈氦浣滀笟浜哄憳', + content, + type: 'Normal', + cmsTypeRefCode: '', + newDataListRequest: [] + } + MG.ugc + .newTopicMessage(data) + .then((res: any) => { + if (res) { + ElMessage({ + type: 'success', + message: '宸插偓浜�' + }) + } + }) + .catch((err: any) => { + console.log(err) + }) +} + +// 浣滀笟鎼滅储 +const searchData = () => { + const data = [ + { + compareType: 'Contains', + keywords: searchKey.value, + field: 'Name' + } + ] + pages.page = 1 + if (workState.value != 'WaitSubmit') { + getTaskDetail(undefined, searchKey.value ? data : []) + } else { + getUnSubmitList(undefined, searchKey.value ? data : []) + } +} + +const goBack = () => { + router.go(-1) +} +</script> +<style lang="less" scoped> +.classManagePage-box { + background: #fff; + + .classManagePage-nav { + width: 100%; + padding: 0 20px; + height: 40px; + border-bottom: 1px solid #e6e8ed; + position: sticky; + top: 0; + z-index: 999; + display: flex; + align-items: center; + background: #fff; + } + .classManagePage-content { + width: 100%; + position: relative; + .backBtn { + width: 100%; + height: 45px; + margin-bottom: 10px; + padding: 0 20px; + display: flex; + align-items: center; + position: sticky; + top: 40px; + z-index: 99; + background: #fff; + box-shadow: 0px 0px 20px 1px #eeeeee83; + } + .contentBox { + width: 100%; + padding: 0 20px; + box-sizing: border-box; + .content-title-box { + padding: 0 10px; + display: flex; + justify-content: flex-start; + align-items: center; + border-left: 4px solid #ff6d00; + span { + margin-right: 15px; + } + } + .content-user-box { + width: 100%; + padding: 10px 10px; + box-sizing: border-box; + display: flex; + overflow-x: auto; + .user-info-box { + width: auto; + display: flex; + align-items: center; + padding: 10px 15px; + .user-info-data-box { + flex: 1; + height: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; + margin-left: 10px; + .user-name { + padding: 6px 0; + } + .user-num { + padding: 6px 0; + color: #666; + font-size: 12px; + white-space: nowrap; + } + } + } + } + .content-user-box::-webkit-scrollbar { + height: 3px; + } + .content-user-box::-webkit-scrollbar-thumb { + background-color: #ff6d00; + cursor: pointer; + } + .content-user-box::-webkit-scrollbar-track-piece { + background: #eee; + } + .content-tab-box { + .content-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + .searchBox { + width: 300px; + float: left; + padding: 10px 0; + .searchBtn { + background-color: var(--el-color-primary); + color: #fff; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + } + + .content-list-box { + .headerCellClassName { + .cell { + text-align: center; + } + } + } + } + } + } + ::v-deep(.customDialog) { + border-radius: 5px; + margin: 10px auto; + padding-bottom: 20px; + .pubContent { + position: relative; + height: 80vh; + } + } + .pageBox { + padding: 10px 0; + display: flex; + justify-content: flex-end; + } +} +</style> -- Gitblit v1.9.1