Quellcode durchsuchen

feat: 添加混合课程和游戏页面组件及路由配置

refactor(home): 重构首页菜单交互和物理课程组件

新增混合课程和游戏相关页面组件,包括:
1. 添加混合课程选择页面(mix/select)
2. 添加混合课程首页(mix/index)
3. 添加游戏首页(game/index)
4. 在pages.json中配置新增页面路由
5. 将物理课程内容抽离为独立组件
6. 重构首页菜单交互逻辑
whj vor 2 Wochen
Ursprung
Commit
cd9459d61e
6 geänderte Dateien mit 631 neuen und 123 gelöschten Zeilen
  1. 21 0
      pages.json
  2. 181 0
      pages/game/index.uvue
  3. 99 0
      pages/index/components/physics.uvue
  4. 10 123
      pages/index/home.uvue
  5. 180 0
      pages/mix/index.uvue
  6. 140 0
      pages/mix/select.uvue

+ 21 - 0
pages.json

@@ -75,6 +75,27 @@
 				"navigationStyle": "custom",
 				"disableScroll": true
 			}
+		},
+		{
+			"path": "pages/mix/index",
+			"style": {
+				"navigationStyle": "custom",
+				"disableScroll": true
+			}
+		},
+		{
+			"path": "pages/mix/select",
+			"style": {
+				"navigationStyle": "custom",
+				"disableScroll": true
+			}
+		},
+		{
+			"path": "pages/game/index",
+			"style": {
+				"navigationStyle": "custom",
+			"disableScroll": true
+			}
 		}
 	],
 	"globalStyle": {

+ 181 - 0
pages/game/index.uvue

@@ -0,0 +1,181 @@
+<script lang="ts" setup>
+import { ref, onMounted } from 'vue'
+import { fetchSubjectConfigInfo } from '@/services/subject/info'
+import type { SubjectCatalogResult } from '@/services/subject/catalog'
+import Progress from '../catalog/components/progress.uvue'
+import Back from '@/components/back.uvue'
+import Lock from '@/components/lock.uvue'
+import Loading from '@/components/loading.uvue'
+import { config } from '@/config'
+import { router } from "@/.cool";
+import { dict } from '@/.cool/store'
+const isLoading = ref(true)
+const visible = ref<boolean>(false)
+const dataList = ref<SubjectCatalogResult[]>([])
+const catalog = ref<SubjectCatalogResult>()
+async function getDataList() {
+  const id = dict.getValueByLabelMapByType('index_subject_id')['娱乐']
+  const res = await fetchSubjectConfigInfo({ id })
+  dataList.value = res.catalogList || []
+  catalog.value = res?.catalogList?.[0]
+}
+onMounted(async () => {
+  try {
+    await getDataList()
+    isLoading.value = false
+  } catch (err) {
+    console.log(err);
+    isLoading.value = false
+  }
+})
+function handleSelect(item: SubjectCatalogResult) {
+  catalog.value = item
+  visible.value = false
+}
+function handleDetail(item: SubjectCatalogResult) {
+  if (!item.payFlag && !item.trialPlay) {
+    uni.showToast({
+      title: '请先购买',
+      icon: 'none'
+    })
+    return
+  }
+  router.push({
+    path: "/pages/english/detail",
+    query: {
+      id: item.id,
+    }
+  });
+}
+</script>
+
+<template>
+  <Loading v-show="isLoading" />
+  <cl-page v-show="!isLoading">
+    <Back />
+    <img src="https://oss.xiaoxiongcode.com/static/语文/图层 4.png" alt="" class="w-full h-full object-cover" />
+    <!-- 精灵图动画 -->
+    <cl-image src="https://oss.xiaoxiongcode.com/static/home/3.gif" mode="heightFix"
+      class="!absolute bottom-0 left-0 !w-[44vh] !h-[55vh] z-[1]" />
+    <view>
+
+    </view>
+    <!-- 顶部右侧光标签 -->
+    <view class="light-tag" @tap="visible = true">
+      <image class="light-icon" v-if="catalog?.fileList?.[0]?.url" :src="config.baseUrl + catalog?.fileList?.[0]?.url">
+      </image>
+      <text class="light-text">{{ catalog?.name }}</text>
+      <cl-icon name="arrow-left-right-line" color="primary"></cl-icon>
+    </view>
+    <view class="boxs">
+      <scroll-view class="scroll-view_H" direction="horizontal" :show-scrollbar="false">
+        <view class="scroll-view-item_H bg-[white]" v-for="course in catalog?.courseList || []" :key="course.id"
+          @tap="handleDetail(course)">
+          <cl-image :src="config.baseUrl + course?.fileList?.[0]?.url" mode="heightFix"
+            class="!w-full !h-[26vh] mb-[2px] rounded-xl"></cl-image>
+          <text class="text-[16px] font-bold">{{
+            course.mainTitle }}</text>
+          <text class="text-[14px] text-[#666]">{{
+            course.assistantTitle }}</text>
+          <!-- <view>
+            <Progress :progress="30" />
+          </view> -->
+          <Lock v-if="!course.trialPlay && !course.payFlag" :record="course" />
+        </view>
+      </scroll-view>
+    </view>
+    <!-- <view class="footer">
+      <view>
+        <cl-image src="https://oss.xiaoxiongcode.com/static/home/4.png" mode="heightFix"
+          class=" !h-[40px] mb-[2px] rounded-xl"></cl-image>
+        <text class="text-[14px] text-white font-bold text-stroke-custom">虚拟实验</text>
+      </view>
+      <view>
+        <cl-image src="https://oss.xiaoxiongcode.com/static/home/5.png" mode="heightFix"
+          class=" !h-[40px] mb-[2px] rounded-xl"></cl-image>
+        <text class="text-[14px] text-white font-bold text-stroke-custom">我的收获</text>
+      </view>
+      <view>
+        <cl-image src="https://oss.xiaoxiongcode.com/static/home/6.png" mode="heightFix"
+          class=" !h-[40px] mb-[2px] rounded-xl"></cl-image>
+        <text class="text-[14px] text-white font-bold text-stroke-custom">学习报告</text>
+      </view>
+    </view> -->
+    <cl-popup v-model="visible" :show-header="false" direction="center" :size="600">
+      <view class="p-4">
+        <cl-row :gutter="0">
+          <cl-col :span="6" v-for="item in dataList || []" :key="item.id" :pt="{
+            className: '!p-2'
+          }" @tap="handleSelect(item)">
+            <view class="select-item" :class="{ selected: item.id === catalog?.id }">
+              <image :src="config.baseUrl + item?.fileList?.[0]?.url" class="w-[30rpx] h-[30rpx] mb-[2px]"></image>
+              <text>{{ item.name }}</text>
+            </view>
+          </cl-col>
+        </cl-row>
+      </view>
+    </cl-popup>
+  </cl-page>
+</template>
+
+
+
+<style lang="scss" scoped>
+.boxs {
+  @apply w-[100vw] h-[50vh] absolute top-1/2 left-[50vh] z-[1];
+  transform: translateY(-50%);
+}
+
+.scroll-view_H {
+  width: 100%;
+  height: 100%;
+  flex-direction: row;
+}
+
+.scroll-view-item_H {
+  @apply w-[40vh] h-[50vh] mr-[20px] rounded-2xl border-[5px] border-[#1D4BD9] border-solid border-b-[10px] p-1 flex items-center justify-between pb-[20px];
+}
+
+.light-tag {
+  @apply absolute top-3 left-1/2 z-[1] flex flex-row items-center bg-white px-3 py-2 font-bold rounded-full shadow-md;
+  transform: translateX(-50%);
+
+  .light-icon {
+    width: 20px;
+    height: 20px;
+    margin-right: 3px;
+  }
+
+  .light-text {
+    font-size: 16px;
+    min-width: 100px;
+    padding-right: 5px;
+  }
+}
+
+.select-item {
+  @apply flex items-center justify-center rounded-xl border-[3px] border-[#1D4BD9] border-solid border-b-[5px] px-4 py-2 font-bold;
+}
+
+.selected {
+  @apply border-green-500;
+}
+
+.footer {
+  @apply absolute bottom-2 right-5 z-[1] flex flex-row items-center justify-center gap-4;
+}
+
+.text-stroke-custom {
+  color: white;
+  text-shadow:
+    /* 左上角投影 */
+    -1px -1px 0 #1D4BD9,
+    /* 右上角投影 */
+    1px -1px 0 #1D4BD9,
+    /* 左下角投影 */
+    -1px 1px 0 #1D4BD9,
+    /* 右下角投影 */
+    1px 1px 0 #1D4BD9;
+
+}
+</style>

+ 99 - 0
pages/index/components/physics.uvue

@@ -0,0 +1,99 @@
+<script setup lang='ts'>
+import { ref } from 'vue'
+import { router } from '@/.cool'
+import { user } from '@/.cool'
+
+function handleView(url) {
+  router.push({ path: url })
+}
+</script>
+<template>
+  <view class="bottom">
+    <view class=" progress">
+      <view class="text-[26px] font-bold">学习进度</view>
+      <view class=" w-full flex flex-row items-center justify-center gap-2">
+
+        <cl-progress class="flex-1" color="linear-gradient(0deg, #1FA5F5 37%, #A2D8FF 100%)"
+          :value="user.info.value?.studyCourseNum" :show-text="false" :strokeWidth="16"
+          :pt="{ outer: { className: '!rounded-full' }, inner: { className: '!rounded-full' } }"></cl-progress>
+
+        <view class="text-[12px] w-[100px] rounded-full text-black font-bold text-center check
+               to-pink-500 h-[20px] ">
+          今日打卡
+        </view>
+
+      </view>
+    </view>
+    <view class="flex-1 flex flex-col items-center justify-between gap-2 bg1 py-3">
+      <cl-image src="https://oss.xiaoxiongcode.com/static/home/17.png" mode="widthFix" width="40%" height="auto" />
+      <text class="text-[14px]">趣味虚拟实验</text>
+    </view>
+    <view class="flex-1 flex flex-col items-center justify-between gap-1 bg2 py-3"
+      @tap="handleView('/pages/card/index')">
+      <cl-image src="https://oss.xiaoxiongcode.com/static/home/19.png" mode="widthFix" width="70%" height="auto" />
+      <text class="text-[14px]">我的收获</text>
+    </view>
+    <view class="flex-1 flex flex-col items-center justify-between gap-1 bg3 py-3">
+      <cl-image src="https://oss.xiaoxiongcode.com/static/home/18.png" mode="widthFix" width="35%" height="auto" />
+      <text class="text-[14px]">学习报告</text>
+    </view>
+  </view>
+  <view class="content" @tap="handleView('/pages/catalog/index')">
+    <cl-image src="https://oss.xiaoxiongcode.com/static/home/3.gif" mode="heightFix" height="100%" width="auto" />
+    <view class="flex-1 flex flex-col items-center justify-center gap-2 ft">
+      <view class="text-[10vh] font-bold">
+        启蒙物理AI课
+      </view>
+      <view class="h-[15vh]">
+        <cl-image src="https://oss.xiaoxiongcode.com/static/home/play.png" mode="heightFix" height="100%"
+          width="auto" />
+      </view>
+    </view>
+  </view>
+</template>
+<style lang="scss" scoped>
+.bottom {
+  @apply absolute bottom-[1vh] left-1/2 w-full max-w-[800px] rounded-[20px] px-10 py-1 flex flex-row items-center justify-between gap-5;
+  transform: translateX(-50%);
+
+  .progress {
+    @apply w-[400px] h-[80px] rounded-[40px] flex justify-center gap-2 px-[30px] gap-3;
+    background: linear-gradient(0deg, #AAE3FF 0%, #DFF4FD 100%);
+    width: 40%;
+  }
+
+  .check {
+    background: linear-gradient(0deg, #FBD00E 0%, #FBEC92 100%);
+    line-height: 20px;
+  }
+}
+
+.bg1 {
+  background: linear-gradient(0deg, #7597FA 0%, #C1DAFF 100%);
+  border-radius: 28px;
+  height: 80px;
+}
+
+.bg2 {
+  background: linear-gradient(0deg, #3CD3DE 0%, #ADFBFF 100%);
+  border-radius: 28px;
+  height: 80px;
+}
+
+.bg3 {
+  background: linear-gradient(0deg, #FFCE4A 0%, #FFEC88 100%);
+  border-radius: 28px;
+  height: 80px;
+}
+
+.ft {
+  font-family: eryazhaocaimao;
+  text-shadow: 0 0 10px rgba(255, 255, 255, 0.8), 0 0 20px rgba(255, 255, 255, 0.6), 0 0 30px rgba(255, 255, 255, 0.4), 0 0 40px rgba(62, 166, 238, 0.8);
+}
+
+.content {
+  @apply absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white w-[120vh] border-[3px] border-[#fff] border-solid rounded-[30px] px-10 py-4 h-[44vh] flex flex-row items-center justify-between gap-4;
+  background: linear-gradient(0deg, #C7F0FE 0%, #30B9FF 100%);
+
+}
+</style>

+ 10 - 123
pages/index/home.uvue

@@ -1,8 +1,9 @@
 <script lang="ts" setup>
-import { computed, onMounted } from 'vue'
+import { computed, onMounted, ref } from 'vue'
 import { dict } from '@/.cool/store'
 import { router } from '@/.cool'
 import { user } from '@/.cool'
+import Physics from './components/physics.uvue'
 
 const menuList = computed(() => {
 	return [
@@ -26,43 +27,9 @@ const icons = {
 	exchange: "https://oss.xiaoxiongcode.com/static/home/图层 5.png",
 	user: "https://oss.xiaoxiongcode.com/static/home/个人中心.png",
 }
+const selected = ref<string>('physics')
 function handlePage(val: any) {
-	let params: {
-		path: string,
-		query: {
-			[key: string]: any,
-		}
-	} = {
-		path: "",
-		query: {
-		}
-	}
-	switch (val.code) {
-		case 'physics':
-			params.path = "/pages/catalog/index"
-			break;
-		case 'chinese':
-			params.path = '/pages/chinese/index'
-			break;
-		case 'english':
-			params.path = '/pages/english/select'
-			break;
-		// case 'mix':
-		// 	url = '/pages/index/mix'
-		// 	break;
-		// case 'game':
-		// 	url = '/pages/index/game'
-		// 	break;
-		// case 'exchange':
-		// 	url = '/pages/index/exchange'
-		// 	break;
-		case 'user':
-			params.path = '/pages/user/info'
-			break;
-		default:
-			break;
-	}
-	router.push(params);
+	selected.value = val.code
 }
 onMounted(() => {
 	console.log(menuList.value)
@@ -78,103 +45,23 @@ const userInfo = computed(() => user.info.value?.userInfo)
 		<img src="https://oss.xiaoxiongcode.com/static/home/11.png" alt="" class="w-full h-full object-cover" />
 		<view class="menus ">
 			<view v-for="item in menuList" :key="item.code"
-				class="flex flex-col items-center justify-center gap-1 active:scale-[.9] transition-all duration-300"
-				@tap="handlePage(item)">
+				class="flex flex-col items-center p-1 px-4 justify-center gap-1 active:scale-[.9] transition-all duration-300"
+				@tap="handlePage(item)" :class="{ 'selected': item.code === selected }">
 				<cl-image :src="icons[item.code]" mode="aspectFill" width="40" height="40"></cl-image>
 				<text class="text-[12px]">{{ item.label }}</text>
 			</view>
 		</view>
-		<view class="bottom">
-			<view class=" progress">
-				<view class="text-[26px] font-bold">学习进度</view>
-				<view class=" w-full flex flex-row items-center justify-center gap-2">
 
-					<cl-progress class="flex-1" color="linear-gradient(0deg, #1FA5F5 37%, #A2D8FF 100%)"
-						:value="user.info.value?.studyCourseNum" :show-text="false" :strokeWidth="16"
-						:pt="{ outer: { className: '!rounded-full' }, inner: { className: '!rounded-full' } }"></cl-progress>
-
-					<view class="text-[12px] w-[100px] rounded-full text-black font-bold text-center check
-               to-pink-500 h-[20px] ">
-						今日打卡
-					</view>
-
-				</view>
-			</view>
-			<view class="flex-1 flex flex-col items-center justify-between gap-2 bg1 py-3">
-				<cl-image src="https://oss.xiaoxiongcode.com/static/home/17.png" mode="widthFix" width="40%" height="auto" />
-				<text class="text-[14px]">趣味虚拟实验</text>
-			</view>
-			<view class="flex-1 flex flex-col items-center justify-between gap-1 bg2 py-3"
-				@tap="handleView('/pages/card/index')">
-				<cl-image src="https://oss.xiaoxiongcode.com/static/home/19.png" mode="widthFix" width="70%" height="auto" />
-				<text class="text-[14px]">我的收获</text>
-			</view>
-			<view class="flex-1 flex flex-col items-center justify-between gap-1 bg3 py-3">
-				<cl-image src="https://oss.xiaoxiongcode.com/static/home/18.png" mode="widthFix" width="35%" height="auto" />
-				<text class="text-[14px]">学习报告</text>
-			</view>
-		</view>
-		<view class="content">
-			<cl-image src="https://oss.xiaoxiongcode.com/static/home/nh.png" mode="heightFix" height="100%" width="auto" />
-			<view class="flex-1 flex flex-col items-center justify-center gap-2 ft">
-				<view class="text-[10vh] font-bold">
-					推荐课程
-				</view>
-				<view class="text-[8vh]">
-					启蒙物理AI课
-				</view>
-			</view>
-		</view>
+		<Physics />
 	</cl-page>
 </template>
 <style lang="scss" scoped>
-.content {
-	@apply absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white w-[120vh] border-[3px] border-[#fff] border-solid rounded-[30px] px-10 py-4 h-[44vh] flex flex-row items-center justify-between gap-4;
-	background: linear-gradient(0deg, #C7F0FE 0%, #30B9FF 100%);
-
-}
-
 .menus {
-	@apply absolute top-[5vh] left-1/2 bg-white rounded-[20px] px-10 py-1 flex flex-row items-center justify-between gap-10;
+	@apply absolute top-[5vh] left-1/2 bg-white rounded-[20px] px-10 py-2 flex flex-row items-center justify-between gap-2;
 	transform: translateX(-50%);
 }
 
-.bottom {
-	@apply absolute bottom-[1vh] left-1/2 w-full max-w-[800px] rounded-[20px] px-10 py-1 flex flex-row items-center justify-between gap-5;
-	transform: translateX(-50%);
-
-	.progress {
-		@apply w-[400px] h-[80px] rounded-[40px] flex justify-center gap-2 px-[30px] gap-3;
-		background: linear-gradient(0deg, #AAE3FF 0%, #DFF4FD 100%);
-		width: 40%;
-	}
-
-	.check {
-		background: linear-gradient(0deg, #FBD00E 0%, #FBEC92 100%);
-		line-height: 20px;
-	}
-}
-
-.bg1 {
-	background: linear-gradient(0deg, #7597FA 0%, #C1DAFF 100%);
-	border-radius: 28px;
-	height: 80px;
-}
-
-.bg2 {
-	background: linear-gradient(0deg, #3CD3DE 0%, #ADFBFF 100%);
-	border-radius: 28px;
-	height: 80px;
-}
-
-.bg3 {
-	background: linear-gradient(0deg, #FFCE4A 0%, #FFEC88 100%);
-	border-radius: 28px;
-	height: 80px;
-}
-
-.ft {
-	font-family: eryazhaocaimao;
-	text-shadow: 0 0 10px rgba(255, 255, 255, 0.8), 0 0 20px rgba(255, 255, 255, 0.6), 0 0 30px rgba(255, 255, 255, 0.4), 0 0 40px rgba(62, 166, 238, 0.8);
+.selected {
+	@apply scale-[1.1] bg-[#f0f0f0] rounded-xl;
 }
 </style>

+ 180 - 0
pages/mix/index.uvue

@@ -0,0 +1,180 @@
+<script lang="ts" setup>
+import { ref, onMounted } from 'vue'
+import { fetchSubjectConfigInfo } from '@/services/subject/info'
+import type { SubjectCatalogResult } from '@/services/subject/catalog'
+import Progress from '../catalog/components/progress.uvue'
+import Back from '@/components/back.uvue'
+import Lock from '@/components/lock.uvue'
+import Loading from '@/components/loading.uvue'
+import { config } from '@/config'
+import { router } from "@/.cool";
+const isLoading = ref(true)
+const visible = ref<boolean>(false)
+const dataList = ref<SubjectCatalogResult[]>([])
+const catalog = ref<SubjectCatalogResult>()
+async function getDataList() {
+  const res = await fetchSubjectConfigInfo({ id: router.query().id })
+  dataList.value = res.catalogList || []
+  catalog.value = res?.catalogList?.[0]
+}
+onMounted(async () => {
+  try {
+    await getDataList()
+    isLoading.value = false
+  } catch (err) {
+    console.log(err);
+    isLoading.value = false
+  }
+})
+function handleSelect(item: SubjectCatalogResult) {
+  catalog.value = item
+  visible.value = false
+}
+function handleDetail(item: SubjectCatalogResult) {
+  if (!item.payFlag && !item.trialPlay) {
+    uni.showToast({
+      title: '请先购买',
+      icon: 'none'
+    })
+    return
+  }
+  router.push({
+    path: "/pages/english/detail",
+    query: {
+      id: item.id,
+    }
+  });
+}
+</script>
+
+<template>
+  <Loading v-show="isLoading" />
+  <cl-page v-show="!isLoading">
+    <Back />
+    <img src="https://oss.xiaoxiongcode.com/static/英语/图层 6.png" alt="" class="w-full h-full object-cover" />
+
+    <!-- 精灵图动画 -->
+    <cl-image src="https://oss.xiaoxiongcode.com/static/home/3.gif" mode="heightFix"
+      class="!absolute bottom-0 left-0 !w-[44vh] !h-[55vh] z-[1]" />
+    <view>
+
+    </view>
+    <!-- 顶部右侧光标签 -->
+    <view class="light-tag" @tap="visible = true">
+      <image class="light-icon" v-if="catalog?.fileList?.[0]?.url" :src="config.baseUrl + catalog?.fileList?.[0]?.url">
+      </image>
+      <text class="light-text">{{ catalog?.name }}</text>
+      <cl-icon name="arrow-left-right-line" color="primary"></cl-icon>
+    </view>
+    <view class="boxs">
+      <scroll-view class="scroll-view_H" direction="horizontal" :show-scrollbar="false">
+        <view class="scroll-view-item_H bg-[white]" v-for="course in catalog?.courseList || []" :key="course.id"
+          @tap="handleDetail(course)">
+          <cl-image :src="config.baseUrl + course?.fileList?.[0]?.url" mode="heightFix"
+            class="!w-full !h-[26vh] mb-[2px] rounded-xl"></cl-image>
+          <text class="text-[16px] font-bold">{{
+            course.mainTitle }}</text>
+          <text class="text-[14px] text-[#666]">{{
+            course.assistantTitle }}</text>
+          <!-- <view>
+            <Progress :progress="30" />
+          </view> -->
+          <Lock v-if="!course.trialPlay && !course.payFlag" :record="course" />
+        </view>
+      </scroll-view>
+    </view>
+    <!-- <view class="footer">
+      <view>
+        <cl-image src="https://oss.xiaoxiongcode.com/static/home/4.png" mode="heightFix"
+          class=" !h-[40px] mb-[2px] rounded-xl"></cl-image>
+        <text class="text-[14px] text-white font-bold text-stroke-custom">虚拟实验</text>
+      </view>
+      <view>
+        <cl-image src="https://oss.xiaoxiongcode.com/static/home/5.png" mode="heightFix"
+          class=" !h-[40px] mb-[2px] rounded-xl"></cl-image>
+        <text class="text-[14px] text-white font-bold text-stroke-custom">我的收获</text>
+      </view>
+      <view>
+        <cl-image src="https://oss.xiaoxiongcode.com/static/home/6.png" mode="heightFix"
+          class=" !h-[40px] mb-[2px] rounded-xl"></cl-image>
+        <text class="text-[14px] text-white font-bold text-stroke-custom">学习报告</text>
+      </view>
+    </view> -->
+    <cl-popup v-model="visible" :show-header="false" direction="center" :size="600">
+      <view class="p-4">
+        <cl-row :gutter="0">
+          <cl-col :span="6" v-for="item in dataList || []" :key="item.id" :pt="{
+            className: '!p-2'
+          }" @tap="handleSelect(item)">
+            <view class="select-item" :class="{ selected: item.id === catalog?.id }">
+              <image :src="config.baseUrl + item?.fileList?.[0]?.url" class="w-[30rpx] h-[30rpx] mb-[2px]"></image>
+              <text>{{ item.name }}</text>
+            </view>
+          </cl-col>
+        </cl-row>
+      </view>
+    </cl-popup>
+  </cl-page>
+</template>
+
+
+
+<style lang="scss" scoped>
+.boxs {
+  @apply w-[100vw] h-[50vh] absolute top-1/2 left-[50vh] z-[1];
+  transform: translateY(-50%);
+}
+
+.scroll-view_H {
+  width: 100%;
+  height: 100%;
+  flex-direction: row;
+}
+
+.scroll-view-item_H {
+  @apply w-[40vh] h-[50vh] mr-[20px] rounded-2xl border-[5px] border-[#1D4BD9] border-solid border-b-[10px] p-1 flex items-center justify-between pb-[20px];
+}
+
+.light-tag {
+  @apply absolute top-3 left-1/2 z-[1] flex flex-row items-center bg-white px-3 py-2 font-bold rounded-full shadow-md;
+  transform: translateX(-50%);
+
+  .light-icon {
+    width: 20px;
+    height: 20px;
+    margin-right: 3px;
+  }
+
+  .light-text {
+    font-size: 16px;
+    min-width: 100px;
+    padding-right: 5px;
+  }
+}
+
+.select-item {
+  @apply flex items-center justify-center rounded-xl border-[3px] border-[#1D4BD9] border-solid border-b-[5px] px-4 py-2 font-bold;
+}
+
+.selected {
+  @apply border-green-500;
+}
+
+.footer {
+  @apply absolute bottom-2 right-5 z-[1] flex flex-row items-center justify-center gap-4;
+}
+
+.text-stroke-custom {
+  color: white;
+  text-shadow:
+    /* 左上角投影 */
+    -1px -1px 0 #1D4BD9,
+    /* 右上角投影 */
+    1px -1px 0 #1D4BD9,
+    /* 左下角投影 */
+    -1px 1px 0 #1D4BD9,
+    /* 右下角投影 */
+    1px 1px 0 #1D4BD9;
+
+}
+</style>

+ 140 - 0
pages/mix/select.uvue

@@ -0,0 +1,140 @@
+<script lang="ts" setup>
+import { ref, onMounted } from 'vue'
+import { querySubjectInfo } from '@/services/subject/info'
+import type { SubjectInfoResult } from '@/services/subject/info'
+import Back from '@/components/back.uvue'
+import Loading from '@/components/loading.uvue'
+import { config } from '@/config'
+import { router } from "@/.cool";
+const isLoading = ref(true)
+const visible = ref<boolean>(false)
+const dataList = ref<SubjectInfoResult[]>([])
+async function getDataList() {
+  const res = await querySubjectInfo({
+    delFlag: false,
+    subjectType: 'mix'
+  })
+  dataList.value = res
+}
+onMounted(async () => {
+  try {
+    await getDataList()
+    isLoading.value = false
+  } catch (err) {
+    console.log(err);
+    isLoading.value = false
+  }
+})
+function handleDetail(item: SubjectCatalogResult) {
+  router.push({
+    path: "/pages/english/index",
+    query: {
+      id: item.id,
+    }
+  });
+}
+</script>
+
+<template>
+  <Loading v-show="isLoading" />
+  <cl-page v-show="!isLoading">
+    <Back />
+    <img src="https://oss.xiaoxiongcode.com/static/英语/图层 6.png" alt="" class="w-full h-full object-cover" />
+    <!-- 精灵图动画 -->
+    <!-- <cl-image src="https://oss.xiaoxiongcode.com/static/home/3.gif" mode="heightFix"
+      class="!absolute bottom-0 left-0 !w-[44vh] !h-[55vh] z-[1]" /> -->
+    <!-- <view class="flex flex-row items-center justify-center gap-4 kk">
+      <view class="text-[20px] font-bold bg-[#00C6F1] text-white px-4 py-4 rounded-xl">
+        课程导航
+      </view>
+      <view class="jj"></view>
+    </view> -->
+    <view class="boxs">
+      <scroll-view class="scroll-view_H" direction="horizontal" :show-scrollbar="false">
+        <view class="scroll-view-item_H bg-[white]" v-for="course in dataList || []" :key="course.id"
+          @tap="handleDetail(course)">
+          <cl-image :src="config.baseUrl + course?.iconPath" mode="heightFix"
+            class="!w-full !h-[26vh] mb-[2px] rounded-xl"></cl-image>
+          <text class="text-[16px] font-bold">{{
+            course.mainTitle }}</text>
+          <text class="text-[14px] text-[#666]">{{
+            course.assistantTitle }}</text>
+        </view>
+      </scroll-view>
+    </view>
+  </cl-page>
+</template>
+
+
+
+<style lang="scss" scoped>
+.boxs {
+  @apply h-[50vh] absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-[1];
+}
+
+.kk {
+  @apply w-[50vh] h-[50vh] absolute top-1/2 left-0 z-[1];
+  transform: translateY(-50%);
+
+}
+
+.jj {
+  border: 20px solid #00C6F1;
+
+  border-top: 15px solid #00000000;
+  border-right: 15px solid #00000000;
+  border-bottom: 15px solid #00000000;
+}
+
+.scroll-view_H {
+  width: 100%;
+  height: 100%;
+  flex-direction: row;
+}
+
+.scroll-view-item_H {
+  @apply w-[40vh] h-[50vh] mr-[20px] rounded-2xl border-[5px] border-[#1D4BD9] border-solid border-b-[10px] p-1 flex items-center justify-between pb-[20px];
+}
+
+.light-tag {
+  @apply absolute top-3 left-1/2 z-[1] flex flex-row items-center bg-white px-3 py-2 font-bold rounded-full shadow-md;
+  transform: translateX(-50%);
+
+  .light-icon {
+    width: 20px;
+    height: 20px;
+    margin-right: 3px;
+  }
+
+  .light-text {
+    font-size: 16px;
+    width: 100px;
+  }
+}
+
+.select-item {
+  @apply flex items-center justify-center rounded-xl border-[3px] border-[#1D4BD9] border-solid border-b-[5px] px-4 py-2 font-bold;
+}
+
+.selected {
+  @apply border-green-500;
+}
+
+.footer {
+  @apply absolute bottom-2 right-5 z-[1] flex flex-row items-center justify-center gap-4;
+}
+
+.text-stroke-custom {
+  color: white;
+  text-shadow:
+    /* 左上角投影 */
+    -1px -1px 0 #1D4BD9,
+    /* 右上角投影 */
+    1px -1px 0 #1D4BD9,
+    /* 左下角投影 */
+    -1px 1px 0 #1D4BD9,
+    /* 右下角投影 */
+    1px 1px 0 #1D4BD9;
+
+}
+</style>