소스 검색

修改新版前端界面

丸子 9 달 전
부모
커밋
2fc72d4568

+ 1 - 1
package-lock.json

@@ -545,7 +545,7 @@
     },
     "node_modules/@microsoft/fetch-event-source": {
       "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@microsoft/fetch-event-source/-/fetch-event-source-2.0.1.tgz",
+      "resolved": "https://registry.npmmirror.com/@microsoft/fetch-event-source/-/fetch-event-source-2.0.1.tgz",
       "integrity": "sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==",
       "license": "MIT"
     },

+ 3 - 2
src/api/questions.js

@@ -1,6 +1,7 @@
 import axios from "@/utils/request";
 
-// import { fetchEventSource } from '@microsoft/fetch-event-source'
+import { fetchEventSource } from '@microsoft/fetch-event-source'
+
 
 // 数字人对话框
 export function CreateDialogue (data){
@@ -23,7 +24,7 @@ export async function sendChatMessageStream (
     onError,
     onClose
 ) {
-  return fetchEventSource(`http://127.0.0.1:8080/admin-api/bjdxWeb/ai/dialogue-send-stream`, {
+  return fetchEventSource(`http://192.168.110.8:8080/admin-api/bjdxWeb/ai/dialogue-send-stream`, {
     method: 'post',
     headers: {
       'Content-Type': 'application/json',

+ 19 - 13
src/components/HomePage.vue

@@ -123,7 +123,7 @@ const selectedGrade = ref('小学低年级')
   left: 0;
   right: 0;
   bottom: 0;
-   background: linear-gradient(to bottom, #001169, #B4A8E1);
+  background: linear-gradient(to bottom, #001169, #8a78d0);
   display: flex;
   flex-direction: column;
   gap: rpx(0);
@@ -138,7 +138,8 @@ const selectedGrade = ref('小学低年级')
   font-size: rpx(16); // 默认字体大小
 }
 .box-2 {
-  width: 100%;
+  width: 90%;
+  margin: auto;
   flex: 1;
   display: flex;
   justify-content: space-between;
@@ -160,7 +161,7 @@ const selectedGrade = ref('小学低年级')
   border-radius: rpx(20);
   flex: 1; // 让三个盒子平均分配空间
   margin: 0 rpx(10); // 添加左右间距
-  height: 75%; // 高度占满容器
+  height: 85%; // 高度占满容器
   display: flex;
   justify-content: flex-start;
   align-items: flex-start;
@@ -182,7 +183,7 @@ const selectedGrade = ref('小学低年级')
 .right-box-in-box2 {
   flex: 1; // 让三个盒子平均分配空间
   margin: 0 rpx(10); // 添加左右间距
-  height: 75%; // 高度占满容器
+  height: 85%; // 高度占满容器
   display: flex;
   // 确保两个子盒子上下排列
   flex-direction: column;
@@ -245,7 +246,7 @@ const selectedGrade = ref('小学低年级')
   width: rpx(65); // 使用 rpx 函数设置按钮宽度
   height: rpx(15); // 使用 rpx 函数设置按钮高度
   margin: rpx(10) rpx(10) 0 0; // 使用 rpx 函数设置外边距
-  background-color: #8587b0;
+  background-color: transparent;
   color: white;
   border: none; // 移除默认边框
   font-size: rpx(7); // 使用 rpx 函数设置字体大小
@@ -254,25 +255,27 @@ const selectedGrade = ref('小学低年级')
 .top-right-btn.is-active,
 .top-right-btn:active,
 .top-right-btn:focus {
-  background-color: white; // 点击选中后白色背景色
+  background-color: rgb(255, 255, 255, 0.7);
+  border: 1px white solid;
   color: black;
-  border: none; // 移除点击时的边框
   outline: none; // 移除点击时的外边框
   box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
 }
 .dropdown-box {
   width: 100%;
   height: 100%;
-  display: flex; // 添加 flex 布局;
+  // display: flex; // 添加 flex 布局;
+  margin-left: rpx(-80);
   flex: 1;
   align-items: center; // 垂直居中;
-  padding-left: rpx(25); // 添加右侧内边距;
-  margin-top: rpx(25);
+  margin-top: rpx(22);
 }
 .dropdown-box .el-button {
-  width: rpx(65); // 设置按钮宽度;
+  width: rpx(55); // 设置按钮宽度;
   height: rpx(15); // 设置按钮高度;
-  background-color: white;
+  background-color: rgb(255, 255, 255, 0.7);
+  border: 1px white solid;
+  box-shadow: 0 4px 8px rgb(0, 0, 0, 0.3);
   color: black;
   border-radius: rpx(12);
   font-size: rpx(7); // 设置字体大小;
@@ -287,7 +290,8 @@ const selectedGrade = ref('小学低年级')
   width: rpx(100);
   height: rpx(50);
   border-radius: rpx(6);
-  background-color: rgba(165, 209, 247, 0.5);
+  border: 1px white solid;
+   background-color: rgba(161, 161, 161, 0.5);
   box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
 }
 // .el-dropdown__popper.el-popper
@@ -301,6 +305,7 @@ const selectedGrade = ref('小学低年级')
   margin-left: rpx(4);
   margin-bottom: rpx(8);
 }
+
 .dropdown-menu ::v-deep(.el-dropdown-menu__item:hover),
 .dropdown-menu ::v-deep(.el-dropdown-menu__item:focus),
 .dropdown-menu ::v-deep(.el-dropdown-menu__item:active) {
@@ -309,5 +314,6 @@ const selectedGrade = ref('小学低年级')
     #fee78a,
     #ffce1b
   ); /* 设置悬停、聚焦、点击状态下的背景色 */
+  color: white;
 }
 </style>

+ 8 - 4
src/router/index.js

@@ -1,10 +1,14 @@
 import { createRouter, createWebHistory } from 'vue-router'
 import App from '../App.vue'
-import HomePage from '../components/HomePage.vue'
+// import HomePage from '../components/HomePage.vue'
 
 const routes = [
-  { path: '/', component: HomePage },
-  { path: '/home', component: HomePage },
+  { path: '/login', component: () => import('../views/AILogin.vue') },
+  // 首页
+  {
+    path: '/home',
+    component: () => import('../components/HomePage.vue')
+  },
   // 智能课
   {
     path: '/ai-general-course',
@@ -21,7 +25,7 @@ const routes = [
     component: () => import('../views/AIPainting.vue')
   },
   // 智能问答
-   {
+  {
     path: '/ai-questions',
     component: () => import('../views/AIQuestions.vue')
   },

+ 2 - 0
src/utils/request.js

@@ -9,6 +9,8 @@ import router from '@/router/index.js'
 // process.env.NODE_ENV 用来获取我们当前的环境
 const isDev = process.env.NODE_ENV == 'development'
 
+// const BASE_URL = 'http://192.168.110.8:8080/admin-api'
+
 // 创建一个请求对象
 const request = axios.create({
   // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。

+ 204 - 146
src/views/AIDevelop.vue

@@ -4,11 +4,11 @@
     <!-- 添加抽屉 -->
     <div class="drawer-box">
       <el-button
-          v-if="!drawerVisible"
-          type="primary"
-          @click="drawerVisible = true"
-          @closed="buttonVisible = false"
-          class="toggle-button"
+        v-if="!drawerVisible"
+        type="primary"
+        @click="drawerVisible = true"
+        @closed="buttonVisible = false"
+        class="toggle-button"
       >
         课程小节
       </el-button>
@@ -26,8 +26,8 @@
             >
               <template v-for="item in menuItems" :key="item.index">
                 <el-menu-item v-if="!item.children" :index="item.index">{{
-                    item.title
-                  }}</el-menu-item>
+                  item.title
+                }}</el-menu-item>
                 <el-sub-menu v-else :index="item.index">
                   <template #title>
                     <span>{{ item.title }}</span>
@@ -35,8 +35,8 @@
                   <el-menu-item-group v-if="item.children">
                     <template v-for="child in item.children" :key="child.index">
                       <el-menu-item :index="child.index">{{
-                          child.title
-                        }}</el-menu-item>
+                        child.title
+                      }}</el-menu-item>
                     </template>
                   </el-menu-item-group>
                 </el-sub-menu>
@@ -57,9 +57,9 @@
       <div class="inner-box right-box">
         <div class="top-right-box">
           <el-input
-              v-model="SearchInput"
-              class="search-input"
-              placeholder="搜索"
+            v-model="SearchInput"
+            class="search-input"
+            placeholder="搜索"
           >
             <template #prefix>
               <el-icon class="el-input__icon"><search /></el-icon>
@@ -73,26 +73,29 @@
       <div class="small-title">
         <span>{{ smallTitle }}</span>
       </div>
-      <video
-        class="full-box-video"
-        :src="videoSrc"
-        controlsList="nodownload"
-        controls
-        @timeupdate="handleTimeUpdate"
-        ref="videoRef"
-      >
-        <source :src="videoSrc" type="video/mp4" />
-        您的浏览器不支持视频播放。
-      </video>
+      <div class="box-video">
+        <video
+          class="full-box-video"
+          :src="videoSrc"
+          controlsList="nodownload"
+          controls
+          @timeupdate="handleTimeUpdate"
+          ref="videoRef"
+        >
+          <source :src="videoSrc" type="video/mp4" />
+          您的浏览器不支持视频播放。
+        </video>
+      </div>
+
       <!-- 添加切换视频 -->
       <div class="video-switch">
         <!-- 上一个视频 -->
         <div class="caret-left" @click="playPreviousVideo">
-          <el-button type="warning" round>上一</el-button>
+          <el-button type="warning" round>上一</el-button>
         </div>
         <!-- 下一个视频 -->
         <div class="caret-right" @click="playNextVideo">
-          <el-button type="warning" round>下一</el-button>
+          <el-button type="warning" round>下一</el-button>
         </div>
       </div>
     </div>
@@ -102,83 +105,97 @@
         v-show="questionDialogVisible"
         class="child-dialog-wrapper"
         @click.self="handleCloseQuestionDialog"
-    >
-      <div class="child-dialog">
-        <div class="question-title">
-          <span class="question-icon">?</span>
-          {{ currentQuestion.title }}
-        </div>
-        <!-- 选项区域 -->
-        <div v-if="currentQuestion.options && currentQuestion.options.length > 0" class="options-container">
+      >
+        <div class="child-dialog">
+          <div class="question-title">
+            <span class="question-icon">?</span>
+            {{ currentQuestion.title }}
+          </div>
+          <!-- 选项区域 -->
           <div
+            v-if="currentQuestion.options && currentQuestion.options.length > 0"
+            class="options-container"
+          >
+            <div
               v-for="(option, index) in currentQuestion.options"
               :key="index"
               class="question-option"
-          >
-            <el-radio v-model="selectedOption" :label="index" :value="option" v-cloak="selectedOption = option">
-              <span>{{ option }}</span>
-            </el-radio>
+            >
+              <el-radio
+                v-model="selectedOption"
+                :label="index"
+                :value="option"
+                v-cloak="(selectedOption = option)"
+              >
+                <span>{{ option }}</span>
+              </el-radio>
+            </div>
+          </div>
+          <div v-else class="no-options">
+            <!--          暂无选项-->
+          </div>
+          <!-- 底部按钮 -->
+          <div class="dialog-footer">
+            <!--          <el-button class="child-button cancel" @click="questionDialogVisible = false; showAIDialog = false">取消</el-button>-->
+            <el-button class="child-button confirm" @click="handleSubmitAnswer"
+              >确定</el-button
+            >
+          </div>
+          <!-- 右侧小图标 -->
+          <div class="ai-icon-container" @click="handleAIClick">
+            <img
+              src="@/assets/images/xiaozhi.png"
+              alt="AI对话"
+              class="ai-icon"
+            />
+            <span class="ai-text">AI助手</span>
           </div>
-        </div>
-        <div v-else class="no-options">
-<!--          暂无选项-->
-        </div>
-        <!-- 底部按钮 -->
-        <div class="dialog-footer">
-<!--          <el-button class="child-button cancel" @click="questionDialogVisible = false; showAIDialog = false">取消</el-button>-->
-          <el-button class="child-button confirm" @click="handleSubmitAnswer">确定</el-button>
-        </div>
-        <!-- 右侧小图标 -->
-        <div class="ai-icon-container" @click="handleAIClick">
-          <img src="@/assets/images/xiaozhi.png" alt="AI对话" class="ai-icon" />
-          <span class="ai-text">AI助手</span>
         </div>
       </div>
-    </div>
     </transition>
 
     <!-- AI对话弹框 -->
     <div
-        v-show="showAIDialog"
-        class="ai-dialog-wrapper"
-        @click.self="showAIDialog = false"
+      v-show="showAIDialog"
+      class="ai-dialog-wrapper"
+      @click.self="showAIDialog = false"
     >
       <div class="ai-dialog">
         <div class="ai-dialog-header">
           <h3>小智智能助手</h3>
-          <el-button @click="showAIDialog = false" class="close-btn">×</el-button>
+          <el-button @click="showAIDialog = false" class="close-btn"
+            >×</el-button
+          >
         </div>
         <div class="ai-dialog-content">
           <div class="ai-message-history">
             <div
-                v-for="(message, index) in messageHistory"
-                :key="index"
-                :class="['message', message.type]"
+              v-for="(message, index) in messageHistory"
+              :key="index"
+              :class="['message', message.type]"
             >
               <img
-                  v-if="message.type === 'user'"
-                  src="@/assets/images/user.png"
-                  class="avatar user"
-              />
-              <img
-                  v-else
-                  src="@/assets/images/xiaozhi.png"
-                  class="avatar"
+                v-if="message.type === 'user'"
+                src="@/assets/images/user.png"
+                class="avatar user"
               />
+              <img v-else src="@/assets/images/xiaozhi.png" class="avatar" />
               <div class="message-content">
                 {{ message.content }}
               </div>
             </div>
           </div>
           <el-input
-              v-model="userMessage"
-              placeholder="输入问题..."
-              class="user-input"
-              @keyup.enter="sendMessage"
+            v-model="userMessage"
+            placeholder="输入问题..."
+            class="user-input"
+            @keyup.enter="sendMessage"
           >
             <template #append class="flex flex-wrap items-center mb-4">
-<!--              <el-button @click="sendMessage" class="child-button confirm">发送</el-button>-->
-              <el-button @click="sendMessage"  size="large" round>发送</el-button>
+              <!--              <el-button @click="sendMessage" class="child-button confirm">发送</el-button>-->
+              <el-button @click="sendMessage" size="large" round
+                >发送</el-button
+              >
             </template>
           </el-input>
         </div>
@@ -190,7 +207,12 @@
 <script setup>
 import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
-import { ArrowDown, ArrowRightBold, CaretRight,CaretLeft } from '@element-plus/icons-vue'
+import {
+  ArrowDown,
+  ArrowRightBold,
+  CaretRight,
+  CaretLeft
+} from '@element-plus/icons-vue'
 import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
 import { valueEquals } from 'element-plus'
 // 引入视频
@@ -331,7 +353,7 @@ const flattenMenuItems = () => {
 }
 
 // 播放下一个视频
-const playNextVideo = () => { 
+const playNextVideo = () => {
   const allIndices = flattenMenuItems()
   const currentIndexInList = allIndices.indexOf(currentIndex.value)
   if (currentIndexInList !== -1 && currentIndexInList < allIndices.length - 1) {
@@ -339,7 +361,9 @@ const playNextVideo = () => {
     handleSelect(nextIndex)
     // 切换视频后自动播放
     if (videoRef.value) {
-      videoRef.value.addEventListener('loadedmetadata', tryPlayVideo, { once: true })
+      videoRef.value.addEventListener('loadedmetadata', tryPlayVideo, {
+        once: true
+      })
     }
   }
   // 重置
@@ -357,7 +381,9 @@ const playPreviousVideo = () => {
     handleSelect(previousIndex)
     // 切换视频后自动播放
     if (videoRef.value) {
-      videoRef.value.addEventListener('loadedmetadata', tryPlayVideo, { once: true })
+      videoRef.value.addEventListener('loadedmetadata', tryPlayVideo, {
+        once: true
+      })
     }
   }
 }
@@ -371,7 +397,6 @@ const tryPlayVideo = () => {
   }
 }
 
-
 // 视频 ref
 const videoRef = ref(null)
 // 记录已经暂停过的时间点索引
@@ -399,7 +424,8 @@ const videoPauseTimes = {
         title: '视频当中发生了什么事情呢?',
         options: [],
         aiQuestion: '视频当中发生了什么事情呢',
-        aiAnswer: '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
+        aiAnswer:
+          '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
       }
     ]
   },
@@ -410,7 +436,8 @@ const videoPauseTimes = {
         title: '视频当中发生了什么事情呢?',
         options: [],
         aiQuestion: '视频当中发生了什么事情呢',
-        aiAnswer: '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
+        aiAnswer:
+          '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
       }
     ]
   },
@@ -421,7 +448,8 @@ const videoPauseTimes = {
         title: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
         options: [],
         aiQuestion: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
-        aiAnswer: '大模型已缩短与图灵测试的标志距离,尤其在表面对话层面,但因缺乏深层次理解、逻辑一致性与真实认知,仍无法在严格测试中稳定通过。'
+        aiAnswer:
+          '大模型已缩短与图灵测试的标志距离,尤其在表面对话层面,但因缺乏深层次理解、逻辑一致性与真实认知,仍无法在严格测试中稳定通过。'
       }
     ]
   },
@@ -437,10 +465,10 @@ const videoPauseTimes = {
     ]
   },
   [video6]: {
-    pauseTimes: [5],
+    pauseTimes: [5]
   },
   [video7]: {
-    pauseTimes: [64,91],
+    pauseTimes: [64, 91],
     questions: [
       {
         title: '如果你是聊天机器人,你会怎么回答用户呢?',
@@ -449,11 +477,14 @@ const videoPauseTimes = {
         aiAnswer: '发生什么事情了呢?'
       },
       {
-        title: '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
+        title:
+          '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
         options: [],
-        aiQuestion: '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
-        aiAnswer: '与聊天机器人的对话被人类查看时,隐私泄露风险客\n' +
-            '观存在,尤其是人类介入或安全漏洞场景下。建议优先选择支持本地'
+        aiQuestion:
+          '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
+        aiAnswer:
+          '与聊天机器人的对话被人类查看时,隐私泄露风险客\n' +
+          '观存在,尤其是人类介入或安全漏洞场景下。建议优先选择支持本地'
       }
     ]
   },
@@ -463,7 +494,8 @@ const videoPauseTimes = {
       {
         title: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
         options: [],
-        aiQuestion: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
+        aiQuestion:
+          '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
         aiAnswer: '这题没给答案,你自己去查吧!'
       }
     ]
@@ -475,12 +507,13 @@ const videoPauseTimes = {
         title: '在生活中,有哪些正在使用的专家系统呢?',
         options: [],
         aiQuestion: '在生活中,有哪些正在使用的专家系统呢?',
-        aiAnswer: '在医疗健康领域有复杂疾病协同决策和Ai医生分身与诊断辅助;在水利交通领域的水利厅专家库系统用于项目验收和抢险督查'
+        aiAnswer:
+          '在医疗健康领域有复杂疾病协同决策和Ai医生分身与诊断辅助;在水利交通领域的水利厅专家库系统用于项目验收和抢险督查'
       }
     ]
   },
   [video11]: {
-    pauseTimes: [1,90,176],
+    pauseTimes: [1, 90, 176],
     questions: [
       {
         title: '怎么会有爆炸声?泡泡怪在这里吗?',
@@ -498,12 +531,13 @@ const videoPauseTimes = {
         title: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
         options: [],
         aiQuestion: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
-        aiAnswer: '围棋是人类智力游戏的巅峰,拥有天文数字级的可能性,每颗棋子价值由全局态势动态决定,所以当前一手可能百步之后才显现价值。AlphaGo战胜人类顶尖选手,它证明了Ai不仅能处理规则明确的事物,更能攻克依赖直觉、策略的“人类专属领域”'
+        aiAnswer:
+          '围棋是人类智力游戏的巅峰,拥有天文数字级的可能性,每颗棋子价值由全局态势动态决定,所以当前一手可能百步之后才显现价值。AlphaGo战胜人类顶尖选手,它证明了Ai不仅能处理规则明确的事物,更能攻克依赖直觉、策略的“人类专属领域”'
       }
     ]
   },
   [video12]: {
-    pauseTimes: [1],
+    pauseTimes: [1]
   },
   [video13]: {
     pauseTimes: [61],
@@ -518,7 +552,6 @@ const videoPauseTimes = {
   }
 }
 
-
 // 处理视频时间更新事件
 const handleTimeUpdate = () => {
   if (!videoRef.value) return
@@ -592,12 +625,14 @@ const handleAIClick = () => {
 }
 
 // 模拟 AI 回复
-const simulateAIResponse = (question) => {
-  return new Promise((resolve) => {
+const simulateAIResponse = question => {
+  return new Promise(resolve => {
     setTimeout(() => {
       const currentVideoInfo = videoPauseTimes[videoSrc.value]
       if (currentVideoInfo) {
-        const currentQuestionObj = currentVideoInfo.questions.find(q => q.aiQuestion === question)
+        const currentQuestionObj = currentVideoInfo.questions.find(
+          q => q.aiQuestion === question
+        )
         if (currentQuestionObj && currentQuestionObj.aiAnswer) {
           resolve(currentQuestionObj.aiAnswer)
           return
@@ -615,7 +650,6 @@ const handleCloseAIDialog = () => {
 }
 </script>
 
-
 <style scoped lang="scss">
 @use 'sass:math';
 @use 'sass:color'; // 引入 color 模块
@@ -637,7 +671,7 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
   left: 0;
   right: 0;
   bottom: 0;
-   background: linear-gradient(to bottom, #001169, #B4A8E1);
+  background: linear-gradient(to bottom, #001169, #b4a8e1);
   display: flex;
   flex-direction: column;
   gap: rpx(0);
@@ -664,9 +698,9 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
 .el-menu ::v-deep(.el-sub-menu__title:focus),
 .el-menu ::v-deep(.el-sub-menu__title:active) {
   background: linear-gradient(
-          to bottom,
-          #fee78a,
-          #ffce1b
+    to bottom,
+    #fee78a,
+    #ffce1b
   ); /* 设置悬停、聚焦、点击状态下的背景色 */
   background-color: transparent;
 }
@@ -691,9 +725,9 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
 .el-menu ::v-deep(.el-menu-item:focus),
 .el-menu ::v-deep(.el-menu-item:active) {
   background: linear-gradient(
-          to bottom,
-          #fee78a,
-          #ffce1b
+    to bottom,
+    #fee78a,
+    #ffce1b
   ); /* 设置悬停、聚焦、点击状态下的背景色 */
 }
 .drawer-box {
@@ -803,7 +837,7 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
 }
 .top-right-box {
   ::v-deep(.el-input__wrapper) {
-    background-color: transparent;
+    background-color: rgb(255, 255, 255, 0.5);
     border-radius: rpx(12);
     color: white;
   }
@@ -816,7 +850,7 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
   }
   // 添加输入框文字颜色样式
   ::v-deep(.el-input__inner) {
-    color: white;
+    color: black;
   }
 }
 // 搜索框
@@ -835,9 +869,13 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
   flex-wrap: wrap; // 允许子元素换行;
   align-content: center; // 顶部对齐;
   cursor: pointer; // 添加鼠标指针样式
+}
+.box-video {
+  width: 100%;
+  height: rpx(300);
   video.full-box-video {
-    //width: rpx(550);
-    height: rpx(300);
+    // width: 100%;
+    height: rpx(280);
     margin: 0 auto;
     border-radius: rpx(12);
     box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
@@ -847,19 +885,10 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
 }
 // 视频进度条样式
 video.full-box-video::-webkit-media-controls-timeline {
-  background-color: rgba(255, 255, 255,0.3); // 进度条背景颜色,调浅为半透明白色
-}
-video.full-box-video::-webkit-media-controls-current-time-display,
-video.full-box-video::-webkit-media-controls-time-remaining-display {
-  color: white; // 时间显示颜色
-}
-video.full-box-video::-webkit-media-controls-progress-bar {
-  background-color: rgba(255, 255, 255, 0.5); // 已播放进度颜色,调浅为半透明白色
-}
-video.full-box-video::-webkit-media-controls-thumb {
-  background-color: white; // 滑块颜色
+  background-color: rgb(255, 255, 255,0.3); // 进度条背景颜色,调浅为半透明白色
 }
 
+
 .small-title {
   width: 100%;
   margin-top: rpx(-20);
@@ -872,30 +901,28 @@ video.full-box-video::-webkit-media-controls-thumb {
   width: 100%;
   // height: rpx(50);
   display: flex;
-  // margin-top: rpx(10);
+  margin-top: rpx(-20);
   // background-color: saddlebrown;
 }
 .caret-right,
-.caret-left{
+.caret-left {
   width: rpx(50);
   // height: rpx(50);
   margin: auto;
   display: flex;
   // grid: rpx(4);
   margin-top: rpx(5);
-  margin-bottom: rpx(5);
+  margin-bottom: rpx(15);
 }
-.caret-left ::v-deep(.el-button.is-round) ,
+.caret-left ::v-deep(.el-button.is-round),
 .caret-right ::v-deep(.el-button.is-round) {
   width: rpx(50);
+  height: rpx(15);
   color: black;
   border-radius: none;
-  background: linear-gradient(
-    to bottom,
-    #fee78a,
-    #ffce1b
-  ); /* 设置悬停、聚焦、点击状态下的背景色 */
-    box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
+  border: 1px white solid;
+  background-color: rgb(255, 255, 255, 0.5); // 进度条背景颜色,调浅为半透明白色
+  box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
 }
 
 // 儿童风格试题弹框样式
@@ -923,20 +950,31 @@ video.full-box-video::-webkit-media-controls-thumb {
   .el-dialog {
     border: none;
     border-radius: rpx(20);
-    background: linear-gradient(135deg, $light-color, #d8bfd8); // 柔和的蓝紫色渐变
+    background: linear-gradient(
+      135deg,
+      $light-color,
+      #d8bfd8
+    ); // 柔和的蓝紫色渐变
     // 添加边框边晕效果
-    box-shadow: 0 0 20px 5px rgba($primary-color, 0.6), 0 0 40px 10px rgba($primary-color, 0.4), 0 0 60px 15px rgba($primary-color, 0.2);
+    box-shadow: 0 0 20px 5px rgba($primary-color, 0.6),
+      0 0 40px 10px rgba($primary-color, 0.4),
+      0 0 60px 15px rgba($primary-color, 0.2);
     overflow: hidden;
 
     // 添加装饰元素
     &::before {
-      content: "";
+      content: '';
       position: absolute;
       top: 0;
       left: 0;
       width: 100%;
       height: rpx(10);
-      background: linear-gradient(90deg, $primary-color, $secondary-color, $accent-color);
+      background: linear-gradient(
+        90deg,
+        $primary-color,
+        $secondary-color,
+        $accent-color
+      );
     }
   }
 }
@@ -970,13 +1008,19 @@ video.full-box-video::-webkit-media-controls-thumb {
     // 修改半透明背景色
     background-color: rgba(255, 255, 255, 0.95);
     // 添加边框边晕效果
-    box-shadow: 0 0 20px 5px rgba($primary-color, 0.6), 0 0 40px 10px rgba($primary-color, 0.4), 0 0 60px 15px rgba($primary-color, 0.2);
+    box-shadow: 0 0 20px 5px rgba($primary-color, 0.6),
+      0 0 40px 10px rgba($primary-color, 0.4),
+      0 0 60px 15px rgba($primary-color, 0.2);
   }
 }
 
 // 问题标题样式
 .question-title {
-  background: linear-gradient(90deg, rgba($primary-color, 0.2), rgba($secondary-color, 0.2));
+  background: linear-gradient(
+    90deg,
+    rgba($primary-color, 0.2),
+    rgba($secondary-color, 0.2)
+  );
   padding: rpx(15);
   border-radius: rpx(12);
   margin-bottom: rpx(20);
@@ -1063,12 +1107,15 @@ video.full-box-video::-webkit-media-controls-thumb {
   &.confirm {
     background: linear-gradient(to right, $primary-color, $secondary-color);
     border: none;
-    border-right: 15px;;
+    border-right: 15px;
     color: white;
 
-
     &:hover {
-      background: linear-gradient(to right, color.adjust($primary-color, $lightness: -5%), color.adjust($secondary-color, $lightness: -5%));
+      background: linear-gradient(
+        to right,
+        color.adjust($primary-color, $lightness: -5%),
+        color.adjust($secondary-color, $lightness: -5%)
+      );
       box-shadow: 0 rpx(3) rpx(10) rgba($primary-color, 0.4);
       transform: translateY(-rpx(1));
       color: white;
@@ -1230,8 +1277,14 @@ video.full-box-video::-webkit-media-controls-thumb {
 .child-dialog {
   border: none;
   border-radius: rpx(20);
-  background: linear-gradient(135deg, $light-color, #d8bfd8); // 柔和的蓝紫色渐变
-  box-shadow: 0 0 20px 5px rgba($primary-color, 0.6), 0 0 40px 10px rgba($primary-color, 0.4), 0 0 60px 15px rgba($primary-color, 0.2);
+  background: linear-gradient(
+    135deg,
+    $light-color,
+    #d8bfd8
+  ); // 柔和的蓝紫色渐变
+  box-shadow: 0 0 20px 5px rgba($primary-color, 0.6),
+    0 0 40px 10px rgba($primary-color, 0.4),
+    0 0 60px 15px rgba($primary-color, 0.2);
   overflow: hidden;
   padding: rpx(20);
   width: 60%;
@@ -1256,7 +1309,9 @@ video.full-box-video::-webkit-media-controls-thumb {
   border: none;
   border-radius: rpx(20);
   background: linear-gradient(135deg, $light-color, #d8bfd8);
-  box-shadow: 0 0 20px 5px rgba($primary-color, 0.6), 0 0 40px 10px rgba($primary-color, 0.4), 0 0 60px 15px rgba($primary-color, 0.2);
+  box-shadow: 0 0 20px 5px rgba($primary-color, 0.6),
+    0 0 40px 10px rgba($primary-color, 0.4),
+    0 0 60px 15px rgba($primary-color, 0.2);
   overflow: hidden;
   padding: rpx(20);
   width: 30%;
@@ -1269,13 +1324,18 @@ video.full-box-video::-webkit-media-controls-thumb {
   flex-direction: column;
 
   &::before {
-    content: "";
+    content: '';
     position: absolute;
     top: 0;
     left: 0;
     width: 100%;
     height: rpx(10);
-    background: linear-gradient(90deg, $primary-color, $secondary-color, $accent-color);
+    background: linear-gradient(
+      90deg,
+      $primary-color,
+      $secondary-color,
+      $accent-color
+    );
   }
 }
 
@@ -1314,7 +1374,6 @@ video.full-box-video::-webkit-media-controls-thumb {
   max-height: 50vh;
   padding: 5px 10px;
 
-
   .message {
     display: flex;
     align-items: flex-start;
@@ -1331,7 +1390,7 @@ video.full-box-video::-webkit-media-controls-thumb {
       margin: 0 rpx(10);
     }
 
-    .user{
+    .user {
       width: 15px;
       height: 15px;
     }
@@ -1396,7 +1455,6 @@ video.full-box-video::-webkit-media-controls-thumb {
   }
 }
 
-
 // 优化发送按钮样式
 .send-button {
   //background: linear-gradient(90deg, $primary-color, $secondary-color);
@@ -1407,4 +1465,4 @@ video.full-box-video::-webkit-media-controls-thumb {
     //background: linear-gradient(90deg, darken($primary-color, 5%), darken($secondary-color, 5%));
   }
 }
-</style>
+</style>

+ 225 - 126
src/views/AIGeneralCourse.vue

@@ -1,93 +1,97 @@
 <template>
   <!-- AI智能课 -->
   <div class="home-container">
-    <!-- 添加抽屉 -->
-    <!--   @mouseenter="buttonVisible = true" 
-        @mouseleave="buttonVisible = false"  -->
-    <div class="drawer-box">
-      <el-button
-        v-if="!drawerVisible"
-        type="primary"
-        @click="drawerVisible = true"
-        @closed="buttonVisible = false"
-        class="toggle-button"
-      >
-        教材大纲
-        <!-- <el-icon><ArrowRightBold /></el-icon> -->
-      </el-button>
-      <el-drawer v-model="drawerVisible" direction="ltr" size="19%">
-        <el-row class="tac">
-          <el-col :span="12">
-            <h3 class="mb-2">教材大纲</h3>
-            <el-menu
-            default-active="1"
-              class="el-menu-vertical-demo"
-              @open="handleOpen"
-              @close="handleClose"
-            >
-            <el-menu-item
-                v-for="(title, index) in courseTitles"
-                :key="index + 1"
-                :index="(index + 1).toString()"
-                @click="goToAIExperience(index + 1)"
-              >
-                <!-- <el-icon><icon-menu /></el-icon> -->
-                <span>0{{ index + 1 }} AI{{ title }}</span>
-              </el-menu-item>
-            </el-menu>
-          </el-col>
-        </el-row>
-      </el-drawer>
+    <!-- 展开收起侧边栏 -->
+    <div class="icon-expand">
+      <el-icon @click="toggleDrawer" :style="{ color: drawerVisible ?'white': '#B6B0D8'  }">
+        <component :is="drawerVisible ? Fold : Expand" />
+         <!-- <Tickets /> -->
+      </el-icon>
     </div>
-    <div class="box-1">
-      <div class="inner-box left-box">
-        <div class="box-icon" @click="goBack">
-          <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
-          {{pageTitle}}
-        </div>
-        <div class="dropdown-box">
-          <!-- 下拉菜单 -->
-          <el-dropdown v-model="selectedGrade">
-            <el-button type="primary">
-              {{ selectedGrade
-              }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
-            </el-button>
-            <template #dropdown>
-              <el-dropdown-menu class="dropdown-menu">
-                <el-dropdown-item>小学低年级</el-dropdown-item>
-                <el-dropdown-item>小学高年级</el-dropdown-item>
-              </el-dropdown-menu>
-            </template>
-          </el-dropdown>
+    <transition name="drawer-slide">
+      <div class="main-content" v-if="drawerVisible">
+        <!-- 菜单栏 -->
+        <div class="drawer-box">
+          <el-row class="tac">
+            <el-col :span="12">
+              <h3 class="mb-2">
+                <el-icon><Reading /></el-icon>
+                教学大纲
+              </h3>
+              <el-menu
+                default-active="1"
+                :class="{ 'el-menu-vertical-demo': true }"
+              >
+                <el-menu-item
+                  v-for="(title, index) in courseTitles"
+                  :key="index + 1"
+                  :index="(index + 1).toString()"
+                  @click="goToAIExperience(index + 1)"
+                >
+                  0{{ index + 1 }} AI{{ title }}
+                </el-menu-item>
+              </el-menu>
+            </el-col>
+          </el-row>
         </div>
       </div>
-      <div class="inner-box right-box">
-        <div class="top-right-box">
-          <el-input
-            v-model="SearchInput"
-            class="search-input"
-            placeholder="搜索"
-          >
-            <template #prefix>
-              <el-icon class="el-input__icon"><search /></el-icon>
-            </template>
-          </el-input>
+    </transition>
+
+    <div class="content-box">
+      <div class="box-1">
+        <div class="inner-box left-box">
+          <div class="box-icon" @click="goBack">
+            <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
+            {{ pageTitle }}
+          </div>
+          <div class="dropdown-box">
+            <!-- 下拉菜单 -->
+            <el-dropdown v-model="selectedGrade">
+              <el-button type="primary">
+                {{ selectedGrade
+                }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
+              </el-button>
+              <template #dropdown>
+                <el-dropdown-menu class="dropdown-menu">
+                  <el-dropdown-item>小学低年级</el-dropdown-item>
+                  <el-dropdown-item>小学高年级</el-dropdown-item>
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </div>
+        </div>
+        <div class="inner-box right-box">
+          <div class="top-right-box">
+            <el-input
+              v-model="SearchInput"
+              class="search-input"
+              placeholder="搜索"
+            >
+              <template #prefix>
+                <el-icon class="el-input__icon"><search /></el-icon>
+              </template>
+            </el-input>
+          </div>
         </div>
       </div>
-    </div>
-    <div class="box-2">
-      <div
-        class="small-box"
-        v-for="(image, index) in courseImages"
-        :key="index"
-        @click="goToAIExperience(index + 1)"
-      >
+
+      <div class="box-2">
         <div
-          class="nested-box"
-          :style="{ backgroundImage: `url(${image})`, backgroundSize: 'cover' }"
-        ></div>
-        <div class="additional-text">
-          0{{ index + 1 }} AI{{ getCourseTitle(index + 1) }}
+          class="small-box"
+          v-for="(image, index) in courseImages"
+          :key="index"
+          @click="goToAIExperience(index + 1)"
+        >
+          <div
+            class="nested-box"
+            :style="{
+              backgroundImage: `url(${image})`,
+              backgroundSize: 'cover'
+            }"
+          ></div>
+          <div class="additional-text">
+            0{{ index + 1 }} AI{{ getCourseTitle(index + 1) }}
+          </div>
         </div>
       </div>
     </div>
@@ -95,18 +99,45 @@
 </template>
 
 <script setup>
-import { ref,onMounted } from 'vue'
+import { ref, onMounted,computed } from 'vue'
 import { useRouter } from 'vue-router'
-import { ArrowDown, ArrowRightBold } from '@element-plus/icons-vue'
+// 添加 Element Plus 组件引入
+// import { ElDrawer, ElMenu, ElMenuItem, ElRow, ElCol } from 'element-plus'
+import {
+  ArrowDown,
+  ArrowRightBold,
+  Expand,
+  Reading,
+  Fold,
+  Tickets
+} from '@element-plus/icons-vue'
 import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
-const selectedButton = ref('AI通识课') // 默认选中 AI 通识课
+
+// 添加切换抽屉显示状态的函数
+const toggleDrawer = () => {
+  drawerVisible.value = !drawerVisible.value
+}
+
 const router = useRouter() // 获取当前路由对象
+// 菜单栏默认选中AI初体验
+
 // 搜索框
 const SearchInput = ref('')
+// 添加筛选后的课程标题数组
+const filteredTitles = computed(() => {
+  if (!SearchInput.value) {
+    return courseTitles
+  }
+  return courseTitles.filter(title => 
+    title.includes(SearchInput.value)
+  )
+})
+
+
 // 添加按钮显示状态
 const buttonVisible = ref(false)
 // 添加抽屉显示状态
-const drawerVisible = ref(false)
+const drawerVisible = ref(true)
 // 定义 rpx 函数
 // const rpx = (px) => px / 750 * 100
 // 添加下拉菜单选中项
@@ -115,18 +146,18 @@ const goBack = () => {
   router.go(-1) // 返回上一页
 }
 // 添加跳转课程页面的函数
-const goToAIExperience = (index) => {
+const goToAIExperience = index => {
   const routes = [
-    '/ai-initial-experience',// 跳转AI初体验
-    '/ai-develop', // 跳转AI发展历程
+    '/ai-initial-experience', // 跳转AI初体验
+    '/ai-develop' // 跳转AI发展历程
     // '/ai-development-history',
-  ];
-  const title = `0${index} AI${getCourseTitle(index)}`; // 定义 title 变量
+  ]
+  const title = `0${index} AI${getCourseTitle(index)}` // 定义 title 变量
   if (index >= 1 && index <= routes.length) {
     router.push({
       path: routes[index - 1],
-      query:{title:title}
-    });
+      query: { title: title }
+    })
   }
 }
 // 添加获取课程标题
@@ -159,13 +190,12 @@ const courseImages = ref([
 ])
 // 首页点击渲染后的页面title
 const pageTitle = ref('')
-onMounted(()=>{
+onMounted(() => {
   const title = router.currentRoute.value.query.title
   if (title) {
     pageTitle.value = title
   }
 })
-
 </script>
 
 <style scoped lang="scss">
@@ -174,50 +204,112 @@ onMounted(()=>{
 @function rpx($px) {
   @return math.div($px, 750) * 100vw;
 }
+/* 添加过渡样式 */
+.drawer-slide-enter-active,
+.drawer-slide-leave-active {
+  transition: all 0.3s ease;
+}
+.drawer-slide-enter-from,
+.drawer-slide-leave-to {
+  transform: translateX(-100%);
+  opacity: 0;
+}
 .home-container {
   position: fixed;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
-  background: linear-gradient(to bottom, #001169, #B4A8E1);
   display: flex;
-  flex-direction: column;
+  flex-direction: row;
+  background: linear-gradient(
+    to bottom,
+    #e2ddfc,
+    #f1effd
+  ); /* 设置悬停、聚焦、点击状态下的背景色 */
   gap: rpx(0);
 }
+.main-content {
+  width: rpx(135);
+  height: 100%;
+  position: relative;
+  background: linear-gradient(to bottom, #001169, #8a78d0);
+}
+.icon-expand {
+  width: rpx(30);
+  height: rpx(30);
+  z-index: 9999;
+  position: absolute;
+  cursor: pointer; // 添加鼠标指针样式
+}
+.icon-expand .el-icon {
+  font-size: rpx(15);
+  position: absolute;
+  color: white;
+  left: rpx(9);
+  margin-top: rpx(17);
+}
+.icon-expand .el-icon:active {
+  color: black;
+}
+.content-box {
+  flex: 1;
+  height: 100%;
+  display: flex;
+  flex-direction: column; /* 子元素上下排列 */
+  background: linear-gradient(
+    to bottom,
+    #e2ddfc,
+    #f1effd
+  ); /* 设置悬停、聚焦、点击状态下的背景色 */
+}
 .tac .el-menu {
   background-color: transparent;
   border: none;
   width: 100%;
+  margin-left: rpx(10);
 }
-.mb-2{
-  color: black;
+
+.el-col-12 {
+  max-width: 100%;
+}
+.mb-2 {
+  color: white;
+  font-size: rpx(11);
+  margin-left: rpx(-45);
+}
+.mb-2 .el-icon {
+  margin-right: rpx(3);
 }
-.el-menu-item{
-  width: rpx(130);
-  height: rpx(20);
+.el-menu-item {
+  width: rpx(115);
+  // height: rpx(20);
   margin-bottom: rpx(10);
   border-radius: rpx(6);
-}
-.el-menu-item span{
-  color: black;
+   color: white;
   font-size: rpx(7);
 }
+
 .el-menu ::v-deep(.el-menu-item:hover),
 .el-menu ::v-deep(.el-menu-item:focus),
 .el-menu ::v-deep(.el-menu-item:active) {
   background: linear-gradient(
     to bottom,
-    #fee78a,
-    #ffce1b
+    #ffefb0,
+    #ffcc00
   ); /* 设置悬停、聚焦、点击状态下的背景色 */
+  box-shadow: 0 8px 8px rgb(0, 0, 0,0.3);
+  color: black;
 }
+
 .drawer-box {
   position: absolute;
   display: flex;
   align-items: center;
   height: 100%;
+  width: 100%;
 }
+
 .drawer-box .toggle-button {
   width: rpx(10);
   height: rpx(50);
@@ -231,11 +323,11 @@ onMounted(()=>{
   left: 0;
 }
 .drawer-box ::v-deep(.el-drawer.ltr) {
-  background-color: rgb(255, 255, 255,0.7);
+  background-color: rgb(255, 255, 255, 0.7);
   box-shadow: 0 8px 8px rgba(202, 52, 52, 0.1);
 }
 
-.drawer-box ::v-deep(.el-drawer__header){
+.drawer-box ::v-deep(.el-drawer__header) {
   margin-bottom: rpx(0);
 }
 .drawer-box ::v-deep(.el-drawer__body)::-webkit-scrollbar {
@@ -285,7 +377,7 @@ onMounted(()=>{
   flex: 0.6;
   display: flex; // 添加 flex 布局
   align-items: center; // 垂直居中
-  color: white; // 设置图标颜色为白色
+  color: bl; // 设置图标颜色为白色
   padding-left: rpx(15);
   font-size: rpx(10); // 设置图标大小,可按需调整
   cursor: pointer; // 添加鼠标指针样式
@@ -303,18 +395,22 @@ onMounted(()=>{
   color: white;
 }
 .dropdown-box {
-  width: 50%;
+  width: 40%;
   height: 100%;
   display: flex; // 添加 flex 布局;
   flex: 1;
   align-items: center; // 垂直居中;
-  padding-right: rpx(10); // 添加右侧内边距;
+  // padding-right: rpx(0); // 添加右侧内边距;
 }
 .dropdown-box .el-button {
-  width: rpx(65); // 设置按钮宽度;
+  width: rpx(55); // 设置按钮宽度;
   height: rpx(15); // 设置按钮高度;
-  background-color: white;
+    background-color: rgb(255, 255, 255,0.7);
+   border: 1px white solid;
+  box-shadow: 0 4px 8px rgb(0, 0, 0,0.3);
   color: black;
+  border: none;
+  margin-left: rpx(10);
   border-radius: rpx(12);
   font-size: rpx(7); // 设置字体大小;
 }
@@ -327,14 +423,14 @@ onMounted(()=>{
 .dropdown-menu {
   width: rpx(100);
   height: rpx(50);
-  border-radius: rpx(6);
-  background-color: rgba(165, 209, 247, 0.5);
+  border-radius: rpx(8);
+  background-color: rgba(161, 161, 161, 0.5);
   box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
 }
 .dropdown-menu ::v-deep(.el-dropdown-menu__item) {
   font-size: rpx(8);
   color: black;
-  border-radius: rpx(6);
+  border-radius: rpx(8);
   width: rpx(78);
   height: rpx(15);
   margin-left: rpx(4);
@@ -364,23 +460,24 @@ onMounted(()=>{
 }
 .top-right-box {
   ::v-deep(.el-input__wrapper) {
-    background-color: transparent;
+    background-color: rgb(255, 255, 255,0.5);
     border-radius: rpx(12);
-    color: white;
+    border: white 1px solid;
+    color: #aaa5c5;
   }
   ::v-deep(.el-input__icon) {
-    color: white; // 设置输入框图标颜色为白色
+    color: #aaa5c5; // 设置输入框图标颜色为白色
   }
   // 添加占位符样式
   ::v-deep(.el-input__inner::placeholder) {
-    color: white;
+    color: #aaa5c5;
   }
   // 添加输入框文字颜色样式
   ::v-deep(.el-input__inner) {
-    color: white;
+    color: black;
   }
 }
-.search-input{
+.search-input {
   width: rpx(100);
   height: rpx(15);
   font-size: rpx(7);
@@ -395,6 +492,7 @@ onMounted(()=>{
   flex-wrap: wrap; // 允许子元素换行;
   align-content: center; // 顶部对齐;
   cursor: pointer; // 添加鼠标指针样式
+  margin-top: rpx(-20);
 }
 .small-box {
   flex: 0 0 calc(33.333% - rpx(10)); // 每个小盒子占三分之一宽度,减去间距
@@ -404,13 +502,14 @@ onMounted(()=>{
   flex-direction: column;
   justify-content: flex-start;
   align-items: center;
-  color: white;
+  color: black;
   font-size: rpx(8);
 }
 .nested-box {
-  width: 70%;
+  width: rpx(150);
   height: rpx(80);
   border-radius: rpx(10);
+  margin-top: rpx(5);
   display: flex;
   border: 1px solid white; // 添加边框;
   justify-content: center;
@@ -423,7 +522,7 @@ onMounted(()=>{
 .additional-text {
   margin-top: auto;
   margin-bottom: rpx(4);
-  margin-top: rpx(4);
-  font-size: rpx(6);
+  // margin-top: rpx(4);
+  font-size: rpx(7);
 }
 </style>

+ 1 - 1
src/views/AIInitialExperience.vue

@@ -124,7 +124,7 @@ const classTitles = [
   left: 0;
   right: 0;
   bottom: 0;
-  background: linear-gradient(to bottom, #001169, #B4A8E1);
+  background: linear-gradient(to bottom, #001169, #8A78D0);
   display: flex;
   flex-direction: column;
   gap: rpx(0);

+ 167 - 51
src/views/AILaboratory.vue

@@ -1,25 +1,42 @@
 <template>
   <!-- AI实验室 -->
   <div class="home-container">
-    <!-- 左侧折叠面板 -->
-    <div class="left-group">
-      <el-row class="tac">
-        <el-col :span="12">
-          <el-menu
-            default-active="2"
-            class="el-menu-vertical-demo"
-            @open="handleOpen"
-            @close="handleClose"
-          >
-            <el-menu-item v-for="(item, index) in groupList" :key="index"
-                          @click="navigateToAI(item)">
-              <el-icon><component :is="item.icon" /></el-icon>
-              <span>{{ item.title }}</span>
-            </el-menu-item>
-          </el-menu>
-        </el-col>
-      </el-row>
+    <!-- 展开收起侧边栏 -->
+    <div class="icon-expand">
+      <el-icon
+        @click="toggleDrawer"
+        :style="{ color: drawerVisible ? 'white' : '#B6B0D8' }"
+      >
+        <component :is="drawerVisible ? Fold : Expand" />
+        <Tickets />
+      </el-icon>
     </div>
+
+    <!-- 左侧折叠面板 -->
+    <transition name="drawer-slide">
+      <div class="left-group" v-if="drawerVisible">
+        <el-row class="tac">
+          <el-col :span="12">
+            <el-menu
+              default-active="2"
+              class="el-menu-vertical-demo"
+              @open="handleOpen"
+              @close="handleClose"
+            >
+              <el-menu-item
+                v-for="(item, index) in groupList"
+                :key="index"
+                @click="navigateToAI(item)"
+              >
+                <el-icon><component :is="item.icon" /></el-icon>
+                {{ item.title }}
+              </el-menu-item>
+            </el-menu>
+          </el-col>
+        </el-row>
+      </div>
+    </transition>
+
     <!-- 右侧数字人 -->
     <div class="number-people">
       <div class="title-box">
@@ -29,8 +46,8 @@
         </div>
       </div>
 
+      <!-- 动态渲染数字人 -->
       <div class="content-box">
-        <!-- 动态渲染数字人 -->
         <div
           v-for="(person, index) in peopleList"
           :key="index"
@@ -54,10 +71,22 @@ import {
   Document,
   Menu as IconMenu,
   Setting,
-  ArrowLeftBold
+  ArrowLeftBold,
+  Fold,
+  Expand,
+  ChatLineRound,
+  Picture,
+  MagicStick
 } from '@element-plus/icons-vue'
 const router = useRouter()
 
+// 添加抽屉显示状态
+const drawerVisible = ref(true)
+// 添加切换抽屉显示状态的函数
+const toggleDrawer = () => {
+  drawerVisible.value = !drawerVisible.value
+}
+
 // 返回上一页
 const goBack = () => {
   router.go(-1)
@@ -72,46 +101,92 @@ import NumberPeople05 from '@/assets/images/number-people05.png'
 
 // 渲染数字人老师及图片
 const peopleList = ref([
-  { id: 21, name: '鲁迅', image: NumberPeople01 , message: '您好,我叫鲁迅,著名的文学家、思想家、革命家、教育家、民主战士,新文化运动的重要参与者,中国现代文学的奠基人之一' },
-  { id: 22, name: '门捷列夫', image: NumberPeople02 , message: '您好,我是门捷列夫,俄国科学家,发现并归纳元素周期律,依照原子量,制作出世界上第一张元素周期表。你需要问我什么问题呢?' },
-  { id: 19, name: '牛顿', image: NumberPeople03 , message: '您好,我是牛顿爵士,生于英格兰林肯郡伍尔索普村,英国物理学家、数学家、哲学家。欢迎向我询问物理学、数学、哲学问题。' },
-  { id: 23, name: '特斯拉', image: NumberPeople04 , message: '您好,我是特斯拉,是塞尔维亚裔美籍发明家 、物理学家、机械工程师、电气工程师。有什么需要帮助的?' },
-  { id: 18, name: '李白', image: NumberPeople05 , message: '您好,我叫李白,出生于蜀郡绵州昌隆县(一说出生于西域碎叶)。我是伟大的浪漫主义诗人,经我创造书写诗文千余篇,有《李太白集》传世。欢迎向我提问诗文。' }
+  {
+    id: 21,
+    name: '鲁迅',
+    image: NumberPeople01,
+    message:
+      '您好,我叫鲁迅,著名的文学家、思想家、革命家、教育家、民主战士,新文化运动的重要参与者,中国现代文学的奠基人之一'
+  },
+  {
+    id: 22,
+    name: '门捷列夫',
+    image: NumberPeople02,
+    message:
+      '您好,我是门捷列夫,俄国科学家,发现并归纳元素周期律,依照原子量,制作出世界上第一张元素周期表。你需要问我什么问题呢?'
+  },
+  {
+    id: 19,
+    name: '牛顿',
+    image: NumberPeople03,
+    message:
+      '您好,我是牛顿爵士,生于英格兰林肯郡伍尔索普村,英国物理学家、数学家、哲学家。欢迎向我询问物理学、数学、哲学问题。'
+  },
+  {
+    id: 23,
+    name: '特斯拉',
+    image: NumberPeople04,
+    message:
+      '您好,我是特斯拉,是塞尔维亚裔美籍发明家 、物理学家、机械工程师、电气工程师。有什么需要帮助的?'
+  },
+  {
+    id: 18,
+    name: '李白',
+    image: NumberPeople05,
+    message:
+      '您好,我叫李白,出生于蜀郡绵州昌隆县(一说出生于西域碎叶)。我是伟大的浪漫主义诗人,经我创造书写诗文千余篇,有《李太白集》传世。欢迎向我提问诗文。'
+  }
 ])
 
 // 跳转页面携带名字和人物形象
 const navigateToAIQuestions = person => {
   router.push({
     // 跳转问答页面
-    path: '/ai-questions', 
-    query: {  id: person.id, name: person.name, image: person.image, message: person.message }
-  }); 
-};
+    path: '/ai-questions',
+    query: {
+      id: person.id,
+      name: person.name,
+      image: person.image,
+      message: person.message
+    }
+  })
+}
 
 // 跳转智能问答
-const navigateToAI = (group) => {
-  if (group.title === "智能问答") {
-    let person = { id: 10, name: '小智', image: NumberPeople00, message: '您好,我是您的AI智能助手小智,我会尽力回答您的问题或提供有用的建议!!!!'  };
+const navigateToAI = group => {
+  if (group.title === '智能问答') {
+    let person = {
+      id: 10,
+      name: '小智',
+      image: NumberPeople00,
+      message:
+        '您好,我是您的AI智能助手小智,我会尽力回答您的问题或提供有用的建议!!!!'
+    }
     router.push({
       // 跳转问答页面
       path: '/ai-questions',
-      query: {  id: person.id, name: person.name, image: person.image, message: person.message }
-    });
+      query: {
+        id: person.id,
+        name: person.name,
+        image: person.image,
+        message: person.message
+      }
+    })
   }
-  if (group.title === "智能绘图") {
+  if (group.title === '智能绘画') {
     router.push('/ai-painting')
   }
-};
+}
 
 // 渲染侧边栏
 const groupList = ref([
   {
-    icon: IconMenu,
+    icon: ChatLineRound,
     title: '智能问答'
   },
   {
-    icon: Document,
-    title: '智能绘图',
+    icon: MagicStick,
+    title: '智能绘画'
   },
   {
     icon: Setting,
@@ -126,6 +201,17 @@ const groupList = ref([
 @function rpx($px) {
   @return math.div($px, 750) * 100vw;
 }
+/* 添加过渡样式 */
+.drawer-slide-enter-active,
+.drawer-slide-leave-active {
+  transition: all 0.3s ease;
+}
+.drawer-slide-enter-from,
+.drawer-slide-leave-to {
+  transform: translateX(-100%);
+  opacity: 0;
+}
+
 .home-container {
   position: fixed;
   top: 0;
@@ -135,11 +221,34 @@ const groupList = ref([
   display: flex;
   flex-direction: row;
   gap: rpx(0);
+  background: linear-gradient(
+    to bottom,
+    #e2ddfc,
+    #f1effd
+  ); /* 设置悬停、聚焦、点击状态下的背景色 */
+}
+
+.icon-expand {
+  width: rpx(30);
+  height: rpx(30);
+  z-index: 9999;
+  position: absolute;
+  cursor: pointer; // 添加鼠标指针样式
+}
+.icon-expand .el-icon {
+  font-size: rpx(15);
+  position: absolute;
+  color: white;
+  left: rpx(9);
+  margin-top: rpx(17);
+}
+.icon-expand .el-icon:active {
+  color: black;
 }
 
 // 侧边栏
 .left-group {
-  width: rpx(150);
+  width: rpx(135);
   height: 100%;
   background: linear-gradient(to bottom, #001169, #b4a8e1);
 }
@@ -151,32 +260,33 @@ const groupList = ref([
   background-color: transparent;
   border: none;
   width: 100%;
-  margin-top: rpx(30);
+  margin-top: rpx(55);
   margin-left: rpx(10);
 }
 .el-menu-item {
-  width: rpx(130);
+  width: rpx(115);
   height: rpx(25);
   margin-bottom: rpx(5);
   border-radius: rpx(6);
+  color: white;
+  font-size: rpx(8);
 }
 .el-menu-item .el-icon svg {
   font-size: rpx(15);
   color: white;
 }
-.el-menu-item span {
-  color: white;
-  font-size: rpx(8);
-  padding-left: rpx(5);
-}
+
 .el-menu ::v-deep(.el-menu-item:hover),
 .el-menu ::v-deep(.el-menu-item:focus),
 .el-menu ::v-deep(.el-menu-item:active) {
   background: linear-gradient(
     to bottom,
-    #fee78a,
-    #ffce1b
+    #ffefb0,
+    #ffcc00
   ); /* 设置悬停、聚焦、点击状态下的背景色 */
+  box-shadow: 0 8px 8px rgb(0, 0, 0, 0.3);
+  color: black;
+  font-size: rpx(8);
 }
 
 // 右侧数字人内容
@@ -185,7 +295,11 @@ const groupList = ref([
   height: 100%;
   display: flex;
   flex-direction: column; /* 子元素上下排列 */
-  background-color: #e5e1fc;
+  background: linear-gradient(
+    to bottom,
+    #e2ddfc,
+    #f1effd
+  ); /* 设置悬停、聚焦、点击状态下的背景色 */
 }
 // 标题样式
 .title-box {
@@ -213,10 +327,11 @@ const groupList = ref([
   flex-wrap: wrap;
 }
 .small-box {
+  flex: 0 0 calc(30% - rpx(10)); // 每个小盒子占三分之一宽度,减去间距
   width: rpx(180);
   height: rpx(110);
   margin-top: rpx(10);
-  margin-left: rpx(15);
+  margin-left: rpx(20);
   border-radius: rpx(6);
   border: 1px solid white;
   background: rgba($color: #ffffff, $alpha: 0.5);
@@ -239,6 +354,7 @@ const groupList = ref([
 .people-box img {
   width: rpx(100);
   margin-top: rpx(75);
+  // margin-left: rpx(50) auto;
 }
 .people-title {
   font-size: rpx(8);

+ 111 - 0
src/views/AILogin.vue

@@ -0,0 +1,111 @@
+<template>
+  <!-- 登录页面 -->
+  <div class="login-content">
+    <!-- 登录输入框 -->
+    <div class="login-input">
+      <div class="input-item">
+        <!-- <h2></h2> -->
+        <el-input v-model="tenant" :prefix-icon="HomeFilled" placeholder="租户" />
+        <el-input v-model="account" :prefix-icon="Avatar" placeholder="账号" />
+        <el-input
+          v-model="password"
+          type="password"
+          :prefix-icon="Lock"
+          placeholder="密码"
+          show-password
+        />
+        <!-- 多选框 -->
+        <div class="check-box">
+          <el-checkbox v-model="checked" label="记住我" size="large" />
+          <a href="javascript:;" class="forgot-password">忘记密码?</a>
+        </div>
+
+        <el-button type="primary">登录</el-button>
+
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, computed } from 'vue'
+import { useRouter } from 'vue-router'
+import { HomeFilled, Avatar, Lock } from '@element-plus/icons-vue'
+
+// 租户
+const tenant = ref('')
+// 账号
+const account = ref('')
+// 密码
+const password = ref('')
+// 选框
+const checked = ref()
+</script>
+
+<style scoped lang="scss">
+@use 'sass:math';
+// 定义rpx转换函数
+@function rpx($px) {
+  @return math.div($px, 750) * 100vw;
+}
+.login-content {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: linear-gradient(to bottom, #001169, #8a78d0);
+  display: flex;
+  flex-direction: column;
+  gap: rpx(0);
+}
+.login-input {
+  width: rpx(210);
+  height: rpx(240);
+  margin:  auto;
+  display: flex;
+  border-radius: rpx(10);
+  background-color: rgb(255, 255, 255, 0.3);
+  border: 1px white solid;
+  box-shadow: 0 8px 8px rgb(0, 0, 0, 0.3);
+}
+.input-item {
+  margin: auto;
+  // margin-top: rpx(20);
+  // color: white;
+  // letter-spacing: rpx(5);
+}
+.input-item .el-input {
+  width: rpx(180);
+  height: rpx(18);
+  margin-bottom: rpx(15);
+}
+.input-item .el-button {
+  width: rpx(180);
+  height: rpx(18);
+  color: black;
+  font-size: rpx(8);
+  letter-spacing: rpx(10);
+  border-radius: rpx(3);
+  margin: auto;
+  border: none;
+  background: linear-gradient(to bottom, #fee78a, #ffce1b);
+  box-shadow: 0 8px 8px rgb(0, 0, 0, 0.2);
+}
+.check-box {
+  width: rpx(180);
+  height: rpx(18);
+  margin: auto;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+.check-box .el-checkbox{
+  color: white;
+}
+.check-box .forgot-password {
+  color: white;
+  font-size: rpx(6);
+  text-decoration: none;
+}
+</style>

+ 49 - 16
src/views/AIPainting.vue

@@ -1,15 +1,13 @@
 <template>
   <!-- 智能绘画 -->
   <div class="home-container">
-    <!-- 左侧折叠面板 -->
-    <div class="left-group">
+    <div class="left-group2">
       <div class="title-box">
         <div class="box-icon" @click="goBack">
           <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
           智能绘画
         </div>
       </div>
-
       <div class="img-box">
         <p>
           <img
@@ -21,6 +19,7 @@
         <p>期待你的画作喔~</p>
       </div>
     </div>
+
     <!-- 右侧AI问答 -->
     <div class="number-people">
       <div class="content-box">
@@ -29,21 +28,18 @@
           <!-- 对话消息列表 -->
           <div class="message-list">
             <div v-if="imageAllList.length > 0" v-for="(item, index) in imageAllList" :key="index">
-
               <!-- 用户消息 -->
               <div class="user-message" v-if="item.type === 'user'">
                 {{ item.content }}
               </div>
-
               <!-- AI生成图片对话框 -->
               <div class="ai-message" v-if="item.type !== 'user'">
                 {{ item.content }}
-
                 <div class="image-list" v-if="item.imageList">
                   <el-image
                       v-for="(image, index) in item.imageList"
                       :key="index"
-                      style=" width: fit-content; height: 150px; margin: 10px;"
+                      style=" width: fit-content; height: 220px; margin: 10px;"
                       :src="image"
                       :preview-src-list="item.imageList"
                       fit="cover"
@@ -76,18 +72,14 @@
             </div>
 
             <div v-else class="content-demo">
-
               <h3>请参考示例:</h3>
-
               <!-- 用户消息 -->
               <div class="user-message">
                 生成粉色的会飞的猪
               </div>
-
               <!-- AI生成图片对话框 -->
               <div class="ai-message" >
                 为您生成图片:
-
                 <div class="image-list" v-if="demoImageList">
                   <el-image
                       v-for="(image, index) in demoImageList"
@@ -129,7 +121,7 @@
             <input
               type="text"
               v-model="inputMessage"
-              placeholder="说说你的灵感..."
+              placeholder="描述任何画面..."
               @keyup.enter="sendMessage"
             />
             <button @click="sendMessage">发送</button>
@@ -198,7 +190,6 @@ const sendMessage = () => {
     })
   }
 }
-
 // 生成图片
 import { ElIcon } from 'element-plus'
 import {
@@ -235,7 +226,6 @@ const refreshWatchImages = async () => {
     if (image.status === AiImageStatusEnum.IN_PROGRESS) {
       newWatchImages[image.id] = image
     } else {
-
       imageAllList.value.pop();
       imageAllList.value.push({
         type: 'ai',
@@ -295,12 +285,55 @@ const inProgressTimerFun = () => {
 
 // 侧边栏
 .left-group {
+  width: rpx(135);
+  height: 100%;
+  background: linear-gradient(to bottom, #001169, #b4a8e1);
+}
+.mb-2 {
+  color: black;
+  margin-top: rpx(1);
+}
+.tac ::v-deep(.el-menu) {
+  background-color: transparent;
+  border: none;
+  width: 100%;
+  margin-top: rpx(55);
+  margin-left: rpx(10);
+}
+.el-menu-item {
+  width: rpx(115);
+  height: rpx(25);
+  margin-bottom: rpx(5);
+  border-radius: rpx(6);
+  color: white;
+  font-size: rpx(8);
+}
+.el-menu-item .el-icon svg {
+  font-size: rpx(15);
+  color: white;
+}
+
+.el-menu ::v-deep(.el-menu-item:hover),
+.el-menu ::v-deep(.el-menu-item:focus),
+.el-menu ::v-deep(.el-menu-item:active) {
+  background: linear-gradient(
+    to bottom,
+    #ffefb0,
+    #ffcc00
+  ); /* 设置悬停、聚焦、点击状态下的背景色 */
+  box-shadow: 0 8px 8px rgb(0, 0, 0, 0.3);
+  color: black;
+  font-size: rpx(8);
+}
+
+// 侧边栏
+.left-group2 {
   width: rpx(150);
   height: 100%;
   background-color: #ece9fd;
 }
-.left-group img {
-  width: rpx(120);
+.left-group2 img {
+  width: rpx(110);
   height: auto;
   margin-top: rpx(30);
 }

+ 4 - 2
src/views/AIQuestions.vue

@@ -57,7 +57,9 @@ import {
   Menu as IconMenu,
   Location,
   Setting,
-  ArrowLeftBold
+  ArrowLeftBold,
+  MagicStick,
+  ChatLineRound,
 } from '@element-plus/icons-vue'
 // 返回上一页
 const goBack = () => {
@@ -423,7 +425,7 @@ onMounted(async () => {
   width: rpx(120);
   // height: auto;
 }
-.selected-image{
+.selected-image {
   flex: 1;
   margin: auto;
   margin-left: rpx(-60);