ProgrammingSidebar.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <template>
  2. <!-- 左侧折叠面板 -->
  3. <transition name="drawer-slide">
  4. <div class="left-group">
  5. <el-row class="tac">
  6. <el-col :span="12">
  7. <!-- <div class="mb-2-container">
  8. <span class="mb-2">
  9. <img :src="breakthrough" alt="" />
  10. 主题大冒险
  11. </span>
  12. </div> -->
  13. <el-menu
  14. :default-active="currentActiveIndex"
  15. class="el-menu-vertical-demo"
  16. @open="handleOpen"
  17. @close="handleClose"
  18. >
  19. <el-menu-item
  20. v-for="(item, index) in groupList"
  21. :key="index"
  22. :index="index.toString()"
  23. @click="navigateToAI(item)"
  24. v-model="currentActiveIndex"
  25. @mouseover="item.isHover = true"
  26. @mouseout="item.isHover = false"
  27. >
  28. <!-- 根据状态切换图片-->
  29. <img
  30. :src="currentActiveIndex === index.toString() || item.isHover ? item.hoverIcon : item.icon"
  31. alt=""
  32. class="menu-icon"
  33. />
  34. {{ item.title }}
  35. </el-menu-item>
  36. </el-menu>
  37. </el-col>
  38. </el-row>
  39. </div>
  40. </transition>
  41. </template>
  42. <script setup>
  43. import { ref, onMounted,watch} from 'vue'
  44. import { useRouter, useRoute } from 'vue-router'
  45. // 导入图片 白色
  46. import blockly from '@/assets/icon/blockly.png'
  47. // 黑色
  48. import blockly02 from '@/assets/icon/blockly02.png'
  49. import breakthrough from '@/assets/icon/breakthrough.png'
  50. import {blocklyRoutes} from "@/router/index.js";
  51. const router = useRouter()
  52. const route = useRoute()
  53. // 添加抽屉显示状态
  54. const drawerVisible = ref(true)
  55. // 当前选中索引状态
  56. const currentActiveIndex = ref('2')
  57. // 渲染侧边栏
  58. const groupList = ref([
  59. {
  60. icon: blockly,
  61. hoverIcon: blockly02,
  62. title: 'AI编程课'
  63. }
  64. ])
  65. // 提取更新选中状态的逻辑为单独函数
  66. // 优化后的更新选中状态的方法
  67. const updateActiveIndex = () => {
  68. const path = route.path;
  69. // 使用映射表存储路径和索引的对应关系
  70. const pathIndexMap = {
  71. 'programming':"0" // 编程课
  72. };
  73. // 查找路径对应的索引
  74. for (const [key, index] of Object.entries(pathIndexMap)) {
  75. if (path.includes(key)) {
  76. currentActiveIndex.value = index;
  77. return;
  78. }
  79. }
  80. };
  81. // 组件挂载时确保默认选中状态
  82. onMounted(() => {
  83. updateActiveIndex();
  84. });
  85. // 添加路由变化监听,更新选中状态
  86. watch(() => route, () => {
  87. updateActiveIndex();
  88. }, { immediate: true, deep: true });
  89. // 跳转智能问答
  90. const navigateToAI = async (group) => {
  91. if (group.title === 'blockly编程') {
  92. router.push(blocklyRoutes.home)
  93. }
  94. }
  95. // 处理菜单展开和关闭
  96. const handleOpen = () => {}
  97. const handleClose = () => {}
  98. // 导出状态和方法供父组件使用
  99. defineExpose({
  100. drawerVisible,
  101. toggleDrawer: () => {
  102. drawerVisible.value = !drawerVisible.value
  103. }
  104. })
  105. </script>
  106. <style scoped lang="scss">
  107. @use 'sass:math';
  108. // 定义rpx转换函数
  109. @function rpx($px) {
  110. @return math.div($px, 750) * 100vw;
  111. }
  112. /* 添加过渡样式 */
  113. ::v-deep .drawer-slide-enter-active,
  114. ::v-deep .drawer-slide-leave-active {
  115. transition: all 0.3s ease;
  116. }
  117. ::v-deep .drawer-slide-enter-from,
  118. ::v-deep .drawer-slide-leave-to {
  119. transform: translateX(-100%);
  120. opacity: 0;
  121. }
  122. // 侧边栏
  123. .left-group {
  124. width: rpx(135);
  125. height: 100%;
  126. background: linear-gradient(to bottom, #001169, #8a78d0);
  127. overflow-y: auto;
  128. // 自定义滚动条样式
  129. &::-webkit-scrollbar {
  130. width: rpx(0); // 滚动条宽度
  131. }
  132. &::-webkit-scrollbar-track {
  133. background-color: rgba(255, 255, 255, 0.1); // 滚动条轨道背景色
  134. border-radius: rpx(2); // 滚动条轨道圆角
  135. }
  136. &::-webkit-scrollbar-thumb {
  137. background-color: rgba(255, 255, 255, 0.3); // 滚动条滑块颜色
  138. border-radius: rpx(2); // 滚动条滑块圆角
  139. transition: background-color 0.3s ease; // 滑块颜色过渡效果
  140. }
  141. &::-webkit-scrollbar-thumb:hover {
  142. background-color: rgba(255, 255, 255, 0.5); // 鼠标悬停时的滑块颜色
  143. }
  144. }
  145. .mb-2 {
  146. color: white;
  147. font-size: rpx(9);
  148. white-space: nowrap;
  149. }
  150. .mb-2 img {
  151. width: rpx(15);
  152. height: rpx(15);
  153. vertical-align: middle;
  154. margin-top: rpx(-2);
  155. }
  156. .mb-2-container {
  157. width: rpx(135);
  158. height: rpx(30);
  159. margin-top: rpx(20);
  160. margin-left: rpx(10);
  161. text-align: left;
  162. }
  163. .tac ::v-deep(.el-menu) {
  164. background-color: transparent;
  165. border: none;
  166. width: 100%;
  167. margin-top: rpx(25);
  168. margin-left: rpx(10);
  169. }
  170. .el-menu-item {
  171. width: rpx(115);
  172. height: rpx(25);
  173. margin-bottom: rpx(5);
  174. border-radius: rpx(6);
  175. color: white;
  176. font-size: rpx(8);
  177. }
  178. .el-menu-item .el-icon svg {
  179. font-size: rpx(15);
  180. color: white;
  181. }
  182. .el-menu .el-menu-item:hover {
  183. background: linear-gradient(to bottom, #ffefb0, #ffcc00);
  184. box-shadow: 0 8px 8px rgb(0, 0, 0, 0.3);
  185. color: black;
  186. font-size: rpx(8);
  187. }
  188. :deep(.el-menu .el-menu-item.is-active) {
  189. background: linear-gradient(to bottom, #fee78a, #ffce1b);
  190. color: black;
  191. font-size: rpx(8);
  192. box-shadow: 0 4px 8px rgba(3, 3, 3, 0.3);
  193. }
  194. .menu-icon {
  195. width: rpx(11);
  196. height: rpx(11);
  197. margin-right: rpx(2);
  198. }
  199. </style>