|
@@ -0,0 +1,460 @@
|
|
|
+<script>
|
|
|
+/*eslint-disable*/
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="MenuLeft">
|
|
|
+ <img class="logo" src="./assets/img/logo.svg" alt="" />
|
|
|
+ <!-- <img class="logo" src="../../../assets/logo1.png" alt="" /> -->
|
|
|
+
|
|
|
+ <!-- <div id="menuLeft" class="menu commonsScrollbar" v-on:scrollend="handleScrollEnd()" > -->
|
|
|
+ <div ref="scrollDiv" class="menu commonsScrollbar" v-on:scrollend="handleScrollEnd()">
|
|
|
+ <!-- <el-menu default-active="2-2" class="el-menu-vertical-demo" style="width: 200px;"
|
|
|
+ :default-openeds="['2', '3']"
|
|
|
+ @open="handleOpen"
|
|
|
+ @close="handleClose">
|
|
|
+ <el-menu-item index="1">
|
|
|
+ <template #title>
|
|
|
+ <i class="el-icon-s-home"></i>
|
|
|
+ <span>首页</span>
|
|
|
+ </template>
|
|
|
+ </el-menu-item>
|
|
|
+ <el-sub-menu index="2">
|
|
|
+ <template #title>
|
|
|
+ <i class="el-icon-s-order"></i>
|
|
|
+ <span>订单管理</span>
|
|
|
+ </template>
|
|
|
+ <el-menu-item index="2-1">全部订单</el-menu-item>
|
|
|
+ <el-menu-item index="2-2">待付款订单</el-menu-item>
|
|
|
+ <el-menu-item index="2-3">已完成订单</el-menu-item>
|
|
|
+ </el-sub-menu>
|
|
|
+ <el-sub-menu index="3">
|
|
|
+ <template #title>
|
|
|
+ <i class="el-icon-s-custom"></i>
|
|
|
+ <span>客户管理</span>
|
|
|
+ </template>
|
|
|
+ <el-menu-item index="3-1">客户列表</el-menu-item>
|
|
|
+ <el-menu-item index="3-2">新增客户</el-menu-item>
|
|
|
+ </el-sub-menu>
|
|
|
+ </el-menu> -->
|
|
|
+
|
|
|
+ <el-menu
|
|
|
+ :default-active="menuListPrefix"
|
|
|
+ class="elMenuVerticalMenuLeftTwo"
|
|
|
+ :default-openeds="defaultOpeneds"
|
|
|
+ @open="handleOpen"
|
|
|
+ @close="handleClose"
|
|
|
+ >
|
|
|
+ <div class="elMenuVerticalMenuLeftTwo" v-for="(item, index) of menuList" :key="index">
|
|
|
+ <el-sub-menu v-if="item.list != null && item.list != undefined && item.list.length > 0" :index="item.prefix">
|
|
|
+ <template #title>
|
|
|
+ <img
|
|
|
+ class="leftImg"
|
|
|
+ v-if="typeof item.img == 'string' || typeof item.imgNo == 'string'"
|
|
|
+ :src="menuListPrefix == item.prefix ? item.img : item.imgNo"
|
|
|
+ />
|
|
|
+ <span>{{ item.name }}</span>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <el-menu-item
|
|
|
+ v-for="(itemListItem, itemListIndex) of item.list"
|
|
|
+ :key="itemListIndex"
|
|
|
+ v-on:click="menuListEvent(itemListItem, itemListIndex)"
|
|
|
+ :index="itemListItem.prefix"
|
|
|
+ >
|
|
|
+ {{ itemListItem.name }}
|
|
|
+ </el-menu-item>
|
|
|
+ </el-sub-menu>
|
|
|
+
|
|
|
+ <el-menu-item
|
|
|
+ v-if="item.list != null && item.list != undefined && item.list.length <= 0"
|
|
|
+ v-on:click="menuListEvent(item, index)"
|
|
|
+ :index="item.prefix"
|
|
|
+ >
|
|
|
+ <template #title>
|
|
|
+ <img
|
|
|
+ class="leftImg"
|
|
|
+ v-if="typeof item.img == 'string' || typeof item.imgNo == 'string'"
|
|
|
+ :src="menuListPrefix == item.prefix ? item.img : item.imgNo"
|
|
|
+ />
|
|
|
+ <span>{{ item.name }}</span>
|
|
|
+ </template>
|
|
|
+ </el-menu-item>
|
|
|
+ </div>
|
|
|
+ </el-menu>
|
|
|
+
|
|
|
+ <!-- 新增一个固定底部的距离,让它可以继续滚动到更底部范围 -->
|
|
|
+ <div style="width: 80%; height: 15rem; visibility: hidden"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- <div class="bottom">
|
|
|
+
|
|
|
+ <img class="aiRole" src="../../../assets/teacher/main/ai_t.png" alt="" />
|
|
|
+ <img class="aiBtn" src="../../../assets/teacher/main/Group 873.svg" alt="" />
|
|
|
+
|
|
|
+ </div> -->
|
|
|
+
|
|
|
+ <!-- <AiCommonRole :addStyle="'left:7rem;bottom:3.5rem;right:auto;top:auto;'" ></AiCommonRole> -->
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
|
+import { menuLeftTwo } from './stores/menuLeftTwo.ts'
|
|
|
+import { useRouter } from 'vue-router'
|
|
|
+const router = useRouter()
|
|
|
+
|
|
|
+// 接收参数
|
|
|
+const props = defineProps({
|
|
|
+ // 被选中菜单的 prefix
|
|
|
+ menuUrl: {
|
|
|
+ type: String,
|
|
|
+ default: function () {
|
|
|
+ return 'teacher'
|
|
|
+ },
|
|
|
+ },
|
|
|
+})
|
|
|
+
|
|
|
+/**
|
|
|
+ * 当前左侧菜单选中
|
|
|
+ */
|
|
|
+let menuListPrefix = ref('')
|
|
|
+// let menuListPrefix = ref("2-1");
|
|
|
+// 控制默认几个菜单展开
|
|
|
+let defaultOpeneds = ref([])
|
|
|
+// let defaultOpeneds = ref([ "2" ]);
|
|
|
+
|
|
|
+// 通过vue实现控制目标 div 的滚动
|
|
|
+let scrollDiv = ref(null)
|
|
|
+
|
|
|
+/**
|
|
|
+ * 滚动条结束的时候
|
|
|
+ */
|
|
|
+const handleScrollEnd = () => {
|
|
|
+ // let objMenuLeft = document.getElementById("menuLeft");
|
|
|
+ // menuLeftTwo().show.scrollTop = objMenuLeft.scrollTop;
|
|
|
+ // console.log(
|
|
|
+ // "scrollDiv", scrollDiv
|
|
|
+ // );
|
|
|
+
|
|
|
+ menuLeftTwo().show.scrollTop = scrollDiv.value.scrollTop
|
|
|
+}
|
|
|
+
|
|
|
+let menuList = ref([
|
|
|
+ {
|
|
|
+ name: '课程数据总览',
|
|
|
+ img: new URL('./assets/img/MenuLeftTwo/planet-fill-yes.svg', import.meta.url).href,
|
|
|
+ imgNo: new URL('./assets/img/MenuLeftTwo/planet-fill.svg', import.meta.url).href,
|
|
|
+ url: 'teacher',
|
|
|
+ list: [],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '课程管理',
|
|
|
+ img: new URL('./assets/img/MenuLeftTwo/graduation-cap-fill-yes.svg', import.meta.url).href,
|
|
|
+ imgNo: new URL('./assets/img/MenuLeftTwo/graduation-cap-fill.svg', import.meta.url).href,
|
|
|
+ url: '',
|
|
|
+ list: [
|
|
|
+ {
|
|
|
+ name: '班级管理',
|
|
|
+ url: 'teacherClassManage',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '学生管理',
|
|
|
+ url: 'teacherStudentManage',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '课程题库管理',
|
|
|
+ url: 'teacherQuestionBankManage',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '成绩规则自定义',
|
|
|
+ url: 'teacherScoreRules',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ name: '日常教学',
|
|
|
+ img: new URL('./assets/img/MenuLeftTwo/quill-pen-ai-fill-yes.svg', import.meta.url).href,
|
|
|
+ imgNo: new URL('./assets/img/MenuLeftTwo/quill-pen-ai-fill.svg', import.meta.url).href,
|
|
|
+ url: '',
|
|
|
+ list: [
|
|
|
+ {
|
|
|
+ name: '备课PPT生成',
|
|
|
+ url: 'teacherPreClassPreviewGeneratePPT',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '课前预习布置',
|
|
|
+ url: 'teacherPreClassPreviewAssignment',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '课后作业布置',
|
|
|
+ url: 'teacherHomeworkAssignmentAfterClass',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '课程教学出卷',
|
|
|
+ url: 'teacherCourseTeachingPaperOutput',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ name: '教学资源训练库',
|
|
|
+ img: new URL('./assets/img/MenuLeftTwo/brush-ai-fill-yes.svg', import.meta.url).href,
|
|
|
+ imgNo: new URL('./assets/img/MenuLeftTwo/brush-ai-fill.svg', import.meta.url).href,
|
|
|
+ url: '',
|
|
|
+ list: [
|
|
|
+ {
|
|
|
+ name: '资源库',
|
|
|
+ url: 'teacherResourceLibrary',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '课本教程训练',
|
|
|
+ url: 'teacherTextbookTutorialTraining',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ name: 'AI工具箱',
|
|
|
+ img: new URL('./assets/img/MenuLeftTwo/Frame-yes.svg', import.meta.url).href,
|
|
|
+ imgNo: new URL('./assets/img/MenuLeftTwo/Frame.svg', import.meta.url).href,
|
|
|
+ url: 'teacherAiToolbox',
|
|
|
+ list: [],
|
|
|
+ },
|
|
|
+])
|
|
|
+
|
|
|
+const handleOpen = (key, keyPath) => {
|
|
|
+ // console.log("handleOpen", key, keyPath);
|
|
|
+ for (let i = 0; i < keyPath.length; i++) {
|
|
|
+ let key = keyPath[i]
|
|
|
+ menuLeftTwo().show.listJson[key] = key
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handleClose = (keyOld, keyPath) => {
|
|
|
+ // console.log("handleClose", keyOld, keyPath);
|
|
|
+ for (let i = 0; i < keyPath.length; i++) {
|
|
|
+ let key = keyPath[i]
|
|
|
+ menuLeftTwo().show.listJson[key] = null
|
|
|
+ delete menuLeftTwo().show.listJson[key]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取缓存,更新菜单的选中展示
|
|
|
+ */
|
|
|
+const defaultOpenedsJsonLookEvent = () => {
|
|
|
+ for (let key in menuLeftTwo().show.listJson) {
|
|
|
+ defaultOpeneds.value.push(key)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 自动更新菜单的结构
|
|
|
+ * array 被转换的数组
|
|
|
+ * prefix 可以不传或者传 null, 当内容存在,则对应的前缀拼接方式则追加
|
|
|
+ * prefixOld 原始应该菜单唯一值
|
|
|
+ */
|
|
|
+const menuListUpdateEvent = (array, prefix, prefixOld) => {
|
|
|
+ for (let i = 0; i < array.length; i++) {
|
|
|
+ let thisPrefix = '' + (i + 1)
|
|
|
+ let prefixNew = prefix != null && typeof prefix == 'string' ? prefix + thisPrefix : thisPrefix
|
|
|
+ let thisArray = array[i]
|
|
|
+ thisArray['prefix'] = prefixNew
|
|
|
+
|
|
|
+ // 本次追加的数组数据
|
|
|
+ let addArray = []
|
|
|
+
|
|
|
+ if (typeof thisArray['list'] != 'undefined' && thisArray['list'].length > 0) {
|
|
|
+ addArray = menuListUpdateEvent(thisArray['list'], prefixNew + '-', prefixNew)
|
|
|
+ thisArray['list'] = addArray
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断控制默认选中
|
|
|
+ let url = thisArray?.url
|
|
|
+ if (typeof url == 'string' && url == props.menuUrl) {
|
|
|
+ menuListPrefix.value = prefixNew
|
|
|
+ // defaultOpeneds.value.push(prefixOld);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return array
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 这里需要比较早做处理,不要在 onMounted 方法里触发,否则会发现,默认展开菜单逻辑会没有效果
|
|
|
+ */
|
|
|
+defaultOpenedsJsonLookEvent()
|
|
|
+// 优先更新菜单的结构
|
|
|
+menuList.value = menuListUpdateEvent(menuList.value, null)
|
|
|
+
|
|
|
+/**
|
|
|
+ * 更新滚动条所在位置
|
|
|
+ */
|
|
|
+const scrollTopEvent = () => {
|
|
|
+ // let objMenuLeft = document.getElementById("menuLeft");
|
|
|
+ // objMenuLeft.scrollTop = parseFloat(menuLeftTwo().show.scrollTop);
|
|
|
+
|
|
|
+ scrollDiv.value.scrollTop = parseFloat(menuLeftTwo().show.scrollTop)
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ // setTimeout(function() {
|
|
|
+ // scrollTopEvent();
|
|
|
+ // }, 250);
|
|
|
+
|
|
|
+ scrollTopEvent()
|
|
|
+})
|
|
|
+
|
|
|
+/**
|
|
|
+ * 菜单切换逻辑
|
|
|
+ * item
|
|
|
+ * index
|
|
|
+ */
|
|
|
+const menuListEvent = (item, index) => {
|
|
|
+ // console.log(
|
|
|
+ // "menuListEvent",
|
|
|
+ // item, index
|
|
|
+ // );
|
|
|
+
|
|
|
+ if (typeof item.url == 'string') {
|
|
|
+ // router.push('/' + item.url)
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.elMenuVerticalMenuLeftTwo {
|
|
|
+ width: 16rem;
|
|
|
+ border: unset;
|
|
|
+
|
|
|
+ .el-menu-item,
|
|
|
+ .el-sub-menu {
|
|
|
+ width: 16rem;
|
|
|
+ font-size: 1.2857rem;
|
|
|
+
|
|
|
+ .leftImg {
|
|
|
+ width: 1.4285rem;
|
|
|
+ margin: 0px 0.8571rem 0px 0px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-sub-menu__title {
|
|
|
+ font-size: 1.2857rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-sub-menu__icon-arrow {
|
|
|
+ font-size: 0.8571rem;
|
|
|
+ margin-right: 0px;
|
|
|
+ margin-top: -0.4285rem;
|
|
|
+ right: 1.4285rem;
|
|
|
+ top: 50%;
|
|
|
+ width: inherit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-menu-item {
|
|
|
+ height: 4rem;
|
|
|
+ line-height: 4rem;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+@use './css/commonsScrollbar.scss';
|
|
|
+
|
|
|
+.MenuLeft * {
|
|
|
+ -moz-user-select: none;
|
|
|
+ -webkit-user-select: none;
|
|
|
+ -ms-user-select: none;
|
|
|
+ -khtml-user-select: none;
|
|
|
+ user-select: none;
|
|
|
+}
|
|
|
+
|
|
|
+.MenuLeft {
|
|
|
+ position: fixed;
|
|
|
+ left: 2rem;
|
|
|
+ top: 2rem;
|
|
|
+ bottom: 2rem;
|
|
|
+ width: 18.92rem;
|
|
|
+ border-radius: 1.0714rem;
|
|
|
+ background-color: #ffffff;
|
|
|
+ z-index: 999;
|
|
|
+
|
|
|
+ .logo {
|
|
|
+ position: absolute;
|
|
|
+ width: 12.2857rem;
|
|
|
+ top: 2.8571rem;
|
|
|
+ left: 3.2857rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .menu {
|
|
|
+ position: absolute;
|
|
|
+ top: 11.1428rem;
|
|
|
+ left: 1.3571rem;
|
|
|
+ right: 1.3571rem;
|
|
|
+ // bottom: 24rem;
|
|
|
+ bottom: 1rem;
|
|
|
+
|
|
|
+ overflow-x: hidden;
|
|
|
+
|
|
|
+ .menuBtn {
|
|
|
+ /* 链接选中 一个手势【常用】 */
|
|
|
+ cursor: pointer;
|
|
|
+ width: 100%;
|
|
|
+ height: 3.5714rem;
|
|
|
+ border-radius: 0.7142rem;
|
|
|
+ background-color: #ffffff;
|
|
|
+ color: #7a8388;
|
|
|
+ position: relative;
|
|
|
+ font-size: 1.5714rem;
|
|
|
+ font-weight: 400;
|
|
|
+
|
|
|
+ .menuImg {
|
|
|
+ position: absolute;
|
|
|
+ width: 1.7857rem;
|
|
|
+ top: 0.9285rem;
|
|
|
+ left: 2.0714rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .txt {
|
|
|
+ position: absolute;
|
|
|
+ height: 100%;
|
|
|
+ line-height: 3.5714rem;
|
|
|
+ top: 0px;
|
|
|
+ left: 5.2142rem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .menuBtnSelect {
|
|
|
+ background-color: #2c68ff;
|
|
|
+ color: #ffffff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .bottom {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 2.5714rem;
|
|
|
+ left: 2rem;
|
|
|
+ right: 2rem;
|
|
|
+ height: 15.9285rem;
|
|
|
+ background-color: #ebf3fe;
|
|
|
+ border-radius: 1.8571rem;
|
|
|
+
|
|
|
+ .aiRole {
|
|
|
+ position: absolute;
|
|
|
+ width: 12.7142rem;
|
|
|
+ bottom: 6.7857rem;
|
|
|
+ left: 1.1428rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .aiBtn {
|
|
|
+ position: absolute;
|
|
|
+ width: 11.4285rem;
|
|
|
+ bottom: 1.4285rem;
|
|
|
+ left: 1.7857rem;
|
|
|
+ /* 链接选中 一个手势【常用】 */
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|