Kaynağa Gözat

1、修改通识课界面
2、调取AI生成课后端接口

丸子 2 ay önce
ebeveyn
işleme
5f5b45d308

+ 18 - 10
src/api/class.js

@@ -9,21 +9,29 @@ export function ClassList (data) {
   })
 }
 
-// 根据年级id获取教学大纲 通识
-export function ClassOutline (id) {
+// 根据年级id、大纲id获取课
+export function ClassOutline(id,typeId) {
   return axios({
-    url: 'bjdxWeb/course/getTypeTsByGradeId?id=' + id ,
+    url: 'bjdxWeb/course/getTypeByGradeIdType?id=' + id +'&typeId=' + typeId ,
     method: 'get'
   })
 }
 
-// 实操课
-export function ClassOutlineSc (id) {
-  return axios({
-    url: 'bjdxWeb/course/getTypeScByGradeId?id=' + id ,
-    method: 'get'
-  })
-}
+// 根据年级id获取教学大纲 通识课
+// export function ClassOutline (id) {
+//   return axios({
+//     url: 'bjdxWeb/course/getTypeTsByGradeId?id=' + id ,
+//     method: 'get'
+//   })
+// }
+
+// // 实操课
+// export function ClassOutlineSc (id) {
+//   return axios({
+//     url: 'bjdxWeb/course/getTypeScByGradeId?id=' + id ,
+//     method: 'get'
+//   })
+// }
 
 // 根据类型id获取课程列表
 export function ClassType (typeId) {

BIN
src/assets/dialogue/number-bg.png


+ 1 - 1
src/components/HomePage.vue

@@ -48,7 +48,7 @@
         @click="goToAIGeneralCourse('AI智能课')"
         :style="{ backgroundImage: `url(${indexImages[0]})` }"
       >
-        <span>智能课</span>
+        <span>通识课</span>
       </div>
       <div
         class="center-box-in-box2"

+ 185 - 140
src/views/AIPage/AIGeneralCourse.vue

@@ -28,22 +28,31 @@
           <div class="drawer-box">
             <el-row class="tac">
               <el-col :span="12">
-                <span class="mb-2">
-                  <img :src="teachingImg" alt="教学" />
-                  教学大纲
-                </span>
                 <el-menu
-                  default-active="1"
+                  default-active="general-1"
+                  :default-openeds="['general']"
                   :class="{ 'el-menu-vertical-demo': true }"
+                  unique-opened
                 >
-                  <el-menu-item
-                    v-for="(title, index) in courseTitles"
-                    :key="index + 1"
-                    :index="(index + 1).toString()"
-                    @click="goToAIExperience(classOutlineData[index])"
+                  <!-- 课程菜单 -->
+                  <el-sub-menu 
+                    v-for="menu in menuList" 
+                    :key="menu.id"
+                    :index="menu.id"
+                    @click="showPracticalCourse = menu.isPractical; showAICourse = menu.isAICourse"
                   >
-                   {{ title }}
-                  </el-menu-item>
+                    <template #title>
+                      <span>{{ menu.title }}</span>
+                    </template>
+                    <el-menu-item
+                      v-for="(item, index) in menu.data"
+                      :key="menu.id + '-' + index"
+                      :index="menu.id + '-' + (index + 1).toString()"
+                      @click="goToAIExperience(item)"
+                    >
+                      {{ item.ctTypeSort }} {{ item.ctType }}
+                    </el-menu-item>
+                  </el-sub-menu>
                 </el-menu>
               </el-col>
             </el-row>
@@ -80,16 +89,6 @@
               </template>
             </el-dropdown>
           </div>
-          <!-- 实操课按钮 -->
-          <div class="new-button-container">
-            <el-button 
-              type="primary" 
-              @click="handleNewButtonClick"
-              :style="{ background: showPracticalCourse ? 'linear-gradient(to bottom, #ffefb0, #ffcc00)' : '#fee78a' }"
-            >
-              {{ showPracticalCourse ? '返回通识课' : '实操课' }}
-            </el-button>
-          </div>
         </div>
         <div class="inner-box right-box">
           <div class="top-right-box">
@@ -121,7 +120,7 @@
       <div class="box-2">
         <div
           class="small-box"
-          v-for="(outlineData, index) in (showPracticalCourse ? ClassOutlineScData : classOutlineData)"
+          v-for="(outlineData, index) in currentCourseData"
           :key="index"
           @click="goToAIExperience(outlineData)"
         >
@@ -144,7 +143,7 @@
 <script setup>
 import { ref, onMounted, computed, watch, onBeforeUnmount } from 'vue'
 
-import { ClassList, ClassOutline,ClassOutlineSc } from '@/api/class.js'
+import { ClassList, ClassOutline } from '@/api/class.js'
 //  Element Plus 组件引入
 import {
   ArrowUpBold,
@@ -157,72 +156,88 @@ import {
 } from '@element-plus/icons-vue'
 import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
 import { ElAutocomplete } from 'element-plus' // 导入ElAutocomplete组件
-
+import { Message } from '@/utils/message/Message.js'
 import { useRouter } from 'vue-router'
-
 import teachingImg from '@/assets/icon/teaching.png'
 
 const router = useRouter() // 获取当前路由对象
-
-// 添加下拉菜单选中项
+// 下拉菜单选中项
 const selectedGrade = ref('')
-
-// 添加抽屉显示状态
+// 抽屉显示状态
 const drawerVisible = ref(true)
-
 // 下拉框可见性状态
 const dropdownVisible = ref(false)
-
 // 处理下拉框显示/隐藏事件
 const handleVisibleChange = (visible) => {
   dropdownVisible.value = visible
 }
-
+// 通识课
+const classOutlineData = ref([])
 // 实操课
-const ClassOutlineScData = ref([])
-
-// 状态变量,跟踪当前显示的是通识课还是实操课
+const practicalCourseData = ref([])
+// AI生成课
+const aiGeneratedCourseData = ref([])
+// 状态变量,跟踪当前显示的是通识课、实操课还是AI生成课
 const showPracticalCourse = ref(false)
+// 状态变量,跟踪当前显示的是实操课还是AI生成课
+const showAICourse = ref(false)
+
+// 菜单列表计算属性
+const menuList = computed(() => [
+  {
+    id: 'general',
+    title: '通识课',
+    data: classOutlineData.value,
+    isPractical: false,
+    isAICourse: false
+  },
+  {
+    id: 'practical',
+    title: '实操课',
+    data: practicalCourseData.value,
+    isPractical: true,
+    isAICourse: false
+  },
+  {
+    id: 'ai',
+    title: 'AI生成课',
+    data: aiGeneratedCourseData.value,
+    isPractical: false,
+    isAICourse: true
+  }
+])
 
-// 统一函数来获取课程大纲数据 通识课/实操课
+// 处理课程数据,添加序号
+const processCourseData = (data) => {
+  return data.map((item, index) => {
+    item.ctTypeSort = index + 1
+    item.ctTypeSort = item.ctTypeSort > 9 ? item.ctTypeSort : "0" + item.ctTypeSort
+    return item
+  })
+}
+
+// 统一函数来获取课程大纲数据 通识课/实操课/AI生成课
 const fetchClassOutline = async (classId) => {
   try {
-    // 保存通识课数据
-    const res = await ClassOutline(classId)
-    console.log(res);
-    if (res.code === 0) {
-      classOutlineData.value = res.data
-      classOutlineData.value.map((item, index) => {
-        item.ctTypeSort = index + 1
-        item.ctTypeSort = item.ctTypeSort > 9 ? item.ctTypeSort : "0" + item.ctTypeSort
-      })
-    }
-    // 保存实操课数据
-    const Scres = await ClassOutlineSc(classId)
-    console.log(Scres);
-    if (Scres.code === 0) {
-      ClassOutlineScData.value = Scres.data
-      ClassOutlineScData.value.map((item, index) => {
-        item.ctTypeSort = index + 1
-        item.ctTypeSort = item.ctTypeSort > 9 ? item.ctTypeSort : "0" + item.ctTypeSort
-      })     
-    }
+    // 课程类型配置
+    const courseTypes = [
+      { type: "1", dataRef: classOutlineData },
+      { type: "2", dataRef: practicalCourseData },
+      { type: "3", dataRef: aiGeneratedCourseData }
+    ]
+    // 并行获取所有课程类型数据
+    await Promise.all(courseTypes.map(async (courseType) => {
+      const res = await ClassOutline(classId, courseType.type)
+      console.log(res)
+      if (res.code === 0) {
+        courseType.dataRef.value = processCourseData(res.data)
+      }
+    }))
   } catch (error) {
     console.error('获取课程大纲数据失败:', error)
   }
 }
 
-// 实操课
-const handleNewButtonClick = async() => {
-  // 切换状态
-  showPracticalCourse.value = !showPracticalCourse.value
-  // 保存状态到localStorage
-  localStorage.setItem('showPracticalCourse', showPracticalCourse.value.toString())
-  // 清空搜索框内容
-  SearchInput.value = ''
-  searchKey.value = Date.now()
-}
-
 // 处理下拉菜单选择
 const handleGradeSelect = command => {
   selectedGrade.value = command
@@ -255,8 +270,7 @@ const toggleDrawer = () => {
 }
 // 获取年级
 const classData = ref([])
-// 接口返回的数据引用,用于存储 ClassOutline 结果
-const classOutlineData = ref([])
+
 
 const fetchCtTypes = async () => {
   try {
@@ -294,38 +308,34 @@ const getCourseTitle = index => {
   return ''
 }
 
-// 课程标题数组,依赖修改后的 getCourseTitle 函数 修改课程标题数组为 computed 属性
-const courseTitles = computed(() => {
-  const data = showPracticalCourse.value ? ClassOutlineScData.value : classOutlineData.value
-  return data.map(item => {
-    return `${item.ctTypeSort} ${item.ctType}`;  
-  });
-})
-
 // 首页点击渲染后的页面title
-const pageTitle = ref('AI智能课')
+const pageTitle = ref('返回首页')
 onMounted(() => {
   fetchCtTypes()
-  const title = history.state?.title
-  if (title) {
-    pageTitle.value = title
-  }
-  // 从localStorage读取状态
-  const savedState = localStorage.getItem('showPracticalCourse')
-  if (savedState !== null) {
-    showPracticalCourse.value = savedState === 'true'
-  }
+  // const title = history.state?.title
+  // if (title) {
+  //   pageTitle.value = title
+  // }
+  // 默认显示智能课,不读取localStorage中的状态
+  showPracticalCourse.value = false
+  showAICourse.value = false
 })
 
-import { Message } from '@/utils/message/Message.js'
 
 // 搜索框
 const SearchInput = ref('')
 // 用于强制重新渲染搜索组件的key
 const searchKey = ref(Date.now())
+// 当前显示的课程数据
+const currentCourseData = computed(() => {
+  if (showAICourse.value) return aiGeneratedCourseData.value
+  if (showPracticalCourse.value) return practicalCourseData.value
+  return classOutlineData.value
+})
+
 // 搜索建议查询方法
 const querySearch = (queryString, cb) => {
-  const data = showPracticalCourse.value ? ClassOutlineScData.value : classOutlineData.value
+  const data = currentCourseData.value
   const results = queryString
     ? data.filter(item => {
         // 课程标题和序号查询
@@ -339,15 +349,13 @@ const querySearch = (queryString, cb) => {
 // 搜索选择处理方法
 const handleSearchSelect = item => {
   goToAIExperience(item)
-    // 清空输入框
+  // 清空输入框
   SearchInput.value = '';
 }
 
-
-
-// 修改过滤逻辑,直接使用classOutlineData
+// 修改过滤逻辑,直接使用currentCourseData
 const filteredTitles = computed(() => {
-  const data = showPracticalCourse.value ? ClassOutlineScData.value : classOutlineData.value
+  const data = currentCourseData.value
   if (!SearchInput.value) {
     return data
   }
@@ -357,11 +365,13 @@ const filteredTitles = computed(() => {
   )
 })
 
+
+
 // 添加按钮显示状态
 const buttonVisible = ref(false)
 
 const goBack = () => {
-  router.go(-1) // 返回上一页
+  router.push('/home') // 跳转到HomePage
 }
 
 const goToAIExperience = outlineData => {
@@ -382,10 +392,20 @@ const goToAIExperience = outlineData => {
   //     return
   //   }
   // }
-  router.push({
+  // 根据课程类型跳转到不同页面
+  if (showAICourse.value) {
+    // AI生成课跳转到对话界面
+    router.push({
+      path: '/dialog-interface',
+      state: { typeId: outlineData.id, typeName: outlineData.ctType, typeSort: outlineData.ctTypeSort }
+    })
+  } else {
+    // 其他课程保持原有的跳转逻辑
+    router.push({
       path: '/ai-develop', // 跳转视频页面
-      state: { typeId: outlineData.id, typeName: outlineData.ctType, typeSort:outlineData.ctTypeSort }
+      state: { typeId: outlineData.id, typeName: outlineData.ctType, typeSort: outlineData.ctTypeSort }
     })
+  }
 }
 </script>
 
@@ -497,29 +517,79 @@ const goToAIExperience = outlineData => {
   margin-left: rpx(10);
   margin-top: rpx(10);
 }
-
-.mb-2 {
-  color: white;
-  font-size: rpx(9);
-  margin-left: rpx(10);
-  white-space: nowrap; /* 防止文字换行 */
-}
-.mb-2 img {
-  width: rpx(15);
-  height: rpx(15);
-  vertical-align: middle;
-  margin-top: rpx(-2);
-  margin-left: 0;
+.el-sub-menu ::v-deep(.el-menu){
+  background-color: transparent;
 }
 .el-menu-item {
   width: rpx(115);
-  // height: rpx(20);
+  height: rpx(25);
   margin-bottom: rpx(5);
   border-radius: rpx(6);
   color: white;
   font-size: rpx(8);
 }
 
+.el-sub-menu ::v-deep(.el-sub-menu__title) {
+  width: rpx(115);
+  margin-bottom: rpx(5);
+  border-radius: rpx(6);
+  color: white;
+  font-size: rpx(9);
+  font-weight: bold;
+  padding-left: rpx(10) !important;
+  height: rpx(25);
+  line-height: rpx(30);
+  background: rgba(255, 255, 255, 0.1);
+  transition: all 0.3s ease;
+  // flex布局使标题和图标两端对齐
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.el-sub-menu ::v-deep(.el-sub-menu__title:hover) {
+  background: linear-gradient(
+    to bottom,
+    #ffefb0,
+    #ffcc00
+  );
+  color: black;
+  box-shadow: 0 4px 8px rgb(0, 0, 0, 0.2);
+}
+
+.el-sub-menu.is-opened ::v-deep(.el-sub-menu__title) {
+    background: linear-gradient(
+    to bottom,
+    #ffefb0,
+    #ffcc00
+  );
+    color: black;
+  box-shadow: 0 4px 8px rgb(0, 0, 0, 0.2);
+}
+
+.el-sub-menu ::v-deep(.el-icon) {
+  font-size: rpx(12);
+  color: white;
+}
+
+// 添加折叠图标样式
+.el-sub-menu ::v-deep(.el-sub-menu__icon-arrow) {
+  color: white;
+  font-size: rpx(10);
+  margin-left: auto; // 将图标推到右侧
+  margin-top: rpx(-5);
+  display: block;
+  width: rpx(16); // 确保有明确宽度
+}
+
+.el-sub-menu.is-opened ::v-deep(.el-icon) {
+  color: black;
+}
+
+.el-sub-menu ::v-deep(.el-sub-menu__title:hover .el-icon) {
+  color: black;
+}
+
 .el-menu ::v-deep(.el-menu-item:hover),
 .el-menu ::v-deep(.el-menu-item:focus),
 .el-menu ::v-deep(.el-menu-item:active) {
@@ -528,7 +598,7 @@ const goToAIExperience = outlineData => {
     #ffefb0,
     #ffcc00
   ); /* 设置悬停、聚焦、点击状态下的背景色 */
-  box-shadow: 0 8px 8px rgb(0, 0, 0, 0.3);
+  box-shadow: 0 4px 8px rgb(0, 0, 0, 0.2);
   color: black;
 }
 
@@ -536,7 +606,7 @@ const goToAIExperience = outlineData => {
   position: absolute;
   display: flex;
   // align-items: center;
-  margin-top: rpx(30);
+  margin-top: rpx(10);
   height: 100%;
   width: 100%;
 }
@@ -604,32 +674,7 @@ const goToAIExperience = outlineData => {
   align-items: center;
   gap: rpx(5); // 间距控制
 }
-.new-button-container {
-  display: flex;
-  align-items: center;
-  margin-left: rpx(5); 
-}
-.new-button-container .el-button {
-  width: rpx(60);
-  height: rpx(15);
-  background-color: #fee78a;
-  border: 1px white solid;
-  box-shadow: 0 4px 8px rgb(0, 0, 0, 0.2);
-  color: black;
-  border: none;
-  border-radius: rpx(12);
-  font-size: rpx(8);
-  transition: transform 0.3s ease, box-shadow 0.3s ease;
-}
-.new-button-container .el-button:hover {
-  transform: scale(1.05);
-  background: linear-gradient(
-    to bottom,
-    #fee78a,
-    #ffce1b
-  );
-  box-shadow: 0 6px 12px rgb(0, 0, 0, 0.3);
-}
+
 .box-icon {
   height: 100%;
   display: flex;

Dosya farkı çok büyük olduğundan ihmal edildi
+ 120 - 11
src/views/video-generation/DialogInterface.vue


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor