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/teachingPlan.vue | 891 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 891 insertions(+), 0 deletions(-) diff --git a/src/views/classManage/teachingPlan.vue b/src/views/classManage/teachingPlan.vue new file mode 100644 index 0000000..8df386c --- /dev/null +++ b/src/views/classManage/teachingPlan.vue @@ -0,0 +1,891 @@ +<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="teachPlaneBox"> + <div class="titleBox"> + <div class="titleOptions"> + <span>鏁欏璁″垝</span> + <el-button + v-if="userInfo?.role == 'Teacher'" + @click="openPlan()" + type="primary" + round + >鏂板缓 <el-icon style="margin-left: 3px"><Plus /></el-icon + ></el-button> + </div> + <div class="searchBox"> + <el-input + v-model="searchKey" + clearable + @clear="searchData()" + placeholder="璇疯緭鍏ュ叧閿瓧" + @keydown.enter="searchData()" + > + <template #append> + <el-button + type="primary" + @click="searchData()" + class="searchBtn" + :icon="Search" + /> + </template> + </el-input> + </div> + </div> + <div class="listBox"> + <el-table + :header-cell-style="{ background: '#eee' }" + :data="tableData" + max-height="600px" + style="width: 100%" + v-loading="pages.loading" + > + <el-table-column label="搴忓彿" width="70"> + <template #default="scope"> + <span v-if="scope.row.datas.index">{{ scope.row.datas.index }}</span> + </template> + </el-table-column> + <el-table-column label="鍚嶇О" prop="name"> + <template #default="scope"> + <span v-if="scope.row.datas.Name">{{ scope.row.datas.Name }}</span> + </template> + </el-table-column> + <el-table-column label="瀛︿範绔犺妭" width="300"> + <template #default="scope"> + <div v-if="scope.row.datas.selectChapter?.length > 0"> + <div + @click="toRead(item)" + class="linkTitle" + v-for="(item, index) in scope.row.datas.selectChapter" + :key="index" + > + {{ item.parentName }} + </div> + </div> + </template> + </el-table-column> + <el-table-column label="涓婁紶璧勬簮"> + <template #default="scope"> + <div v-if="scope.row.datas.uploadResources?.length > 0"> + <span + @click="downloadRes(item)" + class="linkTitle" + v-for="(item, index) in scope.row.datas.uploadResources" + :key="index" + > + {{ item.FileName + "." + item.Extension }} + </span> + </div> + </template> + </el-table-column> + <el-table-column label="鍙傝�冭祫鏂�" width="300"> + <template #default="scope"> + <span v-if="scope.row.datas.referenceMaterial">{{ + scope.row.datas.referenceMaterial + }}</span> + </template> + </el-table-column> + <el-table-column label="璇存槑" width="300"> + <template #default="scope"> + <span v-if="scope.row.datas.explain">{{ scope.row.datas.explain }}</span> + </template> + </el-table-column> + <el-table-column v-if="userInfo?.role == 'Teacher'" label="鎿嶄綔" width="150"> + <template #default="scope"> + <!-- <el-button + v-if="scope.row" + @click="editOpen(scope.row)" + link + type="primary" + size="small" + > + 缂栬緫 + </el-button> --> + <el-button + v-if="scope.row" + @click="removeTaskItem(scope.row)" + link + type="danger" + size="small" + > + 绉婚櫎 + </el-button> + </template> + </el-table-column> + </el-table> + <el-pagination + style="float: right" + v-model:current-page="pages.page" + :page-size="pages.pageSize" + layout="total, prev, pager, next" + :total="pages.count" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + </div> + <el-dialog v-model="visible" destroy-on-close title="鏂板缓鏁欏璁″垝" width="1000"> + <div class="formBox"> + <el-row> + <el-col :span="2" class="labelItem"> + <div class="grid-content ep-bg-purple" /> + 鍚嶇О<span style="color: red">*</span> + </el-col> + <el-col :span="20"> + <div class="grid-content ep-bg-purple-light" /> + <el-input + v-model="taskItem.title" + placeholder="璇峰~鍐欏悕绉�" + size="large" + clearable + /> + </el-col> + </el-row> + <el-row> + <el-col :span="2" class="labelItem"> + <div class="grid-content ep-bg-purple" /> + 閫夋嫨绔犺妭<span style="color: red">*</span> + </el-col> + <el-col :span="20" style="position: relative" v-if="classInfo?.bookRefCode"> + <div class="grid-content ep-bg-purple-light" /> + <div + :class="dynamicList.length > 1 ? 'selectBox selectMarBot' : 'selectBox'" + v-for="(item, index) in dynamicList" + :key="index" + > + <el-cascader + size="large" + style="width: 620px; margin-right: 10px" + :options="chapterList" + clearable + @change="parentSelect($event, item)" + > + <template #default="{ node, data }"> + <span>{{ data.label }}</span> + <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span> + </template> + </el-cascader> + </div> + <div class="btngroup"> + <el-button + type="primary" + @click="addGroup" + style="height: 40px" + :icon="Plus" + /> + <el-button + type="warning" + :disabled="dynamicList.length == 1" + @click="reduceGroup" + style="height: 40px" + :icon="Minus" + /> + </div> + </el-col> + <el-col :span="20" style="position: relative" v-else> + <div class="grid-content ep-bg-purple-light" /> + <div + :class="dynamicList.length > 1 ? 'selectBox selectMarBot' : 'selectBox'" + v-for="(item, index) in dynamicList" + :key="index" + > + <div class="inputBox"> + <el-input + type="text" + placeholder="璇疯緭鍏ョ珷" + style="width: 300px; margin-right: 15px" + v-model="item.parentVal" + ></el-input> + <el-input + type="text" + placeholder="璇疯緭鍏ヨ妭" + style="width: 300px" + v-model="item.childVal" + ></el-input> + </div> + <div class="btngroup"> + <el-button + type="primary" + @click="addGroup" + style="height: 40px" + :icon="Plus" + /> + <el-button + type="warning" + :disabled="dynamicList.length == 1" + @click="reduceGroup" + style="height: 40px" + :icon="Minus" + /> + </div> + </div> + </el-col> + </el-row> + <el-row> + <el-col :span="2" class="labelItem"> + <div class="grid-content ep-bg-purple" /> + 涓婁紶璧勬簮<span style="color: red">*</span> + </el-col> + <el-col :span="20"> + <div class="grid-content ep-bg-purple-light" /> + <!-- <el-upload + class="upload" + :http-request="fileUpload" + :show-file-list="false" + :action="'#'" + > + <el-button type="primary" size="large" + ><el-icon size="large" style="margin-right: 5px"><DocumentAdd /></el-icon + >涓婁紶</el-button + > + </el-upload> --> + <el-upload + class="upload" + drag + action="#" + multiple + :http-request="fileUpload" + > + <el-icon class="el-icon--upload"><upload-filled /></el-icon> + <div class="el-upload__text">鎷栨嫿鎴栫偣鍑绘枃浠朵笂浼�</div> + </el-upload> + </el-col> + </el-row> + <el-row> + <el-col :span="2" class="labelItem"> + <div class="grid-content ep-bg-purple" /> + 鍙傝�冭祫鏂� + </el-col> + <el-col :span="20"> + <div class="grid-content ep-bg-purple-light" /> + <el-input + placeholder="璇峰~鍐欏弬鑰冭祫鏂�" + type="textarea" + :rows="8" + size="large" + clearable + v-model="taskItem.referenceMaterial" + /> + </el-col> + </el-row> + <el-row> + <el-col :span="2" class="labelItem"> + <div class="grid-content ep-bg-purple" /> + 璇存槑 + </el-col> + <el-col :span="20"> + <div class="grid-content ep-bg-purple-light" /> + <el-input + v-model="taskItem.explain" + placeholder="璇峰~鍐欒鏄�" + type="textarea" + :rows="8" + size="large" + clearable + /> + </el-col> + </el-row> + </div> + <template #footer> + <div class="dialog-footer"> + <el-button type="primary" :loading="newLoading" @click="newTaskCmsItems"> + 纭 + </el-button> + </div> + </template> + </el-dialog> + </div> + </div> +</template> + +<script setup lang="ts"> +import { Search, ArrowRight, Plus, Minus } from "@element-plus/icons-vue"; +import { ElMessage } from "element-plus"; +import { reactive, ref, onMounted, inject, watch } from "vue"; +import { useRoute } from "vue-router"; +import axios from "axios"; + +const route: any = useRoute(); +const MG: any = inject("MG"); +const config: any = inject("config"); +const tool: any = inject("toolClass"); +const classInfo = JSON.parse(route.query.classInfo); +const userInfo = ref(); +const searchKey = ref(""); +const visible = ref(false); +const dynamicList: any = ref([]); +const tableData: any = ref([]); +const classItem = ref([]); +const fileList: any = ref([]); +const chapterList: any = ref([]); +const childrenList: any = ref([]); +const taskData: any = ref(); +// 鏂板缓鏁欏璁″垝闃叉姈 +const newLoading = ref(false); +const teachPlanvalue = ref(""); +const taskItem = reactive({ + title: "", + selectChapter: "", + referenceMaterial: "", + explain: "", + uploadResources: "", +}); +let pages = reactive({ + page: 1, + pageSize: 13, + count: 0, + loading: false, +}); + +onMounted(() => { + const list = [{ key: 1, parentVal: "", childVal: "" }]; + dynamicList.value = list; + const userCache: any = localStorage.getItem(config.userInfoKey); + if (userCache) { + userInfo.value = JSON.parse(userCache); + } + pages.loading = true; + getTaskList(); +}); + +const searchData = () => { + pages.page = 1; + getTaskCmsList(); +}; + +const openPlan = () => { + visible.value = true; + taskItem.title = ""; + taskItem.selectChapter = ""; + taskItem.referenceMaterial = ""; + taskItem.explain = ""; + taskItem.uploadResources = ""; + dynamicList.value = [{ key: 1, parentVal: "", childVal: "" }]; + fileList.value = []; +}; + +const reduceGroup = () => { + dynamicList.value.pop(); +}; + +const addGroup = () => { + const source = dynamicList.value[dynamicList.value.length - 1]; + const obj = { key: source.key++, parentVal: "", childVal: "" }; + dynamicList.value.push(obj); +}; + +const handleSizeChange = (val: number) => { + pages.pageSize = val; + getTaskCmsList(); +}; + +const handleCurrentChange = (val: number) => { + pages.page = val; + getTaskCmsList(); +}; + +// 鏂板缓浠诲姟 +const newTask = () => { + const data = { + name: classInfo?.name + "鏁欏璁″垝", + description: "", + icon: "", + type: config.taskType.teachingPlan, + state: "Normal", + groupId: classInfo?.id, + order: 0, + beginDate: "2024-09-09T03:38:07.167Z", + endDate: "2024-09-09T03:38:07.167Z", + duration: 0, + }; + MG.edu + .newTask(data) + .then((res: any) => {}) + .catch((e: any) => { + console.log(e); + }); +}; + +// 鑾峰彇浠诲姟鍒楄〃 +const getTaskList = () => { + const data = { + start: 0, + size: 10, + filterList: [ + { + value: config.taskType.teachingPlan, + field: "Type", + subFilters: [], + }, + ], + searchList: [], + groupId: classInfo?.id, + }; + MG.edu + .getTaskList(data) + .then((res: any) => { + if (res.datas.length == 0 && userInfo.value.role == "Teacher") { + newTask(); + } + if (res.datas.length > 0) { + taskData.value = res.datas[0]; + classInfo.taskId = taskData.value?.id; + classInfo.rootTaskCmsId = taskData.value?.rootCmsItemId; + } + getTypeByCode(); + if (classInfo.bookRefCode) { + getCatalogueList(); + } + }) + .catch((e: any) => { + console.log(e); + }); +}; + +// 鍓嶅線闃呰鍣� +const toRead = (item: any) => { + // config.textReaderUrl + // 'http://192.168.3.132:8005/#/home' + if (classInfo.bookRefCode) { + const url = + config.textReaderUrl + + "?bookId=" + + classInfo?.bookRefCode + + "&token=" + + localStorage.getItem(config.tokenKey) + + "&chapter=" + + item.parentVal + + "&startPage=" + + item.childVal; + window.open(url, "_blank"); + } else { + ElMessage.warning("褰撳墠绔犺妭鏃犳硶璺宠浆"); + } +}; + +// 涓嬭浇涓婁紶璧勬簮 +const downloadRes = (item: any) => { + const url = config.requestCtx + "/file/api/ApiDownload?md5=" + item.Md5; + window.open(url, "_blank"); +}; + +// 閫夋嫨鍣� +const parentSelect = (val: any, item: any) => { + if (val?.length) { + const str = val[2]; + const obj = findObj(chapterList.value, str); + item.parentVal = obj.chapter; + item.childVal = obj.start; + } +}; + +// 鏂囦欢涓婁紶 +const fileUpload = (file: any) => { + return new Promise((resolve, reject) => { + // const isJPG = file.file.type === 'image/jpeg' || file.file.type === 'image/png' + // const isLt2M = (0.3 * file.file.size) / 1024 / 1024 < 0.3 + // if (!isJPG) { + // ElMessage.error('涓婁紶鏂囦欢鍙兘鏄� jpg/png 鏍煎紡!') + // return reject() + // } + // if (!isLt2M) { + // ElMessage.error('涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 300KB!') + // return reject() + // } + const FileName = file.file.name.split(".")[0]; + const Extension = file.file.name.split(".")[1]; + const FileType = file.file.type; + let size = 1024; + tool + .getFileMd5(file.file, size * 1024) + .then((e: string) => { + if (!fileList.value.find((item: any) => item.md5 == e)) { + const imgData = new FormData(); + imgData.append("Md5", e); + imgData.append("FileName", FileName); + imgData.append("Extension", Extension); + imgData.append("FileType", FileType); + imgData.append("MetaData", null); + imgData.append("file", file.file); + MG.file.upload(imgData).then(() => { + fileList.value.push({ + md5: e, + linkType: "LinkFile", + linkProtectType: "Public", + fileName: FileName, + extension: Extension, + url: config.requestCtx + `鈥�/file鈥�/api鈥�/ApiDownload?md5=` + e, + }); + }); + } else { + ElMessage.warning("褰撳墠鏂囦欢宸蹭笂浼狅紝璇峰嬁閲嶅鎿嶄綔锛�"); + } + }) + .catch((e: any) => { + console.error(e); + }); + }); +}; + +// 鑾峰彇绔犺妭鐩綍 +const getCatalogueList = () => { + const url = + config.requestCtx + "/books/resource/" + classInfo?.bookRefCode + "/information.json"; + axios + .get(url) + .then((res) => { + if (res.data?.data.length > 0) { + const datas = res.data.data; + const list = datas?.filter((item: any) => item.children?.length > 0); + chapterList.value = changeCascaderData(list); + } + }) + .catch((e) => { + console.log(e); + }); +}; + +// 閫掑綊鏇存暟缁� +const changeCascaderData = (data: any) => { + for (const item of data) { + item.value = item.start; + if (item.children?.length > 0) { + changeCascaderData(item.children); + } + } + return data; +}; + +// 閫掑綊鏌ユ壘 +const findObj = (arr: any, val: any) => { + for (let i = 0; i < arr.length; i++) { + const obj = arr[i]; + if (obj.start === val) { + return obj; // 鎵惧埌鐩爣瀵硅薄锛岀洿鎺ヨ繑鍥� + } + if (obj.children && obj.children.length > 0) { + // 濡傛灉褰撳墠瀵硅薄鏈夊瓙瀵硅薄锛岄�掑綊鏌ユ壘瀛愬璞� + const found: any = findObj(obj.children, val); + if (found) { + return found; // 鍦ㄥ瓙瀵硅薄涓壘鍒扮洰鏍囧璞★紝杩斿洖 + } + } + } + return null; +}; + +// 鑾峰彇绫诲瀷瀛楁 +const getTypeByCode = () => { + MG.resource + .getCmsTypeByRefCode({ + refCodes: [config.refCodes.teachingPlan], + }) + .then((res: any) => { + const data = res[0]?.cmsTypeLinks[0]?.children; + if (data?.length) { + classItem.value = data; + } + getTaskCmsList(); + }) + .catch((err: any) => { + console.log(err); + }); +}; + +// 鑾峰彇浠诲姟涓嬬殑璧勬簮鍒楄〃 +const getTaskCmsList = () => { + const data = { + start: (pages.page - 1) * pages.pageSize, + size: pages.pageSize, + searchList: searchKey.value + ? [ + { + keywords: searchKey.value, + field: "Name", + compareType: "Contains", + }, + ] + : [], + taskId: classInfo?.taskId, + path: String(classInfo?.rootTaskCmsId), + type: "*", + keys: ["referenceMaterial", "Name", "selectChapter", "uploadResources", "explain"], + }; + MG.edu + .getTaskCmsItem(data) + .then((res: any) => { + pages.loading = false; + pages.count = res.totalSize; + for (let i = 0; i < res.datas.length; i++) { + const item = res.datas[i]; + // 澶勭悊瀛楁 + if (taskItem != null) { + for (let fieldKey in taskItem) { + if (item.datas[fieldKey]) { + const values = JSON.parse(item.datas[fieldKey]); + if (values.length > 0) { + // 鐢ㄥ瓧娈靛悕澶勭悊杩斿洖鐨勫瓧娈靛�� + if (values[0].Value) { + item.datas[fieldKey] = values[0].Value; + } else if (values[0].Data) { + item.datas[fieldKey] = values[0].Data.Value; + } else if (!values[0].Value && values[0].FileList?.length > 0) { + item.datas[fieldKey] = values[0].FileList; + } else { + item.datas[fieldKey] = "-"; + } + if (fieldKey == "selectChapter" && values[0].Value) { + const data = JSON.parse(values[0].Value); + item.datas["selectChapter"] = data.map((citem: any) => { + if (classInfo.bookRefCode) { + const dataS = findObj(chapterList.value, citem.childVal); + return { + ...citem, + parentName: + chapterList.value.find( + (sitem: any) => sitem.chapter == citem.parentVal + )?.label + + "---" + + dataS?.label, + }; + } else { + return { + ...citem, + parentName: citem.parentVal + "---" + citem.childVal, + }; + } + }); + } + if (fieldKey == "selectChapter" && !values[0].Value) { + item.datas["selectChapter"] = []; + } + } + const index = i; + item.datas["index"] = index + 1; + } + } + } + } + tableData.value = res.datas; + }) + .catch((e: any) => { + ElMessage({ + message: "鍒楄〃鑾峰彇澶辫触", + type: "error", + }); + console.log(e); + }); +}; + +// 鍒犻櫎璧勬簮 +const removeTaskItem = (item: any) => { + const data = { + taskId: classInfo?.taskId, + requests: [ + { + cmsItemId: item.id, + path: String(classInfo?.rootTaskCmsId), + }, + ], + }; + MG.edu + .removeTaskCmsItemList(data) + .then((res: any) => { + if (res) { + ElMessage({ + message: "鍒犻櫎鎴愬姛", + type: "success", + }); + getTaskCmsList(); + } + }) + .catch((e: any) => { + ElMessage({ + message: "鍒犻櫎澶辫触", + type: "error", + }); + }); +}; + +// 涓轰换鍔℃柊寤鸿祫婧� +const newTaskCmsItems = () => { + newLoading.value = true; + taskItem.selectChapter = JSON.stringify(dynamicList.value); + if (!taskItem.title) { + ElMessage({ + message: "璇峰~鍐欐暀瀛﹀悕绉�", + type: "warning", + }); + newLoading.value = false; + return false; + } + if (dynamicList.value[0]?.parentVal == "") { + ElMessage({ + message: "璇烽�夋嫨鏁欏绔犺妭", + type: "warning", + }); + newLoading.value = false; + return false; + } + if (fileList.value.length == 0) { + ElMessage({ + message: "璇蜂笂浼犳暀瀛︽枃浠�", + type: "warning", + }); + newLoading.value = false; + return false; + } + const data = { + groupId: classInfo?.id, + taskId: classInfo?.taskId, + accessPath: String(classInfo?.rootTaskCmsId), + newGroupCmsItemRequests: [ + { + name: taskItem.title, + description: "", + icon: "", + type: config.refCodes.teachingPlan, + state: "Normal", + order: 0, + newDataListRequest: tool.worksDataBytool( + classItem.value, + taskItem, + fileList.value + ), + newCmsItemAndFileLinkListRequest: [], + newChildrenListRequest: [], + }, + ], + }; + MG.edu.newTaskCmsItem(data).then((res: any) => { + newLoading.value = false; + if (res) { + ElMessage({ + message: "鏂板缓鎴愬姛", + type: "success", + }); + visible.value = false; + getTaskCmsList(); + } + }); +}; + +// // 缂栬緫璧勬簮 +// const editOpen = (item: any) => { +// visible.value = true +// taskItem.title = item?.datas?.Name +// taskItem.explain = item?.datas?.explain +// taskItem.referenceMaterial = item?.datas?.referenceMaterial +// if (item?.datas?.selectChapter > 0) { +// dynamicList.value = item?.datas?.selectChapter +// chapterList.value?.forEach((item: any) => { +// if (dynamicList.value.find((citem: any) => citem.parentVal == item.chapter)) { +// childrenList.value.push(...item.children) +// } +// }) +// } +// } +</script> + +<style lang="less" scoped> +.classManagePage-box { + padding: 20px; + .classManagePage-nav { + padding-bottom: 20px; + border-bottom: 1px solid #e6e8ed; + margin-bottom: 30px; + } + .classManagePage-content { + width: 100%; + .teachPlaneBox { + width: 100%; + .titleBox { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + .titleOptions { + width: 160px; + display: flex; + justify-content: space-between; + align-items: center; + span { + font-family: PingFang SC; + font-weight: bold; + font-size: 16px; + color: #333; + line-height: 0px; + text-align: left; + } + } + .searchBox { + width: 300px; + float: left; + .searchBtn { + background-color: var(--el-color-primary); + color: #fff; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + } + } + .linkTitle { + color: #ff6c00; + cursor: pointer; + } + .linkTitle:hover { + text-decoration: underline; + } + } + .formBox { + width: 100%; + font-family: PingFang SC; + font-weight: 400; + font-size: 14px; + color: #333333; + + .el-row { + margin-bottom: 20px; + display: flex; + align-items: flex-start; + .labelItem { + text-align: right; + margin-right: 15px; + padding-top: 2px; + } + .selectBox { + border: 1px solid #ddd; + border-radius: 5px; + padding: 20px 30px; + ::v-deep(.inputBox) { + display: flex; + align-items: center; + justify-content: flex-start; + .el-input__wrapper { + padding: 5px 11px; + } + } + } + .selectMarBot { + margin-bottom: 10px; + } + .btngroup { + position: absolute; + top: 20px; + right: 27px; + } + .el-upload-list__item-name { + line-height: 22px; + } + } + } +} +</style> -- Gitblit v1.9.1