人生啊人生 3 місяців тому
батько
коміт
40e18f075f

+ 6 - 9
user_web/src/view/admin/Main.vue

@@ -1,18 +1,14 @@
 <script setup>
 import { computed, onMounted, onUnmounted, watch, ref } from "vue";
 import { useRouter } from 'vue-router';
+import MenuLeftTwo from './components/Menu/MenuLeftTwo.vue';
 const router = useRouter();
 
 </script>
 
 <template>
-    <div class="main commonsScrollbar">
-        
-
-        
-
-
-
+    <div class="Main">
+        <MenuLeftTwo ></MenuLeftTwo>
     </div>
 </template>
 
@@ -24,7 +20,7 @@ const router = useRouter();
     -webkit-box-sizing:border-box; /* Safari */
 }
 
-.main * {
+.Main * {
     -moz-user-select: none;
     -webkit-user-select: none;
     -ms-user-select: none;
@@ -32,7 +28,7 @@ const router = useRouter();
     user-select: none;
 }
 
-.main {
+.Main {
 
     position: fixed;
     z-index: 0;
@@ -40,6 +36,7 @@ const router = useRouter();
     height: 100%;
     top: 0px;
     left: 0px;
+    background-color: #f6f7f9;
     
 }
 </style>

+ 460 - 0
user_web/src/view/admin/components/Menu/MenuLeftTwo.vue

@@ -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>

Різницю між файлами не показано, бо вона завелика
+ 2 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/Frame-yes.svg


Різницю між файлами не показано, бо вона завелика
+ 2 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/Frame.svg


+ 5 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/brush-ai-fill-yes.svg

@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="brush-ai-fill">
+<path id="Vector" d="M3.92783 5.94009L3.72235 6.41149C3.57197 6.7566 3.09464 6.7566 2.94427 6.41149L2.7388 5.94009C2.37255 5.09956 1.71287 4.43034 0.889725 4.06423L0.256706 3.78268C-0.0855685 3.63044 -0.0855685 3.13234 0.256706 2.9801L0.854333 2.71428C1.69865 2.33876 2.37014 1.64477 2.7301 0.77569L2.9411 0.266278C3.08815 -0.0887594 3.57847 -0.0887594 3.72552 0.266278L3.93652 0.77569C4.29647 1.64477 4.96798 2.33876 5.81233 2.71428L6.4099 2.9801C6.75226 3.13234 6.75226 3.63044 6.4099 3.78268L5.7769 4.06423C4.95376 4.43034 4.29407 5.09956 3.92783 5.94009ZM15.1898 1.97608L11.0738 5.17741C7.7852 4.36602 4.63202 6.28872 3.75 9.5805C3.66522 9.89692 3.63872 10.2183 3.61097 10.555C3.51524 11.7166 3.40462 13.0589 0.833333 14.9972C2.91667 16.2472 6.66667 17.4987 9.58467 17.4987C12.3452 17.4987 14.8719 15.658 15.6203 12.8648C15.903 11.8099 15.8982 10.7458 15.6539 9.75558L18.8544 5.64066C19.1124 5.30892 19.0831 4.83696 18.7858 4.53978L16.2907 2.04462C15.9935 1.74745 15.5216 1.71807 15.1898 1.97608ZM14.0793 6.90433C14.0266 6.8496 13.9727 6.79578 13.9179 6.74291L12.9807 5.80571L15.6324 3.74332L17.0872 5.19812L15.0247 7.84977L14.0793 6.90433Z" fill="#2C68FF"/>
+</g>
+</svg>

+ 5 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/brush-ai-fill.svg

@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="brush-ai-fill">
+<path id="Vector" d="M3.92783 5.94009L3.72235 6.41149C3.57197 6.7566 3.09464 6.7566 2.94427 6.41149L2.7388 5.94009C2.37255 5.09956 1.71287 4.43034 0.889725 4.06423L0.256706 3.78268C-0.0855685 3.63044 -0.0855685 3.13234 0.256706 2.9801L0.854333 2.71428C1.69865 2.33876 2.37014 1.64477 2.7301 0.77569L2.9411 0.266278C3.08815 -0.0887594 3.57847 -0.0887594 3.72552 0.266278L3.93652 0.77569C4.29647 1.64477 4.96798 2.33876 5.81233 2.71428L6.4099 2.9801C6.75226 3.13234 6.75226 3.63044 6.4099 3.78268L5.7769 4.06423C4.95376 4.43034 4.29407 5.09956 3.92783 5.94009ZM15.1898 1.97608L11.0738 5.17741C7.7852 4.36602 4.63202 6.28872 3.75 9.5805C3.66522 9.89692 3.63872 10.2183 3.61097 10.555C3.51524 11.7166 3.40462 13.0589 0.833333 14.9972C2.91667 16.2472 6.66667 17.4987 9.58467 17.4987C12.3452 17.4987 14.8719 15.658 15.6203 12.8648C15.903 11.8099 15.8982 10.7458 15.6539 9.75558L18.8544 5.64066C19.1124 5.30892 19.0831 4.83696 18.7858 4.53978L16.2907 2.04462C15.9935 1.74745 15.5216 1.71807 15.1898 1.97608ZM14.0793 6.90433C14.0266 6.8496 13.9727 6.79578 13.9179 6.74291L12.9807 5.80571L15.6324 3.74332L17.0872 5.19812L15.0247 7.84977L14.0793 6.90433Z" fill="#515357"/>
+</g>
+</svg>

+ 5 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/graduation-cap-fill-yes.svg

@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="graduation-cap-fill">
+<path id="Vector" d="M10 1.66675L0 7.50008L10 13.3334L18.3333 8.47233V14.5834H20V7.50008L10 1.66675ZM3.33252 11.2422V15.0002C4.85287 17.0242 7.27343 18.3335 9.99983 18.3335C12.7262 18.3335 15.1467 17.0242 16.6671 15.0002L16.6667 11.2428L10.0003 15.1317L3.33252 11.2422Z" fill="#2C68FF"/>
+</g>
+</svg>

+ 5 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/graduation-cap-fill.svg

@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="graduation-cap-fill">
+<path id="Vector" d="M10 1.66675L0 7.50008L10 13.3334L18.3333 8.47233V14.5834H20V7.50008L10 1.66675ZM3.33252 11.2422V15.0002C4.85287 17.0242 7.27343 18.3335 9.99983 18.3335C12.7262 18.3335 15.1467 17.0242 16.6671 15.0002L16.6667 11.2428L10.0003 15.1317L3.33252 11.2422Z" fill="#515357"/>
+</g>
+</svg>

+ 5 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/planet-fill-yes.svg

@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="planet-fill">
+<path id="Vector" d="M4.43537 4.97131C4.51972 4.87812 4.60683 4.78654 4.6967 4.69667C5.09954 4.29383 5.53681 3.9464 5.99902 3.65437C5.73742 3.58226 5.50228 3.53956 5.29618 3.52401C4.81923 3.48804 4.61036 3.6013 4.52127 3.69038C4.43219 3.77946 4.31893 3.98834 4.35491 4.46528C4.36645 4.6183 4.39297 4.78733 4.43537 4.97131ZM17.2714 11.8422C17.3227 11.9447 17.3719 12.0464 17.419 12.1472C17.8161 12.9981 18.0784 13.8287 18.1347 14.5752C18.1908 15.3182 18.0467 16.0922 17.4849 16.654C16.9231 17.2158 16.1492 17.3598 15.4062 17.3038C14.7557 17.2547 14.0414 17.0493 13.3055 16.7346L13.3033 16.7356C13.1757 16.681 13.0475 16.6232 12.9187 16.5622C11.2246 15.7602 9.28625 14.3504 7.46658 12.5307C5.64879 10.713 4.24006 8.77682 3.43767 7.08393C3.37648 6.95484 3.31837 6.82622 3.26357 6.69829L3.26445 6.69651C2.94846 5.95876 2.74214 5.24267 2.69296 4.59063C2.63692 3.8476 2.78097 3.07366 3.34277 2.51186C3.90456 1.95008 4.67849 1.80602 5.42152 1.86206C6.16812 1.91837 6.99867 2.1807 7.84957 2.57778C7.95211 2.62563 8.05556 2.67573 8.15984 2.72804C10.6352 2.10413 13.367 2.76034 15.3033 4.69667C17.2402 6.63356 17.8962 9.36624 17.2714 11.8422ZM16.344 14.0035C16.0523 14.4648 15.7054 14.9012 15.3033 15.3032C15.2142 15.3924 15.1232 15.4789 15.0308 15.5627C15.2127 15.6043 15.38 15.6304 15.5315 15.6418C16.0084 15.6778 16.2173 15.5646 16.3064 15.4755C16.3955 15.3864 16.5087 15.1776 16.4727 14.7006C16.4573 14.496 16.4152 14.2628 16.344 14.0035ZM4.6967 15.3032C2.81034 13.4169 2.13888 10.7757 2.68231 8.35199C3.58421 10.0027 4.93645 11.7684 6.5827 13.4147C8.23027 15.0622 9.99758 16.4154 11.6495 17.3173C9.22542 17.8614 6.58346 17.1901 4.6967 15.3032Z" fill="#2C68FF"/>
+</g>
+</svg>

+ 5 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/planet-fill.svg

@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="planet-fill">
+<path id="Vector" d="M4.43537 4.97131C4.51972 4.87812 4.60683 4.78654 4.6967 4.69667C5.09954 4.29383 5.53681 3.9464 5.99902 3.65437C5.73742 3.58226 5.50228 3.53956 5.29618 3.52401C4.81923 3.48804 4.61036 3.6013 4.52127 3.69038C4.43219 3.77946 4.31893 3.98834 4.35491 4.46528C4.36645 4.6183 4.39297 4.78733 4.43537 4.97131ZM17.2714 11.8422C17.3227 11.9447 17.3719 12.0464 17.419 12.1472C17.8161 12.9981 18.0784 13.8287 18.1347 14.5752C18.1908 15.3182 18.0467 16.0922 17.4849 16.654C16.9231 17.2158 16.1492 17.3598 15.4062 17.3038C14.7557 17.2547 14.0414 17.0493 13.3055 16.7346L13.3033 16.7356C13.1757 16.681 13.0475 16.6232 12.9187 16.5622C11.2246 15.7602 9.28625 14.3504 7.46658 12.5307C5.64879 10.713 4.24006 8.77682 3.43767 7.08393C3.37648 6.95484 3.31837 6.82622 3.26357 6.69829L3.26445 6.69651C2.94846 5.95876 2.74214 5.24267 2.69296 4.59063C2.63692 3.8476 2.78097 3.07366 3.34277 2.51186C3.90456 1.95008 4.67849 1.80602 5.42152 1.86206C6.16812 1.91837 6.99867 2.1807 7.84957 2.57778C7.95211 2.62563 8.05556 2.67573 8.15984 2.72804C10.6352 2.10413 13.367 2.76034 15.3033 4.69667C17.2402 6.63356 17.8962 9.36624 17.2714 11.8422ZM16.344 14.0035C16.0523 14.4648 15.7054 14.9012 15.3033 15.3032C15.2142 15.3924 15.1232 15.4789 15.0308 15.5627C15.2127 15.6043 15.38 15.6304 15.5315 15.6418C16.0084 15.6778 16.2173 15.5646 16.3064 15.4755C16.3955 15.3864 16.5087 15.1776 16.4727 14.7006C16.4573 14.496 16.4152 14.2628 16.344 14.0035ZM4.6967 15.3032C2.81034 13.4169 2.13888 10.7757 2.68231 8.35199C3.58421 10.0027 4.93645 11.7684 6.5827 13.4147C8.23027 15.0622 9.99758 16.4154 11.6495 17.3173C9.22542 17.8614 6.58346 17.1901 4.6967 15.3032Z" fill="#515357"/>
+</g>
+</svg>

+ 5 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/quill-pen-ai-fill-yes.svg

@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="quill-pen-ai-fill">
+<path id="Vector" d="M3.92783 5.94009L3.72235 6.41149C3.57197 6.7566 3.09464 6.7566 2.94427 6.41149L2.7388 5.94009C2.37255 5.09956 1.71287 4.43034 0.889725 4.06423L0.256706 3.78268C-0.0855685 3.63044 -0.0855685 3.13234 0.256706 2.9801L0.854333 2.71428C1.69865 2.33876 2.37014 1.64477 2.7301 0.77569L2.9411 0.266278C3.08815 -0.0887594 3.57847 -0.0887594 3.72552 0.266278L3.93652 0.77569C4.29647 1.64477 4.96798 2.33876 5.81233 2.71428L6.4099 2.9801C6.75226 3.13234 6.75226 3.63044 6.4099 3.78268L5.7769 4.06423C4.95376 4.43034 4.29407 5.09956 3.92783 5.94009ZM2.55301 18.011C3.40712 12.8517 5.25921 1.66382 17.5 1.66382C16.2535 4.16382 15.4167 5.41382 14.5833 6.24715L13.75 7.08048L15 7.91382C14.1667 10.4138 11.6667 13.3305 8.33333 13.7472C6.10955 14.0251 4.72017 15.5529 4.1652 18.3305H2.5C2.51728 18.2268 2.53492 18.1203 2.55301 18.011Z" fill="#2C68FF"/>
+</g>
+</svg>

+ 5 - 0
user_web/src/view/admin/components/Menu/assets/img/MenuLeftTwo/quill-pen-ai-fill.svg

@@ -0,0 +1,5 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g id="quill-pen-ai-fill">
+<path id="Vector" d="M3.92783 5.94009L3.72235 6.41149C3.57197 6.7566 3.09464 6.7566 2.94427 6.41149L2.7388 5.94009C2.37255 5.09956 1.71287 4.43034 0.889725 4.06423L0.256706 3.78268C-0.0855685 3.63044 -0.0855685 3.13234 0.256706 2.9801L0.854333 2.71428C1.69865 2.33876 2.37014 1.64477 2.7301 0.77569L2.9411 0.266278C3.08815 -0.0887594 3.57847 -0.0887594 3.72552 0.266278L3.93652 0.77569C4.29647 1.64477 4.96798 2.33876 5.81233 2.71428L6.4099 2.9801C6.75226 3.13234 6.75226 3.63044 6.4099 3.78268L5.7769 4.06423C4.95376 4.43034 4.29407 5.09956 3.92783 5.94009ZM2.55301 18.011C3.40712 12.8517 5.25921 1.66382 17.5 1.66382C16.2535 4.16382 15.4167 5.41382 14.5833 6.24715L13.75 7.08048L15 7.91382C14.1667 10.4138 11.6667 13.3305 8.33333 13.7472C6.10955 14.0251 4.72017 15.5529 4.1652 18.3305H2.5C2.51728 18.2268 2.53492 18.1203 2.55301 18.011Z" fill="#515357"/>
+</g>
+</svg>

Різницю між файлами не показано, бо вона завелика
+ 11 - 0
user_web/src/view/admin/components/Menu/assets/img/logo.svg


+ 144 - 0
user_web/src/view/admin/components/Menu/css/commonsScrollbar.scss

@@ -0,0 +1,144 @@
+
+/* 滚动 */
+.commonsScrollbar {
+    overflow-y: scroll;
+    overflow-x: visible;
+}
+
+/* 滚动条整体样式 */
+.commonsScrollbar::-webkit-scrollbar {
+    width: 1px;
+    height: 1px;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.commonsScrollbar::scrollbar {
+    width: 1px;
+    height: 1px;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.commonsScrollbar::-moz-scrollbar {
+    width: 1px;
+    height: 1px;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.commonsScrollbar::-ms-scrollbar {
+    width: 1px;
+    height: 1px;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.commonsScrollbar::-o-scrollbar {
+    width: 1px;
+    height: 1px;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+/* 滚动条里面小方块 */
+.commonsScrollbar::-webkit-scrollbar-thumb {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    background-clip: padding-box;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+    min-height: 1px;
+}
+
+.commonsScrollbar::scrollbar-thumb {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    background-clip: padding-box;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+    min-height: 1px;
+}
+
+.commonsScrollbar::-moz-scrollbar-thumb {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    background-clip: padding-box;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+    min-height: 1px;
+}
+
+.commonsScrollbar::-ms-scrollbar-thumb {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    background-clip: padding-box;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+    min-height: 1px;
+}
+
+.commonsScrollbar::-o-scrollbar-thumb {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    background-clip: padding-box;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+    min-height: 1px;
+}
+
+/* 滚动条里面轨道 */
+.commonsScrollbar::-webkit-scrollbar-thumb:hover {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.commonsScrollbar::scrollbar-thumb:hover {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.commonsScrollbar::-moz-scrollbar-thumb:hover {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.commonsScrollbar::-ms-scrollbar-thumb:hover {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+.commonsScrollbar::-o-scrollbar-thumb:hover {
+    /* background-color: #EAEAEA;*/
+    background-color: #D9D9D9;
+    -webkit-border-radius: 5px;
+    -moz-border-radius: 5px;
+    border-radius: 5px;
+}
+
+
+
+
+

+ 18 - 0
user_web/src/view/admin/components/Menu/stores/menuLeftTwo.ts

@@ -0,0 +1,18 @@
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+
+export const menuLeftTwo = defineStore('menuLeftTwo', () => {
+    /**
+     * 记录左侧菜单状态
+     */
+    const show = ref({
+        // 滚动的位置
+        scrollTop: 0,
+        // 展开菜单id的集合
+        listJson: [],
+    })
+
+    return {
+        show,
+    }
+})

+ 193 - 0
user_web/src/view/admin/components/User/LoginOrExit.vue

@@ -0,0 +1,193 @@
+<script>
+/*eslint-disable*/
+</script>
+
+<template>
+    <div class="LoginOrExit" >
+
+        <div class="obj">
+            <img src="../../../assets/teacher/user/sys.png" />
+        </div>
+        <div class="obj" v-on:click="goIndexEvent()" >
+            <img src="../../../assets/teacher/user/host.png" />
+        </div>
+
+        <div class="user" v-on:mousemove="windowsEvent()" v-on:mouseout="windowsExitEvent()" >
+            <!-- <img class="imgUser" src="../../../assets/teacher/user/user.svg"  /> -->
+            <img class="imgUser" src="../../../assets/avatar.png"  />
+            高老师
+            <img class="imgDown" src="../../../assets/teacher/user/down.png"  />
+        </div>
+
+        <div
+        v-on:click="exitEvent()"
+        v-show="open == true"
+        v-on:mousemove="windowsEvent()" v-on:mouseout="windowsExitEvent()"
+        class="list">
+            <div class="select">退出登陆</div>
+        </div>
+
+    </div>
+</template>
+
+<script setup >
+import { computed, onMounted, onUnmounted, watch, ref } from "vue";
+import { useRouter } from 'vue-router';
+const router = useRouter();
+
+// 接收参数
+const props = defineProps({
+    // addStyle: {
+    //     type: String,
+    //     default : function() {
+    //         return "";
+    //     }
+    // },
+});
+
+let open = ref(false);
+
+let objTimeEvent = null;
+
+const objTimeEventClose = () => {
+    if (objTimeEvent != null && objTimeEvent != undefined) {
+        clearInterval(objTimeEvent);
+        objTimeEvent = null;
+    }
+}
+
+let windowsEvent = () => {
+    objTimeEventClose();
+    open.value = true;
+}
+
+let windowsExitEvent = () => {
+
+    objTimeEventClose();
+    objTimeEvent = setInterval(function() {
+        open.value = false;
+        objTimeEventClose();
+    }, 500);
+
+}
+
+/**
+ * 到首页
+ */
+const goIndexEvent = () => {
+    router.push('/teacher');
+}
+
+
+/**
+ * 退出到登录页
+ */
+const exitEvent = () => {
+    router.push('/login');
+}
+
+
+onMounted(function() {
+
+});
+
+</script>
+
+<style scoped lang="scss">
+
+// $myScale: 0.75;
+$myScale: 0.8;
+
+.LoginOrExit * {
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    -ms-user-select: none;
+    -khtml-user-select: none;
+    user-select: none;
+}
+
+.LoginOrExit {
+    position: fixed;
+    z-index: 999;
+    top: 1.9285rem * $myScale;
+    right: 3.7857rem * $myScale;
+    float: left;
+
+    .obj, .user {
+        float: left;
+    }
+
+    .obj {
+        width: 4.7857rem * $myScale;
+        height: 4.7857rem * $myScale;
+        margin: 0px 0.8928rem * $myScale 0px 0.8928rem * $myScale;
+        cursor:pointer;
+
+        // 垂直水平居中
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+
+        img {
+            width: auto;
+            height: auto;
+            max-width: 100%;
+            max-height: 100%;
+        }
+
+    }
+
+    .user {
+        background-color: #ffffff;
+        height: 4.7857rem * $myScale;
+        line-height: 4.7857rem * $myScale;
+        margin: 0px 0.8928rem * $myScale 0px 0.8928rem * $myScale;
+        cursor:pointer;
+        border-radius: 1.0714rem * $myScale;
+        font-size: 1.7142rem * $myScale;
+        color: #000000;
+
+        .imgUser {
+            width: 3.1428rem * $myScale;
+            margin: 0.7142rem * $myScale;
+            float: left;
+            border-radius: 50%;
+        }
+
+        .imgDown {
+            width: 0.9285rem * $myScale;
+            margin: 0rem 1.7142rem * $myScale 0px 5.4285rem * $myScale;
+            position: relative;
+            top: -0.25rem * $myScale;
+        }
+
+    }
+
+    .list {
+
+        position: absolute;
+        width: 18.5rem * $myScale;
+        border-radius: 1.0714rem * $myScale;
+        background-color: #ffffff;
+        right: 0.75rem * $myScale;
+        top: 5rem * $myScale;
+
+        .select {
+            position: relative;
+            height: 4.64285rem * $myScale;
+            line-height: 4.64285rem * $myScale;
+            width: 80%;
+            left: 10%;
+            margin: 0.8rem * $myScale 0px 0.8rem * $myScale 0px;
+            color: #737373;
+            font-size: 1.71428rem * $myScale;
+            cursor:pointer;
+        }
+
+    }
+
+
+}
+
+</style>

Деякі файли не було показано, через те що забагато файлів було змінено