소스 검색

```
feat(learning-system): 添加学习系统详情页课程描述和目录功能

- 新增课程描述、课程目录、评论、学习笔记等国际化文案
- 实现课程价格动态显示,替换硬编码价格
- 添加CourseDescription、CourseDirectory、Pinglun、Xuxibiji组件
- 重构详情页标签页结构,支持课程介绍、目录、评论、学习笔记切换
- 调整样式文件,添加gap20类和课程目录相关样式
- 设置默认激活标签为学习笔记
```

zhangningning 1 개월 전
부모
커밋
a3a7b39839

BIN
src/assets/imgs/mulu.png


+ 5 - 0
src/locales/en.js

@@ -18,6 +18,11 @@ export default {
     lijixuexi: 'Learn Now',
     renkanguo: 'People Have Seen',
     qitakechengtuijian: 'Other Course Recommendations',
+    kechengjieshao: 'Course Description',
+    kechengmulu: 'Course Directory',
+    pinglun: 'Comments',
+    xuxibiji: 'Learning Notes',
+    add: 'Add',
   },
   login: {
     smsLogin: 'SMS Login',

+ 5 - 0
src/locales/zh-CN.js

@@ -19,6 +19,11 @@ export default {
     lijixuexi: '立即学习',
     renkanguo: '人看过',
     qitakechengtuijian: '其他课程推荐',
+    kechengjieshao: '课程介绍',
+    kechengmulu: '课程目录',
+    pinglun: '评论',
+    xuxibiji: '学习笔记',
+    add: '添加',
   },
   login: {
     smsLogin: '短信登录',

+ 16 - 6
src/pages/LearningSystem/LearningSystemDetail.vue

@@ -28,7 +28,7 @@
       <div class="border_radius_16 gradient mt10 pt10">
         <div class="border_radius_16 bg_color_fff flex-center-between" style="padding:0 16px">
           <div class="color_price">
-            <span class="bold font_size36">3999</span>
+            <span class="bold font_size36">{{info.coursePrice}}</span>
             <span class="font_size18">{{$t('common.mibi')}}</span>
           </div>
           <div class="flex-center-between">
@@ -43,11 +43,17 @@
       <div class="flex-between mt20">
         <div class="flex_1 bg_color_fff padding16 border_radius_16 box_shadow_card mr20">
           <el-tabs v-model="activeName" class="demo-tabs">
-            <el-tab-pane label="User" name="first">
-
+            <el-tab-pane :label="$t('common.kechengjieshao')" name="first">
+              <CourseDescription :info="info" />
             </el-tab-pane>
-            <el-tab-pane label="Task" name="fourth">
-
+            <el-tab-pane :label="$t('common.kechengmulu')" name="kechengmulu">
+              <CourseDirectory :info="info" />
+            </el-tab-pane>
+            <el-tab-pane :label="$t('common.pinglun')" name="pinglun">
+              <pinglun :info="info" />
+            </el-tab-pane>
+            <el-tab-pane :label="$t('common.xuxibiji')" name="xuxibiji">
+              <Xuxibiji :info="info" />
             </el-tab-pane>
           </el-tabs>
         </div>
@@ -63,6 +69,10 @@
   import playIcon from '@/assets/imgs/bofang.png'
   import zuIcon from '@/assets/imgs/zu.png'
   import Right from './components/right.vue'
+  import CourseDescription from './components/CourseDescription.vue'
+  import CourseDirectory from './components/CourseDirectory.vue'
+  import Pinglun from './components/pinglun.vue'
+  import Xuxibiji from './components/xuxibiji.vue'
 
   // 引入api
   import { getCourseDetail } from '@/api/course.js'
@@ -75,7 +85,7 @@
   import { useAppStore } from '@/pinia/appStore'
   const appStore = useAppStore()
 
-  const activeName = ref('first');
+  const activeName = ref('xuxibiji');
 
  
 

+ 22 - 0
src/pages/LearningSystem/components/CourseDescription.vue

@@ -0,0 +1,22 @@
+<template>
+  <div>
+    <div v-html="info.courseIntro"></div>
+    <img :src="info.coverImageUrl" alt="" style="width: 100%; height: auto;" class="border_radius_8 mt10">
+  </div>
+</template>
+<script setup>
+import { getCourseList } from '@/api/course.js'
+import { ref, onMounted } from 'vue'
+defineProps({
+  info: {
+    type: Object,
+    default: () => ({})
+  }
+})
+
+const list = ref([]);
+
+</script>
+<style scoped>
+
+</style>

+ 46 - 0
src/pages/LearningSystem/components/CourseDirectory.vue

@@ -0,0 +1,46 @@
+<template>
+  <div class="kechengmulu">
+    <div class="font_size18 bold">{{$t('common.kechengmulu')}}</div>
+    <div class="flex-center-between font_size16 gray list_item" 
+    :class="{'active': index === 0}"
+    v-for="(item, index) in 4" :key="index">
+      <div class="gap10">
+        <div>第一节</div>
+        <div class="gap5">
+          <img :src="muluIcon" alt="" style="width:20px;height:20px" v-if="index === 0">
+          <span>行业要求与职业发展路线</span>
+        </div>
+      </div>
+      <div>20:23</div>
+    </div>
+  </div>
+</template>
+<script setup>
+import muluIcon from '@/assets/imgs/mulu.png'
+import { getCourseList } from '@/api/course.js'
+import { ref, onMounted } from 'vue'
+defineProps({
+  info: {
+    type: Object,
+    default: () => ({})
+  }
+})
+
+const list = ref([]);
+
+</script>
+<style scoped lang="scss">
+  .kechengmulu{
+    .list_item{
+      cursor: pointer;
+      padding: 15px 0;
+      border-bottom: 1px solid #DCDFE6;
+      &.active{
+        color: $primary-color;
+        font-weight: 600;
+      }
+    }
+
+  }
+
+</style>

+ 80 - 0
src/pages/LearningSystem/components/pinglun.vue

@@ -0,0 +1,80 @@
+<template>
+  <div class="pinglun">
+    <div class="font_size18 bold">{{$t('common.pinglun')}} (20)</div>
+    <div class="gap20 mt10">
+      <el-avatar :size="32" :src="appStore.avatarDefault" />
+      <div class="page-add flex_1">
+        <el-input v-model="comments" placeholder="请输入"  maxlength="500" style="width: 100%;"/>
+      </div>
+    </div>
+    <div class="flex-between font_size16 list_item" 
+    v-for="(item, index) in 4" :key="index">
+        <el-avatar :size="32" :src="appStore.avatarDefault" />
+      <div class="ml20 flex_1">
+        <div class="bold font_size14">这是名字</div>
+        <div class="gray mt5 line_height22">
+          这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容这是视频简介内容
+        </div>
+      </div>
+    </div>
+    <Pagination 
+      :total="listTotal"
+      :page-size="searchFom.pageSize"
+      :current-page="searchFom.pageNum"
+      @page-change="handlePageChange"
+    />
+  </div>
+</template>
+<script setup>
+import Pagination from '@/components/Pagination.vue'
+import { getCourseList } from '@/api/course.js'
+import { ref, onMounted,reactive } from 'vue'
+import { useAppStore } from '@/pinia/appStore'
+const appStore = useAppStore()
+defineProps({
+  info: {
+    type: Object,
+    default: () => ({})
+  }
+})
+const comments = ref('');
+const listTotal = ref(0);
+const searchFom = reactive({
+  pageNum: 1,
+  pageSize: 10,
+})
+const list = ref([]);
+
+onMounted(() => {
+  getList();
+});
+
+const handlePageChange = (page) => {
+  searchFom.pageNum = page
+  // 这里可以添加获取数据的逻辑
+  console.log('当前页:', page);
+  getList();
+}
+// 查询寻找工作流列表
+const getList = async (type) => {
+  if(type === 'init'){
+    searchFom.pageNum = 1
+  }
+  // const res = await getQuestList(searchFom)
+  // if(res.code === 200){
+  //   listTotal.value = res.total
+  //   list.value = res.rows
+  // }
+};
+
+</script>
+<style scoped lang="scss">
+  .pinglun{
+    .list_item{
+      cursor: pointer;
+      padding: 15px 0;
+    }
+
+  }
+
+</style>

+ 92 - 0
src/pages/LearningSystem/components/xuxibiji.vue

@@ -0,0 +1,92 @@
+<template>
+  <div class="xuxibiji">
+    <div class="font_size18 bold">{{$t('common.xuxibiji')}}</div>
+    <div class="addBtn flex-center gradient border_radius_16">
+      <div class="gap10">
+        <img :src="addIcon" alt="" style="width:30px;height:30px">
+        <span class="font_size18">{{$t('common.add')}}{{$t('common.xuxibiji')}}</span>
+      </div>
+    </div>
+    <div class="list_item padding16 border_radius_16 mt16 flex-center-between" 
+    v-for="(item, index) in 4" :key="index">
+      <div class="flex_1">
+        <div class="bold font_size18">这是笔记名称</div>
+        <div class="gray999 mt5">更新于 2025-11-08 03:26</div>
+      </div>
+      <div>
+        <el-button type="primary" plain size="large">
+          <el-icon><EditPen /></el-icon>
+          <span class="ml10">编辑</span>
+        </el-button>
+        <el-button type="danger" plain size="large">
+          <el-icon><Delete /></el-icon>
+          <span class="ml10">删除</span>
+        </el-button>
+      </div>
+    </div>
+    <Pagination 
+      :total="listTotal"
+      :page-size="searchFom.pageSize"
+      :current-page="searchFom.pageNum"
+      @page-change="handlePageChange"
+    />
+  </div>
+</template>
+<script setup>
+import addIcon from '@/assets/imgs/add.png'
+import Pagination from '@/components/Pagination.vue'
+import { getCourseList } from '@/api/course.js'
+import { ref, onMounted,reactive } from 'vue'
+import { useAppStore } from '@/pinia/appStore'
+const appStore = useAppStore()
+defineProps({
+  info: {
+    type: Object,
+    default: () => ({})
+  }
+})
+const comments = ref('');
+const listTotal = ref(0);
+const searchFom = reactive({
+  pageNum: 1,
+  pageSize: 10,
+})
+const list = ref([]);
+
+onMounted(() => {
+  getList();
+});
+
+const handlePageChange = (page) => {
+  searchFom.pageNum = page
+  // 这里可以添加获取数据的逻辑
+  console.log('当前页:', page);
+  getList();
+}
+// 查询寻找工作流列表
+const getList = async (type) => {
+  if(type === 'init'){
+    searchFom.pageNum = 1
+  }
+  // const res = await getQuestList(searchFom)
+  // if(res.code === 200){
+  //   listTotal.value = res.total
+  //   list.value = res.rows
+  // }
+};
+
+</script>
+<style scoped lang="scss">
+  .xuxibiji{
+    .list_item{
+      background: #F5F7FA;
+    }
+    .addBtn{
+      margin-top: 20px;
+      padding: 10px 20px;
+      color: #fff;
+    }
+
+  }
+
+</style>

+ 15 - 0
src/styles/index.scss

@@ -54,6 +54,7 @@ body{
 
 .detail_right{
 	width: 410px;
+	height: fit-content;
 }
 .detail_right_content{
 	position: fixed;
@@ -345,6 +346,9 @@ wx-image{
 .gap10{
   gap: 10px;
 }
+.gap20{
+  gap: 20px;
+}
 //首行缩进2em
 .indent_28{
   text-indent: 28px;
@@ -694,4 +698,15 @@ wx-image{
 	.el-textarea__inner{
 		background: #F5F7FA !important;
 	}
+}
+
+//课程目录
+.demo-tabs{
+	.el-tabs__item{
+		font-size: 18px;
+		&.is-active{
+			color: $primary-color;
+			font-weight: 600;
+		}
+	}
 }