From b15a997e95d715c41df3a76aecbf58ec1141ab53 Mon Sep 17 00:00:00 2001 From: qiyunfeng-create <1940665526@qq.com> Date: 星期四, 21 八月 2025 18:37:17 +0800 Subject: [PATCH] 个人中心-接口测试 --- src/views/personalCenter/course.vue | 654 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 651 insertions(+), 3 deletions(-) diff --git a/src/views/personalCenter/course.vue b/src/views/personalCenter/course.vue index 68d9d97..9652dc9 100644 --- a/src/views/personalCenter/course.vue +++ b/src/views/personalCenter/course.vue @@ -1,7 +1,655 @@ <template> - <div class="myBook"> - <div class="myBook_header"> - <div class="myBook_header_title">鎴戠殑璇剧▼</div> + <div class="coursePage"> + <div class="personalPage-title">鎴戠殑璇剧▼</div> + <div class="headerBox"> + <div class="searchBox"> + <el-input + v-model="searchKey" + clearable + @clear="getData" + placeholder="璇疯緭鍏ュ叧閿瓧" + > + <template #append> + <el-button type="primary" class="searchBtn" :icon="Search" @click="getData" /> + </template> + </el-input> + </div> + <el-button type="primary" class="applyStartClasses" @click="applyCourse" + >鐢宠寮�璇�</el-button + > </div> + <div class="courseListBox" v-loading="pages.loading"> + <div + class="courseItem" + v-for="(item, index) in courseList" + :key="index" + @click="gotoDetail(item)" + > + <div class="itemHeader"> + <div class="title" :title="item.name">{{ item.name }}</div> + </div> + <div class="reasonBox"> + <el-tooltip placement="right-end" effect="light" class="box-item"> + <template #content> + <div style="width: 300px" v-html="item.reason"></div> + </template> + <span v-if="item.applyState == 'Reject'" style="color: red"> + 鎷掔粷鍘熷洜锛歿{ item.reason != "" ? item.reason : "-" }} + </span> + </el-tooltip> + <el-button + v-if="item.applyState == 'Reject'" + type="primary" + size="small" + style="margin-left: 20px" + @click="reapplyCourse(item)" + >閲嶆柊鐢宠</el-button + > + </div> + + <div class="itemInfo"> + <div class="imgBox autoImgBox"> + <div + class="stateIcon" + v-if="item.applyState == 'Normal'" + style="background-color: #1dbd11" + > + 浣跨敤涓� + </div> + <div + class="stateIcon" + v-if="item.applyState == 'WaitAudit'" + style="background-color: #ef9f29" + > + 瀹℃牳涓� + </div> + <div + class="stateIcon" + v-if="item.applyState == 'Reject'" + style="background-color: red" + > + 鏈�氳繃 + </div> + <img :src="item.icon" /> + </div> + <div class="infoBox"> + <p class="id">ID锛歿{ item.id }}</p> + <div class="introduction" :title="item.introduction"> + {{ item.introduction }} + </div> + </div> + </div> + </div> + </div> + <div class="pagination-box" v-if="courseList.length > 0"> + <el-pagination + v-model:current-page="pages.page" + v-model:page-size="pages.pageSize" + :background="false" + layout="total, prev, pager, next" + :total="pages.count" + @current-change="pageChange" + /> + </div> + <div class="nullBox" v-if="!pages.loading && courseList.length == 0"> + <el-empty /> + </div> + <!-- 鐢宠寮�璇惧脊妗� --> + <el-dialog v-model="applyCourseDialog" width="750" align-center> + <template #title>{{ editData ? "閲嶆柊鐢宠" : "鐢宠寮�璇�" }}</template> + <el-form + :model="formData" + label-position="left" + ref="dialogFormRef" + label-width="80px" + > + <el-form-item + label="璇剧▼鍚嶇О" + prop="name" + :rules="[{ required: true, message: '璇疯緭鍏ヨ绋嬪悕绉�' }]" + > + <el-input v-model="formData.name" placeholder="璇疯緭鍏ヨ绋嬪悕绉�" /> + </el-form-item> + <el-form-item + v-if="!editData" + label="鍏宠仈鏁欐潗" + prop="bookName" + :rules="[{ required: true, message: '璇烽�夋嫨鏁欐潗' }]" + > + <div style="display: flex"> + <el-input v-model="formData.bookName" disabled="true" style="width: 300px" /> + <el-button style="margin-left: 10px" @click="selectBook">閫夋嫨鏁欐潗</el-button> + </div> + </el-form-item> + <el-form-item label="璇剧▼浠嬬粛"> + <el-input + v-model="formData.desc" + type="textarea" + autocomplete="off" + maxlength="300" + show-word-limit + rows="7" + placeholder="璇疯緭鍏ヨ绋嬩粙缁�" + /> + </el-form-item> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button @click="applyCourseDialog = false">鍙栨秷</el-button> + <el-button type="primary" @click="submit" :loading="submitLoading" + >鎻愪氦</el-button + > + </div> + </template> + </el-dialog> + <!-- 閫夋嫨鏁欐潗寮规 --> + <el-dialog v-model="selectTextBookDialog" width="1000" align-center> + <template #title>閫夋嫨鏁欐潗</template> + <div class="textBookList" v-loading="textBookPages.loading"> + <div class="headerBox" style="padding: 10px"> + <div class="searchBox" style="float: right"> + <el-input + v-model="selectName" + @clear="getTextBook" + clearable + placeholder="璇疯緭鍏ュ叧閿瓧" + > + <template #append> + <el-button + type="primary" + class="searchBtn" + :icon="Search" + @click="getTextBook" + /> + </template> + </el-input> + </div> + </div> + <div style="min-height: 370px" v-if="textBookListData.length > 0"> + <div + v-for="(item, index) in textBookListData" + :key="index" + class="textBookItem" + > + <el-checkbox + class="checkBox" + v-model="item.check" + @change="selectChange(item)" + /> + <div class="imgBox autoImgBox"> + <img :src="item.img" /> + </div> + <p>{{ item.product.name }}</p> + </div> + </div> + <div + class="nullBox" + v-if="!textBookPages.loading && textBookListData.length == 0" + > + <el-empty /> + </div> + </div> + <div class="pagination-box" v-if="textBookListData.length > 0"> + <el-pagination + v-model:current-page="textBookPages.page" + v-model:page-size="textBookPages.pageSize" + :background="false" + layout="total, prev, pager, next" + :total="textBookPages.count" + @current-change="handleCurrentChange" + /> + </div> + <template #footer> + <div class="dialog-footer"> + <el-button @click="selectTextBookDialog = false">鍙栨秷</el-button> + <el-button type="primary" @click="selectTextBookSubmit">纭畾</el-button> + </div> + </template> + </el-dialog> </div> </template> + +<script setup lang="ts"> +import { reactive, ref, onMounted, inject, watch } from "vue"; +import { Search } from "@element-plus/icons-vue"; +import { useRouter, useRoute } from "vue-router"; +import { ElMessage } from "element-plus"; +// eslint-disable-next-line +import { getPublicImage } from "@/assets/js/middleGround/tool.js"; +// eslint-disable-next-line +import defaultImg from "@/assets/images/default-book-img.png"; + +const router: any = useRouter(); +const route: any = useRoute(); +const MG: any = inject("MG"); +const selectName = ref(""); + +// 鐢宠寮�璇鹃槻鎶杔oading +const submitLoading = ref(false); + +const courseList: any = ref([]); + +onMounted(() => { + getData(); +}); + +const searchKey = ref(""); +const pages = reactive({ + page: 1, + pageSize: 6, + count: 0, + loading: true, +}); + +// 鑾峰彇璇剧▼ +const getData = () => { + pages.loading = true; + MG.edu + .getAppCourseList({ + size: pages.pageSize, + start: pages.pageSize * pages.page - pages.pageSize, + sort: { + type: "Desc", + field: "CreateDate", + }, + filterList: [], + searchList: searchKey.value + ? [ + { + keywords: searchKey.value, + field: "Name", + compareType: "Contains", + }, + ] + : [], + }) + .then((res: any) => { + pages.loading = false; + pages.count = res.totalSize; + courseList.value = res.datas.map((item: any) => { + return { + ...item, + name: item.name, + id: item.id, + icon: item.icon != "default" ? getPublicImage(item.icon, 80) : defaultImg, + introduction: item.description, + reason: item.applyReturnMsg ? JSON.parse(item.applyReturnMsg).reason : "", + }; + }); + }); +}; + +// 鐢宠寮�璇� +const applyCourse = () => { + editData.value = null; + formData.value = { + name: "", + bookName: "", + bookId: "", + selectData: "", + desc: "", + }; + applyCourseDialog.value = true; +}; + +const editData: any = ref(null); +const reapplyCourse = (data: any) => { + editData.value = data; + formData.value = { + name: data.name, + bookName: data.linkProduct.name, + bookId: data.linkProduct.id, + selectData: "", + desc: data.description, + }; + applyCourseDialog.value = true; +}; + +// 鐢宠鏁欐潗寮规 +const applyCourseDialog = ref(false); +const selectTextBookDialog = ref(false); +const formData = ref({ + name: "", + bookName: "", + bookId: "", + selectData: "", + desc: "", +}); + +const selectChange = (select: any) => { + for (let i = 0; i < textBookListData.value.length; i++) { + const item: any = textBookListData.value[i]; + if (item.id == select.id) { + item.check = true; + } else { + item.check = false; + } + } +}; + +const selectTextBookSubmit = () => { + const selectData: any = textBookListData.value.filter((item: any) => item.check)[0]; + if (!selectData?.product?.id) { + ElMessage.warning("璇烽�夋嫨寮�璇炬暀鏉愶紒"); + return false; + } + formData.value.bookId = selectData.product.id; + formData.value.bookName = selectData.product.name; + formData.value.selectData = selectData; + selectTextBookDialog.value = false; +}; + +const submit = () => { + submitLoading.value = true; + if (editData.value) { + MG.edu + .updateCourse({ + courseId: editData.value.id, + name: formData.value.name, + description: formData.value.desc, + }) + .then((res: any) => { + MG.edu + .updateCourseApply({ + courseId: editData.value.id, + applyData: JSON.stringify({ + textBookId: formData.value.bookId, + textBookName: formData.value.bookName, + }), + }) + .then((ares: any) => { + ElMessage.success("璇剧▼宸查噸鏂扮敵璇凤紝绛夊緟绠$悊鍛樺鏍搞��"); + applyCourseDialog.value = false; + getData(); + }); + }); + } else { + if (formData.value.name == "") { + ElMessage({ + type: "warning", + message: "璇峰~鍐欒绋嬪悕绉�", + }); + submitLoading.value = false; + return false; + } + if (!formData.value.bookId) { + ElMessage({ + type: "warning", + message: "璇烽�夋嫨鍏宠仈鏁欐潗", + }); + submitLoading.value = false; + return false; + } + MG.edu + .applyNewCourse({ + name: formData.value.name, + description: formData.value.desc, + content: "", + icon: formData.value.selectData.product.icon ?? "default", + type: "course", + config: "", + applyData: JSON.stringify({ + textBookId: formData.value.bookId, + textBookName: formData.value.bookName, + }), + linkProductId: formData.value.bookId, + maxClassCount: 999, + payPrice: 0, + }) + .then((res: any) => { + if (res) { + ElMessage.success("璇剧▼宸茬敵璇凤紝绛夊緟绠$悊鍛樺鏍搞��"); + applyCourseDialog.value = false; + getData(); + } + }); + } + formData.value.selectData = ""; + setTimeout(() => { + submitLoading.value = false; + }, 1000); +}; + +// 鑾峰彇宸茶喘涔扮殑鏁欐潗鍒楄〃 +const textBookPages = reactive({ + page: 1, + pageSize: 12, + count: 0, + loading: false, +}); +const textBookListData = ref([]); + +const getTextBook = () => { + textBookPages.loading = true; + const searchData = [ + { + keywords: "jsek_digitalTextbooks", + field: "ProductType", + }, + { + keywords: "jsek_mediaBook", + field: "ProductType", + }, + { + keywords: selectName.value, + field: "ProductName", + }, + ]; + const data = { + Size: textBookPages.pageSize, + Start: textBookPages.pageSize * textBookPages.page - textBookPages.pageSize, + sort: { + type: "Desc", + field: "CreateDate", + }, + searchList: searchData, + }; + MG.store + .getPurchasedProductList(data) + .then((res: any) => { + textBookPages.count = res.totalSize; + textBookListData.value = res.datas.map((item: any) => { + return { + ...item, + img: item.product.icon ? getPublicImage(item.product.icon, 80) : defaultImg, + }; + }); + textBookPages.loading = false; + }) + .catch(() => { + textBookPages.loading = false; + }); +}; + +// 閫夋嫨鏁欐潗 +const selectBook = () => { + selectTextBookDialog.value = true; + textBookListData.value = []; + getTextBook(); +}; + +const pageChange = (val: any) => { + pages.page = val; + getData(); +}; +const handleCurrentChange = (val: any) => { + textBookPages.page = val; + getTextBook(); +}; + +const gotoDetail = (data: any) => { + if (data.applyState == "Normal") { + router.push({ + name: "courseDetail", + query: { + courseId: data.id, + }, + }); + } +}; +</script> + +<style lang="less" scoped> +.coursePage { + .headerBox { + padding: 20px; + margin-bottom: 10px; + overflow: hidden; + + .searchBox { + width: 300px; + float: left; + + .searchBtn { + background-color: var(--el-color-primary); + color: #fff; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + + .applyStartClasses { + float: right; + } + } + + .courseListBox { + overflow: hidden; + min-height: 200px; + + .courseItem { + float: left; + width: 46%; + height: 210px; + margin: 0 2% 20px; + border-radius: 8px; + border: 1px solid #efefef; + overflow: hidden; + cursor: pointer; + + .itemHeader { + height: 40px; + line-height: 40px; + padding: 0 20px; + background-color: #f8f8f8; + .title { + font-weight: 600; + } + + div { + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + word-break: break-all; + } + } + + .reasonBox { + display: flex; + padding: 5px 20px; + cursor: default; + span { + font-size: 12px; + line-height: 24px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + .itemInfo { + padding: 10px 20px; + flex: 1; + display: flex; + .imgBox { + width: 90px; + height: 120px; + margin-right: 20px; + } + .infoBox { + flex: 1; + font-size: 14px; + p { + margin-bottom: 10px; + } + .introduction { + height: 88px; + line-height: 22px; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 4; + overflow: hidden; + text-overflow: ellipsis; + word-break: break-all; + } + } + .stateIcon { + position: absolute; + right: -6px; + top: -4px; + padding: 5px 8px; + color: #fff; + border-top-left-radius: 30px; + border-bottom-right-radius: 30px; + border-top-right-radius: 30px; + z-index: 99; + } + } + } + } +} + +.textBookList { + overflow: hidden; + margin-bottom: 20px; + .textBookItem { + float: left; + width: 140px; + height: 200px; + margin: 10px; + position: relative; + border: 1px solid #eee; + padding: 20px; + box-sizing: border-box; + .checkBox { + position: absolute; + right: 0; + top: 0; + height: 14px; + ::v-deep { + .el-checkbox__inner { + border-color: #888; + } + } + } + + .imgBox { + width: 100px; + height: 110px; + margin-bottom: 10px; + } + + p { + line-height: 1.2; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + } +} + +.pagination-box { + display: flex; + justify-content: center; + padding: 10px 0; +} + +.nullBox { + text-align: center; + margin-top: 30px; + font-size: 20px; + color: #ccc; +} +</style> -- Gitblit v1.9.1