Эх сурвалжийг харах

年级、大纲接口,以及视频界面样式

丸子 9 сар өмнө
parent
commit
2a36596ef8

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 1409 - 16
package-lock.json


+ 1 - 0
package.json

@@ -10,6 +10,7 @@
   },
   "dependencies": {
     "@microsoft/fetch-event-source": "^2.0.1",
+    "@vitejs/plugin-legacy": "^7.0.0",
     "axios": "^1.10.0",
     "element-plus": "^2.10.2",
     "highlight.js": "^11.11.1",

+ 21 - 5
src/api/class.js

@@ -1,10 +1,26 @@
-import axios from "@/utils/request";
+import axios from '@/utils/request'
 
 // 获取年级
-export function ClassList (data){
+export function ClassList (data) {
   return axios({
-    url: "bjdx/course-type/getTypeGrade",
+    url: 'bjdxWeb/course/getTypeGrade',
     method: 'get',
-    params: data
+    data
   })
-}
+}
+
+// 根据年级id获取教学大纲
+export function ClassOutline (id) {
+  return axios({
+    url: 'bjdxWeb/course/getTypeByGradeId?id=' + id ,
+    method: 'get'
+  })
+}
+
+// 根据类型id获取课程列表
+export function ClassType (typeId) {
+  return axios({
+    url: 'bjdxWeb/course/getCourseByTypeld?typeId=' + typeId ,
+    method: 'get'
+  })
+}

+ 11 - 0
src/api/login.js

@@ -0,0 +1,11 @@
+import axios from "@/utils/request";
+
+// 获取租户接口
+export function TenantName (data){
+  return axios({
+    url: "bjdxWeb/web/getTenantIdByName",
+    method: 'get',
+    params: data
+  })
+}
+

+ 1 - 1
src/api/questions.js

@@ -23,7 +23,7 @@ export async function sendChatMessageStream (
     onError,
     onClose
 ) {
-  return fetchEventSource(`http://192.168.110.8:8080/admin-api/bjdxWeb/ai/dialogue-send-stream`, {
+  return fetchEventSource(`http://59.110.91.129/admin-api/bjdxWeb/ai/dialogue-send-stream`, {
     method: 'post',
     headers: {
       'Content-Type': 'application/json',

+ 47 - 11
src/components/HomePage.vue

@@ -7,13 +7,12 @@
           <!-- 下拉菜单 -->
           <el-dropdown v-model="selectedGrade">
             <el-button type="primary">
-              {{ selectedGrade
-              }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
+              {{ selectedGrade }}<el-icon class="el-icon--right"><ArrowDown /></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-item v-for="item in classData" :key="item.id" :value="item.ctType">{{ item.ctType }}</el-dropdown-item>
+                <!-- <el-dropdown-item>小学高年级</el-dropdown-item> -->
               </el-dropdown-menu>
             </template>
           </el-dropdown>
@@ -79,13 +78,14 @@
 </template>
 
 <script setup>
-import { ref } from 'vue'
+import { ref,onMounted,watch } from 'vue'
 import { useRouter } from 'vue-router'
-// import { ClassList } from '@/api/class.js'
+import { ClassList } from '@/api/class.js'
 import { ArrowDown, ArrowRightBold } from '@element-plus/icons-vue'
 import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
 // 默认选中 AI 通识课
 const selectedButton = ref('AI通识课')
+
 // 获取当前路由对象
 const router = useRouter()
 // 添加图片路径
@@ -103,12 +103,48 @@ const goToAIGeneralCourse = title => {
 const goToAILab = () => {
   router.push({ path: '/ai-laboratory' })
 }
+
+
 // 添加下拉菜单选中项
-const selectedGrade = ref('小学低年级')
+const selectedGrade = ref('')
 // 获取年级
-// ClassList().then(res=>{
-//   console.log(res);
-// })
+const classData = ref([])
+const fetchCtTypes = async () => {
+  try {
+    const response = await ClassList();
+    if (response.code === 0) {
+      classData.value = response.data;
+      // 获取到数据,将第一个选项的值作为默认选中值
+      if (classData.value.length > 0) {
+        selectedGrade.value = classData.value[0].ctType;
+      }
+    }
+    console.log(classData.value,selectedGrade.value);
+  } catch (error) {
+    console.error('获取 ctType 数据失败:', error);
+  }
+}
+
+// 添加 watch 监听 selectedGrade 的变化
+watch(selectedGrade, (newValue) => {
+  console.log('当前选中的年级是:', newValue);
+  // 根据 id 切换高年级或低年级
+  const selectedItem = classData.value.find(item => item.ctType === newValue);
+  if (selectedItem) {
+    if (selectedItem.id === 3) {
+      selectedGrade.value = '小学高年级';
+      console.log(selectedGrade.value);
+    } else if (selectedItem.id === 1) {
+      selectedGrade.value = '小学低年级';
+      console.log(selectedGrade.value);
+    }
+  }
+});
+
+onMounted(() => {
+  fetchCtTypes();
+});
+
 </script>
 
 <style scoped lang="scss">
@@ -291,7 +327,7 @@ const selectedGrade = ref('小学低年级')
   height: rpx(50);
   border-radius: rpx(6);
   border: 1px white solid;
-   background-color: rgba(161, 161, 161, 0.5);
+  background-color: rgba(161, 161, 161, 0.5);
   box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
 }
 // .el-dropdown__popper.el-popper

+ 1 - 1
src/router/index.js

@@ -3,7 +3,7 @@ import App from '../App.vue'
 // import HomePage from '../components/HomePage.vue'
 
 const routes = [
-  { path: '/login', component: () => import('../views/AILogin.vue') },
+  { path: '/', component: () => import('../views/AILogin.vue') },
   // 首页
   {
     path: '/home',

+ 4 - 4
src/style.css

@@ -1,13 +1,13 @@
 /* 添加字体声明 */
-@font-face {
+/* @font-face {
   font-family: 'SourceHanSansCN-Regular';
   src: url('../assets/typeface/SourceHanSansCN-Regular_0.otf') format('opentype');
   font-weight: normal;
   font-style: normal;
-}
+} */
 :root {
-  /* font-family: 'SourceHanSansCN-Regular'; */
-  font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+  font-family: 'SemiBold';
+  /* font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; */
   line-height: 1.5;
   font-weight: normal;
   color-scheme: light dark;

+ 2 - 1
src/utils/request.js

@@ -18,7 +18,8 @@ const request = axios.create({
   // baseURL: isDev ? 'http://121.89.205.189:3000/admin' : 'http://121.89.205.189:3000/admin',
   //  baseURL: 'http://59.110.91.129:3000',
   baseURL: 'http://192.168.110.8:8080/admin-api',
-  // baseURL: 'http://127.0.0.1:8080/admin-api',
+  // baseURL: 'http://59.110.91.129/admin-api',
+  // baseURL: 'http://127.0.0.1:8080/admin-api',/
 
   // baseURL: '/api',
   // `timeout` 指定请求超时的毫秒数。

+ 343 - 226
src/views/AIDevelop.vue

@@ -1,206 +1,242 @@
 <template>
   <!-- AI发展历程 -->
   <div class="home-container">
-    <!-- 添加抽屉 -->
-    <div class="drawer-box">
-      <el-button
-        v-if="!drawerVisible"
-        type="primary"
-        @click="drawerVisible = true"
-        @closed="buttonVisible = false"
-        class="toggle-button"
+    <!-- 展开收起侧边栏 -->
+    <div class="icon-expand">
+      <el-icon
+        @click="toggleDrawer"
+        :style="{ color: drawerVisible ? 'white' : '#B6B0D8' }"
       >
-        课程小节
-      </el-button>
-      <el-drawer v-model="drawerVisible" direction="ltr" size="20%">
-        <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"
-              @select="handleSelect"
-              :default-openeds="['1']"
-            >
-              <template v-for="item in menuItems" :key="item.index">
-                <el-menu-item v-if="!item.children" :index="item.index">{{
-                  item.title
-                }}</el-menu-item>
-                <el-sub-menu v-else :index="item.index">
-                  <template #title>
-                    <span>{{ item.title }}</span>
-                  </template>
-                  <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>
-                    </template>
-                  </el-menu-item-group>
-                </el-sub-menu>
-              </template>
-            </el-menu>
-          </el-col>
-        </el-row>
-      </el-drawer>
+        <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>
-          {{ boxIconTitle }}
-        </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 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><Memo /></el-icon>
+                课程小节
+              </h3>
+              <el-menu
+                default-active="1"
+                @open="handleOpen"
+                @close="handleClose"
+                @select="handleSelect"
+                :default-openeds="['1']"
+              >
+                <template v-for="item in menuItems" :key="item.index">
+                  <el-menu-item v-if="!item.children" :index="item.index">{{
+                    item.title
+                  }}</el-menu-item>
+                  <el-sub-menu v-else :index="item.index">
+                    <template #title>
+                      <span>{{ item.title }}</span>
+                    </template>
+                    <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>
+                      </template>
+                    </el-menu-item-group>
+                  </el-sub-menu>
+                </template>
+              </el-menu>
+            </el-col>
+          </el-row>
         </div>
       </div>
-    </div>
-    <div class="box-2">
-      <!-- 课程标题 autoplay自动播放   @ended="playNextVideo"-->
-      <div class="small-title">
-        <span>{{ smallTitle }}</span>
-      </div>
-      <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>
+    </transition>
 
-      <!-- 添加切换视频 -->
-      <div class="video-switch">
-        <!-- 上一个视频 -->
-        <div class="caret-left" @click="playPreviousVideo">
-          <el-button type="warning" round>上一节</el-button>
-        </div>
-        <!-- 下一个视频 -->
-        <div class="caret-right" @click="playNextVideo">
-          <el-button type="warning" round>下一节</el-button>
-        </div>
-      </div>
-    </div>
-    <!-- 添加试题弹框 -->
-    <transition name="fade-scale">
-      <div
-        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
-              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>
+    <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>
+            {{ boxIconTitle }}
           </div>
         </div>
-        <div v-else class="no-options">
-<!--          暂无选项-->
+        <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 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="box-2">
+        <!-- 课程标题 autoplay自动播放   @ended="playNextVideo"-->
+        <div class="small-title">
+          <span>{{ smallTitle }}</span>
         </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 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>
-    </div>
-    </transition>
 
-    <!-- AI对话弹框 -->
-    <div
-      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
-          >
+        <!-- 添加切换视频 -->
+        <div class="video-switch">
+          <!-- 上一个视频 -->
+          <div class="caret-left" @click="playPreviousVideo">
+            <el-button type="warning" round>上一节</el-button>
+          </div>
+          <!-- 下一个视频 -->
+          <div class="caret-right" @click="playNextVideo">
+            <el-button type="warning" round>下一节</el-button>
+          </div>
         </div>
-        <div class="ai-dialog-content">
-          <div class="ai-message-history">
+      </div>
+      <!-- 添加试题弹框 -->
+      <transition name="fade-scale">
+        <div
+          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-for="(message, index) in messageHistory"
-              :key="index"
-              :class="['message', message.type]"
+              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>
+              </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
-                v-if="message.type === 'user'"
-                src="@/assets/images/user.png"
-                class="avatar user"
+                src="@/assets/images/xiaozhi.png"
+                alt="AI对话"
+                class="ai-icon"
               />
-              <img v-else src="@/assets/images/xiaozhi.png" class="avatar" />
-              <div class="message-content">
-                {{ message.content }}
-              </div>
+              <span class="ai-text">AI助手</span>
             </div>
           </div>
-          <el-input
-            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
+        </div>
+      </transition>
+      <!-- AI对话弹框 -->
+      <div
+        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
+            >
+          </div>
+          <div class="ai-dialog-content">
+            <div class="ai-message-history">
+              <div
+                v-for="(message, index) in messageHistory"
+                :key="index"
+                :class="['message', message.type]"
               >
-            </template>
-          </el-input>
+                <img
+                  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"
+            >
+              <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
+                >
+              </template>
+            </el-input>
+          </div>
         </div>
       </div>
     </div>
+    
   </div>
 </template>
 
 <script setup>
 import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
+// import { ClassType } from '@/api/class.js'
 import {
   ArrowDown,
   ArrowRightBold,
-  CaretRight,
-  CaretLeft
+  Expand,
+  Reading,
+  Fold,
+  Tickets,
+  Memo
+} from '@element-plus/icons-vue'
+import {
+  Document,
+  Menu as IconMenu,
+  Location,
+  Setting
 } from '@element-plus/icons-vue'
 import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
 import { valueEquals } from 'element-plus'
@@ -227,7 +263,11 @@ const SearchInput = ref('')
 // 添加按钮显示状态
 const buttonVisible = ref(false)
 // 添加抽屉显示状态
-const drawerVisible = ref(false)
+const drawerVisible = ref(true)
+// 添加切换抽屉显示状态的函数
+const toggleDrawer = () => {
+  drawerVisible.value = !drawerVisible.value
+}
 
 // 定义映射
 const videoMap = {
@@ -250,6 +290,11 @@ const videoMap = {
 // 定义视频源
 const videoSrc = ref(video1)
 
+// 课程列表
+// ClassType().then(res=>{
+//   console.log(res);
+// })
+
 // 返回上一页
 const goBack = () => {
   router.go(-1)
@@ -413,7 +458,8 @@ const videoPauseTimes = {
         title: '视频当中发生了什么事情呢?',
         options: [],
         aiQuestion: '视频当中发生了什么事情呢',
-        aiAnswer: '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
+        aiAnswer:
+          '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
       }
     ]
   },
@@ -424,7 +470,8 @@ const videoPauseTimes = {
         title: '同学们,大家了解图灵测试了吗?',
         options: [],
         aiQuestion: '视频当中发生了什么事情呢',
-        aiAnswer: '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
+        aiAnswer:
+          '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
       }
     ]
   },
@@ -435,7 +482,8 @@ const videoPauseTimes = {
         title: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
         options: [],
         aiQuestion: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
-        aiAnswer: '大模型已缩短与图灵测试的标志距离,尤其在表面对话层面,但因缺乏深层次理解、逻辑一致性与真实认知,仍无法在严格测试中稳定通过。'
+        aiAnswer:
+          '大模型已缩短与图灵测试的标志距离,尤其在表面对话层面,但因缺乏深层次理解、逻辑一致性与真实认知,仍无法在严格测试中稳定通过。'
       }
     ]
   },
@@ -444,10 +492,10 @@ const videoPauseTimes = {
     questions: []
   },
   [video6]: {
-    pauseTimes: [5],
+    pauseTimes: [5]
   },
   [video7]: {
-    pauseTimes: [64.5,91],
+    pauseTimes: [64.5, 91],
     questions: [
       {
         title: '如果你是聊天机器人,你会怎么回答用户呢?',
@@ -456,11 +504,14 @@ const videoPauseTimes = {
         aiAnswer: ''
       },
       {
-        title: '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
+        title:
+          '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
         options: [],
-        aiQuestion: '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
-        aiAnswer: '与聊天机器人的对话被人类查看时,隐私泄露风险客\n' +
-            '观存在,尤其是人类介入或安全漏洞场景下。建议优先选择支持本地'
+        aiQuestion:
+          '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
+        aiAnswer:
+          '与聊天机器人的对话被人类查看时,隐私泄露风险客\n' +
+          '观存在,尤其是人类介入或安全漏洞场景下。建议优先选择支持本地'
       }
     ]
   },
@@ -470,7 +521,8 @@ const videoPauseTimes = {
       {
         title: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
         options: [],
-        aiQuestion: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
+        aiQuestion:
+          '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
         aiAnswer: '这题没给答案,你自己去查吧!'
       }
     ]
@@ -482,12 +534,13 @@ const videoPauseTimes = {
         title: '在生活中,有哪些正在使用的专家系统呢?',
         options: [],
         aiQuestion: '在生活中,有哪些正在使用的专家系统呢?',
-        aiAnswer: '在医疗健康领域有复杂疾病协同决策和Ai医生分身与诊断辅助;在水利交通领域的水利厅专家库系统用于项目验收和抢险督查'
+        aiAnswer:
+          '在医疗健康领域有复杂疾病协同决策和Ai医生分身与诊断辅助;在水利交通领域的水利厅专家库系统用于项目验收和抢险督查'
       }
     ]
   },
   [video11]: {
-    pauseTimes: [1,90,176],
+    pauseTimes: [1, 90, 176],
     questions: [
       {
         title: '怎么会有爆炸声?泡泡怪在这里吗?',
@@ -505,12 +558,13 @@ const videoPauseTimes = {
         title: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
         options: [],
         aiQuestion: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
-        aiAnswer: '围棋是人类智力游戏的巅峰,拥有天文数字级的可能性,每颗棋子价值由全局态势动态决定,所以当前一手可能百步之后才显现价值。AlphaGo战胜人类顶尖选手,它证明了Ai不仅能处理规则明确的事物,更能攻克依赖直觉、策略的“人类专属领域”'
+        aiAnswer:
+          '围棋是人类智力游戏的巅峰,拥有天文数字级的可能性,每颗棋子价值由全局态势动态决定,所以当前一手可能百步之后才显现价值。AlphaGo战胜人类顶尖选手,它证明了Ai不仅能处理规则明确的事物,更能攻克依赖直觉、策略的“人类专属领域”'
       }
     ]
   },
   [video12]: {
-    pauseTimes: [1],
+    pauseTimes: [1]
   },
   [video13]: {
     pauseTimes: [62],
@@ -525,11 +579,9 @@ const videoPauseTimes = {
   }
 }
 
-
 // 处理视频时间更新事件
 const handleTimeUpdate = () => {
   if (!videoRef.value) return
-
   const currentTime = videoRef.value.currentTime
   const currentPauseTimes = videoPauseTimes[videoSrc.value]
   if (currentPauseTimes) {
@@ -639,6 +691,51 @@ $accent-color: rgb(133, 89, 220); // 强调色:暗蓝紫色
 $light-color: #e6e6fa; // 浅色背景:淡紫色
 $text-color: #483d8b; // 文本颜色:靛蓝色
 
+/* 添加过渡样式 */
+.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;
+}
+.main-content {
+  width: rpx(135);
+  height: 100%;
+  position: relative;
+  background: linear-gradient(to bottom, #001169, #8a78d0);
+ 
+}
+.content-box {
+  flex: 1;
+  height: 100%;
+  display: flex;
+  flex-direction: column; /* 子元素上下排列 */
+  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;
+}
 .home-container {
   position: fixed;
   top: 0;
@@ -647,9 +744,13 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
   bottom: 0;
   background: linear-gradient(to bottom, #001169, #b4a8e1);
   display: flex;
-  flex-direction: column;
+  flex-direction: row;
   gap: rpx(0);
 }
+.el-row {
+  margin: auto;
+  margin-top: rpx(40);
+}
 .tac ::v-deep(.el-menu) {
   background-color: transparent;
   border: none;
@@ -659,7 +760,7 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
 /* 取消点击后的蓝色字体 el-sub-menu__title*/
 .tac ::v-deep(.el-menu-item.is-active),
 .tac ::v-deep(.el-sub-menu__title.is-active) {
-  color: black;
+  color: white;
 }
 // 取消鼠标悬浮颜色
 .tac ::v-deep(.el-sub-menu__title) {
@@ -675,23 +776,41 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
     to bottom,
     #fee78a,
     #ffce1b
-  ); /* 设置悬停、聚焦、点击状态下的背景色 */
+  ); 
   background-color: transparent;
 }
-.drawer-box ::v-deep(.el-drawer__header) {
-  margin-bottom: rpx(0);
-}
 .mb-2 {
-  color: black;
+  color: white;
   margin-top: rpx(1);
 }
+.mb-2 .el-icon {
+  font-size: rpx(10);
+  margin-left: rpx(5);
+}
 .el-menu-item {
-  width: rpx(130);
+  width: rpx(115);
   height: rpx(20);
   margin-bottom: rpx(5);
   border-radius: rpx(6);
+  color: white;
+  font-size: rpx(7);
+  
+}
+.el-menu ::v-deep(.el-sub-menu__title){
+  color: white;
+   width: rpx(115);
+  height: rpx(20);
+  margin-bottom: rpx(5);
+  font-size: rpx(7);
 }
-.el-menu-item span {
+.el-menu ::v-deep(.el-sub-menu__title:hover),
+.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
+  ); 
   color: black;
   font-size: rpx(8);
 }
@@ -702,13 +821,30 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
     to bottom,
     #fee78a,
     #ffce1b
-  ); /* 设置悬停、聚焦、点击状态下的背景色 */
+  ); 
+  color: black;
+  font-size: rpx(8);
 }
 .drawer-box {
   position: absolute;
   display: flex;
   align-items: center;
   height: 100%;
+  width: 100%;
+  overflow-y: auto; /* 添加垂直滚动条 */
+  max-height: 100%; /* 设置最大高度 */
+  /* 添加滚动条样式 */
+  &::-webkit-scrollbar {
+    width: rpx(1);
+  }
+  &::-webkit-scrollbar-thumb {
+     background-color:#b4a8e1;
+    border-radius: rpx(5);
+  }
+  &::-webkit-scrollbar-track {
+    background-color: rgba(255, 255, 255, 0.2);
+     border-radius: rpx(5);
+  }
 }
 .drawer-box .toggle-button {
   width: rpx(10);
@@ -723,28 +859,13 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
 .toggle-button:hover {
   left: 0;
 }
-// 抽屉滚动条样式
-.drawer-box ::v-deep(.el-drawer.ltr) {
-  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__body)::-webkit-scrollbar {
-  width: rpx(2);
-}
-.drawer-box ::v-deep(.el-drawer__body)::-webkit-scrollbar-thumb {
-  background-color: rgba(0, 0, 0, 0.2);
-  border-radius: 8px;
-}
-.drawer-box ::v-deep(.el-drawer__body)::-webkit-scrollbar-track {
-  background-color: rgba(0, 0, 0, 0.05);
-  border-radius: 8px;
-}
+
 
 .toggle-button.is-active,
 .toggle-button:active,
 .toggle-button:focus {
   background-color: rgba(165, 209, 247, 0.8);
-  color: black;
+  color: white;
   border: none; // 移除点击时的边框
   outline: none; // 移除点击时的外边框
 }
@@ -752,7 +873,7 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
 .box-1 {
   width: 100%;
   height: rpx(50);
-  // margin-top: rpx(10);
+  margin-top: rpx(10);
   display: flex;
   justify-content: center;
   align-items: center;
@@ -781,7 +902,7 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
   flex: 1;
   display: flex; // 添加 flex 布局
   align-items: center; // 垂直居中
-  color: white; // 设置图标颜色为白色
+  color: black; // 设置图标颜色为白色
   padding-left: rpx(15);
   font-size: rpx(10); // 设置图标大小,可按需调整
 }
@@ -793,7 +914,7 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
 .left-box span {
   position: absolute;
   font-size: rpx(11); // 默认字体大小
-  color: white;
+  color: black;
 }
 
 .right-box {
@@ -813,14 +934,15 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
   ::v-deep(.el-input__wrapper) {
     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) {
@@ -838,7 +960,6 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
   flex: 1;
   box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
   box-sizing: border-box;
-  // padding: rpx(-20) rpx(20); // 添加左右内边距
   display: flex; // 确保子元素水平排列
   flex-wrap: wrap; // 允许子元素换行;
   align-content: center; // 顶部对齐;
@@ -867,7 +988,7 @@ video::-webkit-media-controls-panel {
   width: 100%;
   margin-top: rpx(-20);
   height: rpx(20);
-  color: white;
+  color: black;
   font-size: rpx(10);
   justify-content: center; //使子元素水平居中
 }
@@ -881,10 +1002,8 @@ video::-webkit-media-controls-panel {
 .caret-right,
 .caret-left {
   width: rpx(50);
-  // height: rpx(50);
   margin: auto;
   display: flex;
-  // grid: rpx(4);
   margin-top: rpx(5);
   margin-bottom: rpx(15);
 }
@@ -892,7 +1011,7 @@ video::-webkit-media-controls-panel {
 .caret-right ::v-deep(.el-button.is-round) {
   width: rpx(50);
   height: rpx(15);
-  color: black;
+  color: #aaa5c5;
   border-radius: none;
   border: 1px white solid;
   background-color: rgb(255, 255, 255, 0.5); // 进度条背景颜色,调浅为半透明白色
@@ -934,7 +1053,6 @@ video::-webkit-media-controls-panel {
       0 0 40px 10px rgba($primary-color, 0.4),
       0 0 60px 15px rgba($primary-color, 0.2);
     overflow: hidden;
-
     // 添加装饰元素
     &::before {
       content: '';
@@ -1439,5 +1557,4 @@ video::-webkit-media-controls-panel {
     //background: linear-gradient(90deg, darken($primary-color, 5%), darken($secondary-color, 5%));
   }
 }
-
-</style>
+</style>

+ 100 - 44
src/views/AIGeneralCourse.vue

@@ -3,11 +3,15 @@
   <div class="home-container">
     <!-- 展开收起侧边栏 -->
     <div class="icon-expand">
-      <el-icon @click="toggleDrawer" :style="{ color: drawerVisible ?'white': '#B6B0D8'  }">
+      <el-icon
+        @click="toggleDrawer"
+        :style="{ color: drawerVisible ? 'white' : '#B6B0D8' }"
+      >
         <component :is="drawerVisible ? Fold : Expand" />
-         <!-- <Tickets /> -->
+        <!-- <Tickets /> -->
       </el-icon>
     </div>
+
     <transition name="drawer-slide">
       <div class="main-content" v-if="drawerVisible">
         <!-- 菜单栏 -->
@@ -28,7 +32,7 @@
                   :index="(index + 1).toString()"
                   @click="goToAIExperience(index + 1)"
                 >
-                  0{{ index + 1 }} AI{{ title }}
+                  0{{ index + 1 }} {{ title }}
                 </el-menu-item>
               </el-menu>
             </el-col>
@@ -53,8 +57,13 @@
               </el-button>
               <template #dropdown>
                 <el-dropdown-menu class="dropdown-menu">
-                  <el-dropdown-item>小学低年级</el-dropdown-item>
-                  <el-dropdown-item>小学高年级</el-dropdown-item>
+                  <el-dropdown-item
+                    v-for="item in classData"
+                    :key="item.id"
+                    :value="item.ctType"
+                    >{{ item.ctType }}</el-dropdown-item
+                  >
+                  <!-- <el-dropdown-item>小学高年级</el-dropdown-item> -->
                 </el-dropdown-menu>
               </template>
             </el-dropdown>
@@ -90,17 +99,19 @@
             }"
           ></div>
           <div class="additional-text">
-            0{{ index + 1 }} AI{{ getCourseTitle(index + 1) }}
+            0{{ index + 1 }} {{ getCourseTitle(index + 1) }}
           </div>
         </div>
       </div>
     </div>
+    
   </div>
 </template>
 
 <script setup>
-import { ref, onMounted,computed } from 'vue'
+import { ref, onMounted, computed, watch } from 'vue'
 import { useRouter } from 'vue-router'
+import { ClassList, ClassOutline } from '@/api/class.js'
 // 添加 Element Plus 组件引入
 // import { ElDrawer, ElMenu, ElMenuItem, ElRow, ElCol } from 'element-plus'
 import {
@@ -113,13 +124,78 @@ import {
 } from '@element-plus/icons-vue'
 import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
 
+
+
+// 添加下拉菜单选中项
+const selectedGrade = ref('')
+// 获取年级
+const classData = ref([])
+// 添加接口返回的数据引用,用于存储 ClassOutline 结果
+const classOutlineData = ref([])
+
+const fetchCtTypes = async () => {
+  try {
+    const response = await ClassList()
+    if (response.code === 0) {
+      classData.value = response.data
+      // 获取到数据,将第一个选项的值作为默认选中值
+      if (classData.value.length > 0) {
+        selectedGrade.value = classData.value[0].ctType
+      }
+    }
+    console.log(classData.value, selectedGrade.value)
+  } catch (error) {
+    console.error('获取 ctType 数据失败:', error)
+  }
+}
+
+
+// 添加 watch 监听 selectedGrade 的变化
+watch(selectedGrade, newValue => {
+  console.log('当前选中的年级是:', newValue)
+  // 根据 id 切换高年级或低年级
+  const selectedItem = classData.value.find(item => item.ctType === newValue)
+  if (selectedItem) {
+    if (selectedItem.id === 1) {
+      selectedGrade.value = '小学底年级'
+      console.log(selectedGrade.value)
+    } else if (selectedItem.id === 3) {
+      selectedGrade.value = '小学高年级'
+      console.log(selectedGrade.value)
+    }
+    // 调用获取教学大纲函数并传入年级id
+    ClassOutline(selectedItem.id).then(res => {
+       if (res.code === 0) {
+        classOutlineData.value = res.data
+      }
+      console.log(classOutlineData.value)
+    })
+  }
+})
+
+// 添加获取课程标题
+const getCourseTitle = index => {
+  if (classOutlineData.value.length > 0 && index > 0 && index <= classOutlineData.value.length) {
+    return classOutlineData.value[index - 1].ctType
+  }
+  return ''
+}
+// 新增课程标题数组,依赖修改后的 getCourseTitle 函数 修改课程标题数组为 computed 属性
+const courseTitles = computed(() => {
+  return Array.from({ length: 8 }, (_, i) => getCourseTitle(i + 1))
+})
+
+onMounted(() => {
+  fetchCtTypes()
+})
+
+
 // 添加切换抽屉显示状态的函数
 const toggleDrawer = () => {
   drawerVisible.value = !drawerVisible.value
 }
 
 const router = useRouter() // 获取当前路由对象
-// 菜单栏默认选中AI初体验
 
 // 搜索框
 const SearchInput = ref('')
@@ -128,20 +204,13 @@ const filteredTitles = computed(() => {
   if (!SearchInput.value) {
     return courseTitles
   }
-  return courseTitles.filter(title => 
-    title.includes(SearchInput.value)
-  )
+  return courseTitles.filter(title => title.includes(SearchInput.value))
 })
-
-
 // 添加按钮显示状态
 const buttonVisible = ref(false)
 // 添加抽屉显示状态
 const drawerVisible = ref(true)
-// 定义 rpx 函数
-// const rpx = (px) => px / 750 * 100
-// 添加下拉菜单选中项
-const selectedGrade = ref('小学低年级')
+
 const goBack = () => {
   router.go(-1) // 返回上一页
 }
@@ -152,7 +221,8 @@ const goToAIExperience = index => {
     '/ai-develop' // 跳转AI发展历程
     // '/ai-development-history',
   ]
-  const title = `0${index} AI${getCourseTitle(index)}` // 定义 title 变量
+  // 跳转页面渲染title
+  const title = `0${index} ${getCourseTitle(index)}` // 定义 title 变量
   if (index >= 1 && index <= routes.length) {
     router.push({
       path: routes[index - 1],
@@ -160,22 +230,7 @@ const goToAIExperience = index => {
     })
   }
 }
-// 添加获取课程标题
-const getCourseTitle = index => {
-  const titles = [
-    '初体验',
-    '发展历程',
-    '与机器人',
-    '的超级大脑-芯片',
-    '的智能应用',
-    '数据表征与感知智能',
-    '如何学习',
-    '伦理安全'
-  ]
-  return titles[index - 1]
-}
-// 新增课程标题数组
-const courseTitles = Array.from({ length: 8 }, (_, i) => getCourseTitle(i + 1))
+
 
 // 添加图片路径数组
 const courseImages = ref([
@@ -234,6 +289,8 @@ onMounted(() => {
   height: 100%;
   position: relative;
   background: linear-gradient(to bottom, #001169, #8a78d0);
+    overflow-y: auto; /* 添加垂直滚动条 */
+  max-height: 100%; /* 设置最大高度 */
 }
 .icon-expand {
   width: rpx(30);
@@ -271,22 +328,21 @@ onMounted(() => {
 }
 
 .el-col-12 {
-  max-width: 100%;
+  // max-width: 100%;
 }
 .mb-2 {
   color: white;
-  font-size: rpx(11);
-  margin-left: rpx(-45);
 }
 .mb-2 .el-icon {
-  margin-right: rpx(3);
+  font-size: rpx(10);
+  margin-left: rpx(5);
 }
 .el-menu-item {
   width: rpx(115);
   // height: rpx(20);
   margin-bottom: rpx(10);
   border-radius: rpx(6);
-   color: white;
+  color: white;
   font-size: rpx(7);
 }
 
@@ -298,7 +354,7 @@ onMounted(() => {
     #ffefb0,
     #ffcc00
   ); /* 设置悬停、聚焦、点击状态下的背景色 */
-  box-shadow: 0 8px 8px rgb(0, 0, 0,0.3);
+  box-shadow: 0 8px 8px rgb(0, 0, 0, 0.3);
   color: black;
 }
 
@@ -405,9 +461,9 @@ onMounted(() => {
 .dropdown-box .el-button {
   width: rpx(55); // 设置按钮宽度;
   height: rpx(15); // 设置按钮高度;
-    background-color: rgb(255, 255, 255,0.7);
-   border: 1px white solid;
-  box-shadow: 0 4px 8px rgb(0, 0, 0,0.3);
+  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);
@@ -460,7 +516,7 @@ onMounted(() => {
 }
 .top-right-box {
   ::v-deep(.el-input__wrapper) {
-    background-color: rgb(255, 255, 255,0.5);
+    background-color: rgb(255, 255, 255, 0.5);
     border-radius: rpx(12);
     border: white 1px solid;
     color: #aaa5c5;

+ 1194 - 63
src/views/AIInitialExperience.vue

@@ -1,5 +1,5 @@
 <template>
-  <!-- AI初体验 -->
+  <!-- AI发展历程 -->
   <div class="home-container">
     <!-- 添加抽屉 -->
     <div class="drawer-box">
@@ -11,7 +11,6 @@
         class="toggle-button"
       >
         课程小节
-        <!-- <el-icon><ArrowRightBold /></el-icon> -->
       </el-button>
       <el-drawer v-model="drawerVisible" direction="ltr" size="20%">
         <el-row class="tac">
@@ -22,15 +21,26 @@
               class="el-menu-vertical-demo"
               @open="handleOpen"
               @close="handleClose"
+              @select="handleSelect"
+              :default-openeds="['1']"
             >
-            <el-menu-item
-                v-for="(title, index) in classTitles"
-                :key="index + 1"
-                :index="(index + 1).toString()"
-              >
-                <!-- <el-icon><icon-menu /></el-icon> -->
-                <span>{{ title }}</span>
-              </el-menu-item>
+              <template v-for="item in menuItems" :key="item.index">
+                <el-menu-item v-if="!item.children" :index="item.index">{{
+                  item.title
+                }}</el-menu-item>
+                <el-sub-menu v-else :index="item.index">
+                  <template #title>
+                    <span>{{ item.title }}</span>
+                  </template>
+                  <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>
+                    </template>
+                  </el-menu-item-group>
+                </el-sub-menu>
+              </template>
             </el-menu>
           </el-col>
         </el-row>
@@ -41,7 +51,7 @@
       <div class="inner-box left-box">
         <div class="box-icon" @click="goBack">
           <el-icon class="left-icon"><ArrowLeftBold /></el-icon>
-         {{boxIconTitle}}
+          {{ boxIconTitle }}
         </div>
       </div>
       <div class="inner-box right-box">
@@ -59,20 +69,158 @@
       </div>
     </div>
     <div class="box-2">
-      <video class="full-box-video" controls>
-        <source src="" type="video/mp4">
-        您的浏览器不支持视频播放。
-      </video>
+      <!-- 课程标题 autoplay自动播放   @ended="playNextVideo"-->
+      <div class="small-title">
+        <span>{{ smallTitle }}</span>
+      </div>
+      <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>
+        </div>
+        <!-- 下一个视频 -->
+        <div class="caret-right" @click="playNextVideo">
+          <el-button type="warning" round>下一节</el-button>
+        </div>
+      </div>
+    </div>
+    <!-- 添加试题弹框 -->
+    <transition name="fade-scale">
+      <div
+        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
+              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>
+          </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"
+    >
+      <div class="ai-dialog">
+        <div class="ai-dialog-header">
+          <h3>小智智能助手</h3>
+          <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]"
+            >
+              <img
+                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"
+          >
+            <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
+              >
+            </template>
+          </el-input>
+        </div>
+      </div>
     </div>
   </div>
 </template>
 
 <script setup>
-import { ref,onMounted } from 'vue'
+import { ref, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
-import { ArrowDown, ArrowRightBold } 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'
+// 引入视频
+import video1 from '@/assets/02video/01video.mp4'
+import video2 from '@/assets/02video/02video.mp4'
+import video3 from '@/assets/02video/03video.mp4'
+import video4 from '@/assets/02video/04video.mp4'
+import video5 from '@/assets/02video/05video.mp4'
+import video6 from '@/assets/02video/06video.mp4'
+import video7 from '@/assets/02video/07video.mp4'
+import video8 from '@/assets/02video/08video.mp4'
+import video9 from '@/assets/02video/09video.mp4'
+import video10 from '@/assets/02video/10video.mp4'
+import video11 from '@/assets/02video/11video.mp4'
+import video12 from '@/assets/02video/12video.mp4'
+import video13 from '@/assets/02video/13video.mp4'
+import video14 from '@/assets/02video/14video.mp4'
+import video15 from '@/assets/02video/15video.mp4'
+
 const router = useRouter() // 获取当前路由对象
 // 搜索框
 const SearchInput = ref('')
@@ -80,76 +228,472 @@ const SearchInput = ref('')
 const buttonVisible = ref(false)
 // 添加抽屉显示状态
 const drawerVisible = ref(false)
+
+// 定义映射
+const videoMap = {
+  '1-1': video1,
+  '1-2': video2,
+  '1-3': video3,
+  '1-4': video4,
+  '1-5': video5,
+  '1-6': video6,
+  '1-7': video7,
+  '1-8': video8,
+  '1-9': video9,
+  '1-10': video10,
+  '1-11': video11,
+  '1-12': video12,
+  '1-13': video13,
+  '1-14': video14,
+  '1-15': video15
+}
+// 定义视频源
+const videoSrc = ref(video1)
+
 // 返回上一页
 const goBack = () => {
-  router.go(-1) 
+  router.go(-1)
 }
-// 渲染标题
+// 渲染页面标题
 const boxIconTitle = ref('')
 onMounted(() => {
   const title = router.currentRoute.value.query.title
-  if(title){
+  if (title) {
     boxIconTitle.value = String(title)
   }
 })
-// 添加获取抽屉课节标题
-const classTitles = [
-    '课前回顾',
-    '课程引入',
-    '图灵测试',
-    '课堂提问',
-    '达特茅斯会议',
-    '课堂选择',
-    '聊天机器人',
-    '专家系统',
-    '课堂互动',
-    '互联网快速发展',
-    '黄金时代',
-    '课堂提问',
-    '大模型时代',
-    '趣味实操',
-    '课程总结'
-]
+
+// 菜单打开和关闭的处理函数
+const handleOpen = () => {}
+const handleClose = () => {}
+
+// 动态渲染树型结构
+const menuItems = ref([
+  { index: '1-1', title: '课前回顾' },
+  { index: '1-2', title: '课程引入' },
+  {
+    index: '1',
+    title: '知识讲解',
+    children: [
+      { index: '1-3', title: '图灵测试' },
+      { index: '1-4', title: '课堂提问' },
+      { index: '1-5', title: '达特茅斯会议' },
+      { index: '1-6', title: '课堂选择' },
+      { index: '1-7', title: '聊天机器人' },
+      { index: '1-8', title: '专家系统' },
+      { index: '1-9', title: '课堂互动' },
+      { index: '1-10', title: '互联网快速发展' },
+      { index: '1-11', title: '黄金时代' },
+      { index: '1-12', title: '课堂提问' },
+      { index: '1-13', title: '大模型时代' }
+    ]
+  },
+  { index: '1-14', title: '趣味实操' },
+  { index: '1-15', title: '课程总结' }
+])
+
+// 当前播放的索引
+const currentIndex = ref('1-1')
+
+// 渲染课程标题到视频上方
+const smallTitle = ref('课前回顾')
+const handleSelect = index => {
+  const findTitle = items => {
+    for (const item of items) {
+      if (item.index === index) {
+        return item.title
+      }
+      if (item.children) {
+        const result = findTitle(item.children)
+        if (result) {
+          return result
+        }
+      }
+    }
+    return null
+  }
+  const title = findTitle(menuItems.value)
+  if (title) {
+    smallTitle.value = title
+  }
+  // 根据索引切换视频
+  if (videoMap[index]) {
+    videoSrc.value = videoMap[index]
+    currentIndex.value = index
+  }
+  // 选中标题后关闭抽屉
+  drawerVisible.value = false
+}
+
+// 展平所有菜单项索引
+const flattenMenuItems = () => {
+  const indices = []
+  const traverse = items => {
+    for (const item of items) {
+      if (!item.children) {
+        indices.push(item.index)
+      } else {
+        traverse(item.children)
+      }
+    }
+  }
+  traverse(menuItems.value)
+  return indices
+}
+
+// 播放下一个视频
+const playNextVideo = () => {
+  const allIndices = flattenMenuItems()
+  const currentIndexInList = allIndices.indexOf(currentIndex.value)
+  if (currentIndexInList !== -1 && currentIndexInList < allIndices.length - 1) {
+    const nextIndex = allIndices[currentIndexInList + 1]
+    handleSelect(nextIndex)
+    // 切换视频后自动播放
+    if (videoRef.value) {
+      videoRef.value.addEventListener('loadedmetadata', tryPlayVideo, {
+        once: true
+      })
+    }
+  }
+  // 重置
+  pausedIndices = ref([])
+  userMessage = ref('')
+  messageHistory = ref([])
+}
+// 切换视频
+// 播放上一个视频
+const playPreviousVideo = () => {
+  const allIndices = flattenMenuItems()
+  const currentIndexInList = allIndices.indexOf(currentIndex.value)
+  if (currentIndexInList > 0) {
+    const previousIndex = allIndices[currentIndexInList - 1]
+    handleSelect(previousIndex)
+    // 切换视频后自动播放
+    if (videoRef.value) {
+      videoRef.value.addEventListener('loadedmetadata', tryPlayVideo, {
+        once: true
+      })
+    }
+  }
+}
+// 尝试播放视频,处理浏览器自动播放限制
+const tryPlayVideo = () => {
+  const playPromise = videoRef.value.play()
+  if (playPromise !== undefined) {
+    playPromise.catch(error => {
+      console.error('视频播放失败,可能是浏览器自动播放限制:', error)
+    })
+  }
+}
+
+// 视频 ref
+const videoRef = ref(null)
+// 记录已经暂停过的时间点索引
+let pausedIndices = ref([])
+// 试题弹框显示状态
+const questionDialogVisible = ref(false)
+// 当前显示的试题
+const currentQuestion = ref({ title: '', options: [] })
+// 用户选择的选项
+const selectedOption = ref(null)
+
+// AI对话弹出框显示状态
+let showAIDialog = ref(false)
+// 用户输入的消息
+let userMessage = ref('')
+// 消息历史记录
+let messageHistory = ref([])
+
+// 定义每个视频对应的暂停时间和问题
+const videoPauseTimes = {
+  [video2]: {
+    pauseTimes: [30],
+    questions: [
+      {
+        title: '视频当中发生了什么事情呢?',
+        options: [],
+        aiQuestion: '视频当中发生了什么事情呢',
+        aiAnswer: '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
+      }
+    ]
+  },
+  [video3]: {
+    pauseTimes: [49],
+    questions: [
+      {
+        title: '同学们,大家了解图灵测试了吗?',
+        options: [],
+        aiQuestion: '视频当中发生了什么事情呢',
+        aiAnswer: '让我来告诉你吧:泡泡怪篡改了Ai历史数据,导致Ai系统发生崩溃,所以要修正Ai历史抓到泡泡怪!'
+      }
+    ]
+  },
+  [video4]: {
+    pauseTimes: [2],
+    questions: [
+      {
+        title: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
+        options: [],
+        aiQuestion: '你觉得deepseek、豆包等大模型可以通过图灵测试吗?为什么?',
+        aiAnswer: '大模型已缩短与图灵测试的标志距离,尤其在表面对话层面,但因缺乏深层次理解、逻辑一致性与真实认知,仍无法在严格测试中稳定通过。'
+      }
+    ]
+  },
+  [video5]: {
+    pauseTimes: [49],
+    questions: []
+  },
+  [video6]: {
+    pauseTimes: [5],
+  },
+  [video7]: {
+    pauseTimes: [64.5,91],
+    questions: [
+      {
+        title: '如果你是聊天机器人,你会怎么回答用户呢?',
+        options: [],
+        aiQuestion: '',
+        aiAnswer: ''
+      },
+      {
+        title: '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
+        options: [],
+        aiQuestion: '当我们和聊天机器人对话的内容被人类所查看并回答时,隐私信息是否泄露?',
+        aiAnswer: '与聊天机器人的对话被人类查看时,隐私泄露风险客\n' +
+            '观存在,尤其是人类介入或安全漏洞场景下。建议优先选择支持本地'
+      }
+    ]
+  },
+  [video8]: {
+    pauseTimes: [72],
+    questions: [
+      {
+        title: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
+        options: [],
+        aiQuestion: '如果你身体不舒服时找这样的专家检查,那么它开的药你敢喝吗?',
+        aiAnswer: '这题没给答案,你自己去查吧!'
+      }
+    ]
+  },
+  [video9]: {
+    pauseTimes: [2],
+    questions: [
+      {
+        title: '在生活中,有哪些正在使用的专家系统呢?',
+        options: [],
+        aiQuestion: '在生活中,有哪些正在使用的专家系统呢?',
+        aiAnswer: '在医疗健康领域有复杂疾病协同决策和Ai医生分身与诊断辅助;在水利交通领域的水利厅专家库系统用于项目验收和抢险督查'
+      }
+    ]
+  },
+  [video11]: {
+    pauseTimes: [1,90,176],
+    questions: [
+      {
+        title: '怎么会有爆炸声?泡泡怪在这里吗?',
+        options: [],
+        aiQuestion: '',
+        aiAnswer: ''
+      },
+      {
+        title: '同学们喜欢下围棋吗?',
+        options: [],
+        aiQuestion: '',
+        aiAnswer: ''
+      },
+      {
+        title: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
+        options: [],
+        aiQuestion: '为什么AlphaGo要在围棋上攻克真人冠军呢?',
+        aiAnswer: '围棋是人类智力游戏的巅峰,拥有天文数字级的可能性,每颗棋子价值由全局态势动态决定,所以当前一手可能百步之后才显现价值。AlphaGo战胜人类顶尖选手,它证明了Ai不仅能处理规则明确的事物,更能攻克依赖直觉、策略的“人类专属领域”'
+      }
+    ]
+  },
+  [video12]: {
+    pauseTimes: [1],
+  },
+  [video13]: {
+    pauseTimes: [62],
+    questions: [
+      {
+        title: '我们一起来感受一下大模型吧!',
+        options: [],
+        aiQuestion: '',
+        aiAnswer: ''
+      }
+    ]
+  }
+}
+
+
+// 处理视频时间更新事件
+const handleTimeUpdate = () => {
+  if (!videoRef.value) return
+
+  const currentTime = videoRef.value.currentTime
+  const currentPauseTimes = videoPauseTimes[videoSrc.value]
+  if (currentPauseTimes) {
+    currentPauseTimes.pauseTimes.forEach((time, index) => {
+      // 检查是否到达时间点且还未暂停过
+      if (currentTime >= time && !pausedIndices.value.includes(index)) {
+        videoRef.value.pause()
+        pausedIndices.value.push(index)
+        // 显示对应的问题
+        if (currentPauseTimes.questions[index]) {
+          currentQuestion.value = currentPauseTimes.questions[index]
+          questionDialogVisible.value = true
+        }
+      }
+    })
+  }
+}
+// 关闭试题弹框
+const handleCloseQuestionDialog = () => {
+  questionDialogVisible.value = false
+  // 继续播放视频
+  videoRef.value.play()
+}
+
+// 提交答案
+const handleSubmitAnswer = () => {
+  // 这里可以添加答案验证逻辑
+  console.log('用户选择的答案是:', selectedOption.value)
+  questionDialogVisible.value = false
+  // 继续播放视频
+  videoRef.value.play()
+  selectedOption.value = null
+}
+
+// 发送消息
+const sendMessage = async () => {
+  if (userMessage.value.trim()) {
+    // 添加用户消息到历史记录
+    messageHistory.value.push({
+      type: 'user',
+      content: userMessage.value
+    })
+
+    // 模拟 AI 回复
+    const aiResponse = await simulateAIResponse(userMessage.value)
+    messageHistory.value.push({
+      type: 'ai',
+      content: aiResponse
+    })
+
+    // 清空输入框
+    userMessage.value = ''
+  }
+}
+
+// 处理 AI 助手点击事件
+const handleAIClick = () => {
+  // 清空输入框
+  messageHistory = ref([])
+  if (currentQuestion.value.aiQuestion) {
+    userMessage.value = currentQuestion.value.aiQuestion
+    sendMessage()
+    userMessage.value = ''
+  }
+
+  showAIDialog.value = true
+}
+
+// 模拟 AI 回复
+const simulateAIResponse = question => {
+  return new Promise(resolve => {
+    setTimeout(() => {
+      const currentVideoInfo = videoPauseTimes[videoSrc.value]
+      if (currentVideoInfo) {
+        const currentQuestionObj = currentVideoInfo.questions.find(
+          q => q.aiQuestion === question
+        )
+        if (currentQuestionObj && currentQuestionObj.aiAnswer) {
+          resolve(currentQuestionObj.aiAnswer)
+          return
+        }
+      }
+      // 若未匹配到自定义回复,给出默认回复
+      resolve(`您的问题是:${question},这是 AI 的回复示例。`)
+    }, 1000)
+  })
+}
+
+// 关闭AI对话弹出框
+const handleCloseAIDialog = () => {
+  showAIDialog.value = false
+}
 </script>
 
 <style scoped lang="scss">
 @use 'sass:math';
+@use 'sass:color'; // 引入 color 模块
 // 定义rpx转换函数
 @function rpx($px) {
   @return math.div($px, 750) * 100vw;
 }
+
+// 定义儿童风格的蓝紫色调
+$primary-color: rgba(106, 90, 205, 0.52); // 主色调:蓝紫色
+$secondary-color: rgba(147, 112, 219, 0.66); // 辅助色:亮蓝紫色
+$accent-color: rgb(133, 89, 220); // 强调色:暗蓝紫色
+$light-color: #e6e6fa; // 浅色背景:淡紫色
+$text-color: #483d8b; // 文本颜色:靛蓝色
+
 .home-container {
   position: fixed;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
-  background: linear-gradient(to bottom, #001169, #8A78D0);
+  background: linear-gradient(to bottom, #001169, #b4a8e1);
   display: flex;
   flex-direction: column;
   gap: rpx(0);
 }
-.tac .el-menu {
+.tac ::v-deep(.el-menu) {
   background-color: transparent;
   border: none;
   width: 100%;
 }
-.drawer-box ::v-deep(.el-drawer__header){
+
+/* 取消点击后的蓝色字体 el-sub-menu__title*/
+.tac ::v-deep(.el-menu-item.is-active),
+.tac ::v-deep(.el-sub-menu__title.is-active) {
+  color: black;
+}
+// 取消鼠标悬浮颜色
+.tac ::v-deep(.el-sub-menu__title) {
+  width: rpx(130);
+  height: rpx(20);
+  margin-bottom: rpx(5);
+  border-radius: rpx(6);
+}
+.el-menu ::v-deep(.el-sub-menu__title:hover),
+.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
+  ); /* 设置悬停、聚焦、点击状态下的背景色 */
+  background-color: transparent;
+}
+.drawer-box ::v-deep(.el-drawer__header) {
   margin-bottom: rpx(0);
 }
-.mb-2{
+.mb-2 {
   color: black;
   margin-top: rpx(1);
 }
-.el-menu-item{
+.el-menu-item {
   width: rpx(130);
   height: rpx(20);
   margin-bottom: rpx(5);
   border-radius: rpx(6);
 }
-.el-menu-item span{
+.el-menu-item span {
   color: black;
-  font-size: rpx(7);
+  font-size: rpx(8);
 }
 .el-menu ::v-deep(.el-menu-item:hover),
 .el-menu ::v-deep(.el-menu-item:focus),
@@ -169,7 +713,8 @@ const classTitles = [
 .drawer-box .toggle-button {
   width: rpx(10);
   height: rpx(50);
-  background-color: rgba(165, 209, 247, 0.2);
+  font-size: rpx(7);
+  background-color: rgba(17, 23, 29, 0.2);
   border: none;
   position: relative;
   writing-mode: vertical-lr; // 文字垂直排列,从左到右
@@ -180,7 +725,7 @@ const classTitles = [
 }
 // 抽屉滚动条样式
 .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__body)::-webkit-scrollbar {
@@ -206,12 +751,13 @@ const classTitles = [
 
 .box-1 {
   width: 100%;
-  flex: 0.3;
+  height: rpx(50);
+  // margin-top: rpx(10);
   display: flex;
   justify-content: center;
   align-items: center;
   box-sizing: border-box;
-  font-size: rpx(16); // 默认字体大小
+  font-size: rpx(15); // 默认字体大小
 }
 
 .inner-box {
@@ -227,7 +773,7 @@ const classTitles = [
   justify-content: flex-start;
   align-items: flex-start;
   flex: 1; // 设置左侧盒子占比为 2
-   cursor: pointer; // 添加鼠标指针样式
+  cursor: pointer; // 添加鼠标指针样式
 }
 .box-icon {
   width: 100%;
@@ -246,19 +792,17 @@ const classTitles = [
 
 .left-box span {
   position: absolute;
-  top: 20px;
-  left: 20px;
   font-size: rpx(11); // 默认字体大小
   color: white;
 }
 
 .right-box {
-  flex: 2;
+  flex: 1;
   position: relative; // 添加相对定位;
 }
 .top-right-box {
   position: absolute; // 添加绝对定位
-  margin-top: rpx(10); // 调整上边距离
+  margin-top: rpx(20); // 调整上边距离
   margin-right: rpx(50); // 调整右边距离
   width: 100%; // 设置盒子宽度,可按需调整
   height: 60px; // 设置盒子高度,可按需调整
@@ -267,7 +811,7 @@ const classTitles = [
 }
 .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;
   }
@@ -280,33 +824,620 @@ const classTitles = [
   }
   // 添加输入框文字颜色样式
   ::v-deep(.el-input__inner) {
-    color: white;
+    color: black;
   }
 }
 // 搜索框
-.search-input{
+.search-input {
   width: rpx(100);
   height: rpx(15);
   font-size: rpx(7);
 }
 .box-2 {
-  // width: 100%;
-  flex: 2;
+  width: 100%;
+  flex: 1;
   box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
   box-sizing: border-box;
-  padding: 0 rpx(30); // 添加左右内边距
+  // padding: rpx(-20) rpx(20); // 添加左右内边距
   display: flex; // 确保子元素水平排列
   flex-wrap: wrap; // 允许子元素换行;
   align-content: center; // 顶部对齐;
   cursor: pointer; // 添加鼠标指针样式
+}
+.box-video {
+  width: 100%;
+  height: rpx(300);
   video.full-box-video {
     // width: 100%;
-    height: rpx(150);
+    height: rpx(280);
     margin: 0 auto;
     border-radius: rpx(12);
     box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
     object-fit: cover;
-    background-color: #000;
+    // object-fit: contain;
+  }
+}
+
+/* 隐藏 Chrome 视频控件的渐变背景等默认样式 */
+video::-webkit-media-controls-panel {
+  background: transparent !important; /* 去掉背景渐变,设为透明 */
+}
+
+.small-title {
+  width: 100%;
+  margin-top: rpx(-20);
+  height: rpx(20);
+  color: white;
+  font-size: rpx(10);
+  justify-content: center; //使子元素水平居中
+}
+.video-switch {
+  width: 100%;
+  // height: rpx(50);
+  display: flex;
+  margin-top: rpx(-20);
+  // background-color: saddlebrown;
+}
+.caret-right,
+.caret-left {
+  width: rpx(50);
+  // height: rpx(50);
+  margin: auto;
+  display: flex;
+  // grid: rpx(4);
+  margin-top: rpx(5);
+  margin-bottom: rpx(15);
+}
+.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;
+  border: 1px white solid;
+  background-color: rgb(255, 255, 255, 0.5); // 进度条背景颜色,调浅为半透明白色
+  box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
+}
+
+// 儿童风格试题弹框样式
+.child-dialog {
+  .el-dialog__header {
+    display: none; // 隐藏原有的标题栏
+  }
+
+  .el-dialog__body {
+    padding: rpx(20);
+    position: relative;
+  }
+
+  .el-dialog__footer {
+    border-top: none;
+    padding: rpx(10) rpx(20);
+    text-align: center;
+  }
+
+  .el-dialog__wrapper {
+    // 修改半透明背景色
+    background-color: rgba(0, 0, 0, 0.6);
+  }
+
+  .el-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);
+    overflow: hidden;
+
+    // 添加装饰元素
+    &::before {
+      content: '';
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: rpx(10);
+      background: linear-gradient(
+        90deg,
+        $primary-color,
+        $secondary-color,
+        $accent-color
+      );
+    }
+  }
+}
+
+// AI对话弹出框样式
+.ai-dialog {
+  .el-dialog__header {
+    background: linear-gradient(90deg, $primary-color, $secondary-color);
+    color: white;
+    padding: rpx(10) rpx(20);
+    border-radius: rpx(10) rpx(10) 0 0;
+
+    .el-dialog__title {
+      font-size: rpx(12);
+    }
+  }
+
+  .el-dialog__body {
+    padding: rpx(15);
+    background-color: white;
+  }
+
+  .el-dialog__footer {
+    border-top: none;
+    padding: rpx(10) rpx(20);
+    text-align: right;
+  }
+
+  .el-dialog {
+    border-radius: rpx(10);
+    // 修改半透明背景色
+    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);
+  }
+}
+
+// 问题标题样式
+.question-title {
+  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);
+  color: $accent-color;
+  font-weight: bold;
+  font-size: rpx(14);
+  box-shadow: 0 rpx(3) rpx(10) rgba($primary-color, 0.1);
+  position: relative;
+  display: flex;
+  align-items: center;
+
+  .question-icon {
+    background-color: $accent-color;
+    color: white;
+    width: rpx(24);
+    height: rpx(24);
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: rpx(10);
+    font-weight: bold;
+    box-shadow: 0 rpx(2) rpx(5) rgba($accent-color, 0.3);
+  }
+}
+
+// 选项容器样式
+.options-container {
+  margin-bottom: rpx(20);
+}
+
+// 问题选项样式
+.question-option {
+  margin: rpx(8) 0;
+  padding: rpx(10) rpx(15);
+  border-radius: rpx(12);
+  border: rpx(1) solid rgba($primary-color, 0.3);
+  transition: all 0.3s ease;
+  display: flex;
+  align-items: center;
+  background-color: white;
+  box-shadow: 0 rpx(2) rpx(5) rgba($primary-color, 0.05);
+
+  ::v-deep(.el-radio__label) {
+    color: $text-color;
+    margin-left: rpx(8);
+    flex: 1;
+    text-align: left;
+    // 增大字体大小
+    font-size: rpx(12);
+  }
+
+  // 选中时的样式变化
+  .el-radio__input.is-checked + .el-radio__label {
+    font-weight: bold;
+    color: $accent-color;
+  }
+
+  &:hover {
+    background-color: rgba($primary-color, 0.05);
+    border-color: rgba($primary-color, 0.5);
+    transform: translateY(-rpx(1));
+  }
+}
+
+// 暂无选项样式
+.no-options {
+  color: rgba($text-color, 0.7);
+  text-align: center;
+  padding: rpx(20);
+  font-size: rpx(12);
+}
+
+// 底部按钮样式
+.child-button {
+  min-width: rpx(80);
+  height: rpx(30);
+  border-radius: rpx(15);
+  font-size: rpx(12);
+  font-weight: 500;
+  transition: all 0.3s ease;
+  box-shadow: 0 rpx(2) rpx(8) rgba(0, 0, 0, 0.1);
+
+  &.confirm {
+    background: linear-gradient(to right, $primary-color, $secondary-color);
+    border: none;
+    border-right: 15px;
+    color: white;
+
+    &:hover {
+      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;
+    }
+  }
+
+  &.cancel {
+    background: white;
+    border: rpx(1) solid rgba($primary-color, 0.3);
+    color: $text-color;
+
+    &:hover {
+      background: rgba($primary-color, 0.05);
+      border-color: rgba($primary-color, 0.5);
+      transform: translateY(-rpx(1));
+    }
+  }
+}
+
+// AI对话图标样式
+.ai-icon-container {
+  position: absolute;
+  bottom: rpx(20);
+  right: rpx(20);
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  cursor: pointer;
+  transition: all 0.3s ease;
+
+  &:hover {
+    transform: translateY(-rpx(2));
+  }
+
+  .ai-icon {
+    width: rpx(30);
+    height: rpx(30);
+    margin-bottom: rpx(0);
+    filter: drop-shadow(0 rpx(2) rpx(4) rgba($primary-color, 0.3));
+    // 添加过渡动画
+    transition: transform 0.3s ease;
+  }
+
+  // 悬浮时放大效果
+  .ai-icon:hover {
+    transform: scale(1.5);
+  }
+
+  .ai-text {
+    color: $text-color;
+    font-size: rpx(8);
+    background-color: rgba(255, 255, 255, 0.7);
+    padding: rpx(2) rpx(5);
+    border-radius: rpx(5);
+  }
+}
+
+// AI对话弹出框样式
+.ai-dialog {
+  .el-dialog__header {
+    background: linear-gradient(90deg, $primary-color, $secondary-color);
+    color: white;
+    padding: rpx(10) rpx(20);
+    border-radius: rpx(10) rpx(10) 0 0;
+
+    .el-dialog__title {
+      font-size: rpx(12);
+    }
+  }
+
+  .el-dialog__body {
+    padding: rpx(15);
+    background-color: white;
+  }
+
+  .el-dialog__footer {
+    border-top: none;
+    padding: rpx(10) rpx(20);
+    text-align: right;
+  }
+
+  .el-dialog {
+    border-radius: rpx(10);
+    box-shadow: 0 rpx(10) rpx(30) rgba(0, 0, 0, 0.15);
+  }
+}
+
+// AI消息样式
+.ai-message {
+  display: flex;
+  align-items: flex-start;
+  margin-bottom: rpx(15);
+
+  .ai-avatar {
+    width: rpx(30);
+    height: rpx(30);
+    border-radius: 50%;
+    margin-right: rpx(10);
+    background-color: $primary-color;
+    padding: rpx(5);
+    box-shadow: 0 rpx(2) rpx(5) rgba($primary-color, 0.2);
+  }
+
+  .ai-text-content {
+    background-color: $light-color;
+    padding: rpx(8) rpx(12);
+    border-radius: rpx(10);
+    font-size: rpx(10);
+    color: $text-color;
+    max-width: 80%;
+    box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
+  }
+}
+
+// 用户输入框样式
+.user-input {
+  ::v-deep(.el-input__wrapper) {
+    border-radius: rpx(15);
+    border-color: rgba($primary-color, 0.3);
+    margin-right: 10px;
+
+    &:focus-within {
+      box-shadow: 0 0 0 rpx(1) rgba($primary-color, 0.5);
+    }
+  }
+
+  ::v-deep(.el-input__inner) {
+    font-size: rpx(10);
+    color: $text-color;
+    text-indent: 1em;
+  }
+}
+/* 定义淡入和缩放动画 */
+.fade-scale-enter-active,
+.fade-scale-leave-active {
+  transition: all 0.5s ease;
+}
+
+.fade-scale-enter-from,
+.fade-scale-leave-to {
+  opacity: 0.1;
+  transform: scale(0.9);
+}
+
+// 自定义试题弹框背景
+.child-dialog-wrapper {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(0, 0, 0, 0.6); // 半透明背景
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 1000;
+}
+
+.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);
+  overflow: hidden;
+  padding: rpx(20);
+  width: 60%;
+  position: relative;
+}
+
+// AI对话弹框样式
+.ai-dialog-wrapper {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  z-index: 1001;
+  pointer-events: none;
+}
+
+.ai-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);
+  overflow: hidden;
+  padding: rpx(20);
+  width: 30%;
+  // 增加高度
+  height: 80%;
+  margin-right: rpx(50);
+  pointer-events: auto;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: rpx(10);
+    background: linear-gradient(
+      90deg,
+      $primary-color,
+      $secondary-color,
+      $accent-color
+    );
   }
 }
-</style>
+
+.ai-dialog-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: rpx(15);
+
+  h3 {
+    color: $text-color;
+    font-size: rpx(12);
+  }
+
+  .close-btn {
+    padding: 0;
+    width: rpx(20);
+    height: rpx(20);
+    font-size: rpx(16);
+    line-height: 1;
+  }
+}
+
+.ai-dialog-content {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+}
+
+.ai-message-history {
+  flex: 1;
+  // 当内容超出容器高度时,显示垂直滚动条
+  overflow-y: auto;
+  margin-bottom: rpx(15);
+  // 可以根据实际情况调整最大高度
+  max-height: 50vh;
+  padding: 5px 10px;
+
+  .message {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: rpx(10);
+
+    &.user {
+      flex-direction: row-reverse;
+    }
+
+    .avatar {
+      width: rpx(30);
+      height: rpx(30);
+      border-radius: 50%;
+      margin: 0 rpx(10);
+    }
+
+    .user {
+      width: 15px;
+      height: 15px;
+    }
+
+    .message-content {
+      background-color: $light-color;
+      padding: rpx(8) rpx(12);
+      border-radius: rpx(10);
+      font-size: rpx(10);
+      color: $text-color;
+      max-width: 80%;
+      box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
+    }
+  }
+  // 滚动条整体样式
+  &::-webkit-scrollbar {
+    width: rpx(4); // 滚动条宽度
+  }
+
+  // 滚动条滑块样式
+  &::-webkit-scrollbar-thumb {
+    background-color: $primary-color; // 滑块颜色
+    border-radius: rpx(4); // 滑块圆角
+    transition: background-color 0.3s ease; // 颜色过渡效果
+
+    &:hover {
+      //background-color: darken($primary-color, 10%); // 悬停时滑块颜色加深
+    }
+  }
+
+  // 滚动条轨道样式
+  &::-webkit-scrollbar-track {
+    background-color: rgba($primary-color, 0.2); // 轨道颜色
+    border-radius: rpx(4); // 轨道圆角
+  }
+
+  .message {
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: rpx(10);
+
+    &.user {
+      flex-direction: row-reverse;
+    }
+
+    .avatar {
+      width: rpx(30);
+      height: rpx(30);
+      border-radius: 50%;
+      margin: 0 rpx(10);
+    }
+
+    .message-content {
+      background-color: $light-color;
+      padding: rpx(8) rpx(12);
+      border-radius: rpx(10);
+      font-size: rpx(10);
+      color: $text-color;
+      max-width: 80%;
+      box-shadow: 0 rpx(1) rpx(3) rgba(0, 0, 0, 0.05);
+    }
+  }
+}
+
+// 优化发送按钮样式
+.send-button {
+  //background: linear-gradient(90deg, $primary-color, $secondary-color);
+  border: none;
+  color: white;
+
+  &:hover {
+    //background: linear-gradient(90deg, darken($primary-color, 5%), darken($secondary-color, 5%));
+  }
+}
+
+</style>

+ 37 - 12
src/views/AILogin.vue

@@ -4,7 +4,12 @@
     <!-- 登录输入框 -->
     <div class="login-input">
       <div class="input-item">
-        <el-input v-model="tenant" :prefix-icon="HomeFilled" placeholder="租户" />
+        <h2>AI课程</h2>
+        <el-input
+          v-model="tenant"
+          :prefix-icon="HomeFilled"
+          placeholder="租户"
+        />
         <el-input v-model="account" :prefix-icon="Avatar" placeholder="账号" />
         <el-input
           v-model="password"
@@ -20,8 +25,7 @@
         </div>
 
         <!-- 登录按钮 -->
-        <el-button type="primary">登录</el-button>
-
+        <el-button @click="LoginClick" type="primary">登录</el-button>
       </div>
     </div>
   </div>
@@ -31,6 +35,7 @@
 import { ref, onMounted, computed } from 'vue'
 import { useRouter } from 'vue-router'
 import { HomeFilled, Avatar, Lock } from '@element-plus/icons-vue'
+import { TenantName } from '@/api/login.js'
 
 // 租户
 const tenant = ref('')
@@ -40,6 +45,23 @@ const account = ref('')
 const password = ref('')
 // 选框
 const checked = ref()
+
+// 获取当前路由对象
+const router = useRouter()
+// 点击登录跳转首页
+const LoginClick = () => {
+  router.push('/home')
+}
+
+// 租户
+// const tenantName = 'exampleName'
+
+// TenantName({ name: tenantName }).then(res => {
+//   console.log('获取到的租户ID:', res.data)
+// }).catch(error => {
+//   console.error('获取租户ID失败:', error)
+// })
+
 </script>
 
 <style scoped lang="scss">
@@ -60,9 +82,9 @@ const checked = ref()
   gap: rpx(0);
 }
 .login-input {
-  width: rpx(210);
+  width: rpx(200);
   height: rpx(240);
-  margin:  auto;
+  margin: auto;
   display: flex;
   border-radius: rpx(10);
   background-color: rgb(255, 255, 255, 0.3);
@@ -71,17 +93,16 @@ const checked = ref()
 }
 .input-item {
   margin: auto;
-  // margin-top: rpx(20);
-  // color: white;
-  // letter-spacing: rpx(5);
+  margin-top: rpx(20);
+  color: white;
 }
 .input-item .el-input {
-  width: rpx(180);
+  width: rpx(160);
   height: rpx(18);
   margin-bottom: rpx(15);
 }
 .input-item .el-button {
-  width: rpx(180);
+  width: rpx(160);
   height: rpx(18);
   color: black;
   font-size: rpx(8);
@@ -90,17 +111,21 @@ const checked = ref()
   margin: auto;
   border: none;
   background: linear-gradient(to bottom, #fee78a, #ffce1b);
+}
+.input-item .el-button:hover,
+.input-item .el-button:focus,
+.input-item .el-button:active {
   box-shadow: 0 8px 8px rgb(0, 0, 0, 0.2);
 }
 .check-box {
-  width: rpx(180);
+  width: rpx(160);
   height: rpx(18);
   margin: auto;
   display: flex;
   justify-content: space-between;
   align-items: center;
 }
-.check-box .el-checkbox{
+.check-box .el-checkbox {
   color: white;
 }
 .check-box .forgot-password {

+ 11 - 3
vite.config.js

@@ -2,9 +2,17 @@ import { defineConfig } from 'vite'
 import vue from '@vitejs/plugin-vue'
 import path from 'path'
 
+// 引入@vitejs/plugin-legacy
+import legacy from '@vitejs/plugin-legacy'
+
 // https://vite.dev/config/
 export default defineConfig({
-  plugins: [vue()],
+  plugins: [
+    legacy({
+      targets: ['defaults', 'not IE 11']
+    }),
+    vue(),
+  ],
   resolve: {
     // 路径别名配置
     alias: {
@@ -13,10 +21,10 @@ export default defineConfig({
   },
   base: './',
   server: {
-    host: "0.0.0.0",
+    host: '0.0.0.0',
     proxy: {
       '/api': {
-        target: 'https://192.168.110.8:8080',
+        target: 'http://192.168.110.8:8080',
         changeOrigin: true
       }
     }

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно