Explorar o código

1、新增blockly权限配置
2、对blockly课程根据权限、闯关进度实时替换禁用、奖杯状态

liyanbo hai 4 meses
pai
achega
a311d53b7a

BIN=BIN
src/assets/programming/lock.png


BIN=BIN
src/assets/programming/trophy.png


BIN=BIN
src/assets/programming/unlock.png


+ 3 - 0
src/components/HomePage.vue

@@ -142,6 +142,8 @@ const LogoutClick = async () => {
     localStorage.removeItem('isLoggedIn')
     localStorage.removeItem('maxCourseSections')
     localStorage.removeItem('courseDataScope')
+    localStorage.removeItem('blocklyDataScope')
+
     // 跳转到登录页面
     router.push({ path: '/login' })
   } catch (error) {
@@ -151,6 +153,7 @@ const LogoutClick = async () => {
     localStorage.removeItem('isLoggedIn')
     localStorage.removeItem('maxCourseSections')
     localStorage.removeItem('courseDataScope')
+    localStorage.removeItem('blocklyDataScope')
     Message().notifyError('退出登录失败,请重试', true)
     router.push({ path: '/login' })
   }

+ 1 - 0
src/views/Login.vue

@@ -279,6 +279,7 @@ const handleLogin = async params => {
           localStorage.setItem('token', res.data.accessToken)
           //课程权限
           localStorage.setItem('courseDataScope', res.data.courseDataScope)
+          localStorage.setItem('blocklyDataScope', res.data.blocklyDataScope)
 
           if (loginData.value.loginForm.rememberMe) {
             localStorage.setItem('userName', loginData.value.loginForm.username)

+ 1 - 0
src/views/QuickLogin.vue

@@ -75,6 +75,7 @@ const autoLogin = async () => {
       localStorage.setItem('rememberMe', 'true')
       //课程权限
       localStorage.setItem('courseDataScope', res.data.courseDataScope)
+      localStorage.setItem('blocklyDataScope', res.data.blocklyDataScope)
 
       ElMessage.success('信息校验成功')
       // 跳转到课程界面

+ 62 - 10
src/views/programming/ProgrammingList.vue

@@ -29,13 +29,15 @@
           @mouseup="handleMouseUp"
           @mouseleave="handleMouseLeave"
         >
-          <div 
-            v-for="(courseType, index) in specificCourses" 
-            :key="index" 
-            class="middle-inner-box"
-            @click="goToProgrammingList(courseType, index)"
+          <div
+              v-for="(courseType, index) in specificCourses"
+              :key="index"
+              class="middle-inner-box"
+              @click="goToProgrammingList(courseType, index)"
           >
-            <div class="new-white-box" :class="{ 'active': activeButton === index }" @click="goToProgrammingList(courseType, index)">
+            <div class="new-white-box"
+                 :class="{ 'active': activeButton === index, 'disabled': courseType.isDisabled }"
+                 @click="goToProgrammingList(courseType, index)">
               <div class="bg-image-container" :style="{ backgroundImage: `url(${courseType.bgImage})` }"></div>
               <div class="text-container">
                 <div class="box-title">
@@ -43,7 +45,7 @@
                 </div>
               </div>
               <!-- unlock背景图盒子 -->
-              <div class="unlock-box" :style="{ backgroundImage: `url(${unlockImage})` }"></div>
+              <div class="unlock-box" :style="{ backgroundImage: courseType.isDisabled ? `url(${lockImage})` : courseType.progress > 0 ? `url(${trophyImage})` : `url(${unlockImage})` }"></div>
             </div>
           </div>
         </div>
@@ -74,7 +76,10 @@ import { useRouter, useRoute } from 'vue-router';
 // 导入主题列表接口
 import { TopicList } from '@/api/programming/index.js'
 // 导入图片
+import lockImage from '@/assets/programming/lock.png'
 import unlockImage from '@/assets/programming/unlock.png'
+import trophyImage from '@/assets/programming/trophy.png'
+import {Message} from "@/utils/message/Message.js";
 
 // 获取路由实例
 const router = useRouter()
@@ -85,6 +90,11 @@ const pageTitle = ref('')
 // 课程类别ID
 const categoryId = ref('')
 
+// 课程权限
+const blocklyDataScope = ref([])
+// 测试账号禁用视频
+const isDisabled = ref(false)
+
 // 返回上一页
 const goBackIndex = () => {
   router.push('/programming')
@@ -106,10 +116,13 @@ const fetchTopicList = () => {
         // 清空原有数据
         specificCourses.splice(0, specificCourses.length);
         res.data.forEach(item => {
+
           specificCourses.push({
             id: item.id,
             title: item.ctType,
-            bgImage: item.ctTypeImage
+            bgImage: item.ctTypeImage,
+            progress: item.progress,
+            isDisabled: disableBlockly(item.id)
           });
         });
         // 更新圆形按钮数据
@@ -185,6 +198,11 @@ const middleBox = ref(null)
 
 // 组件挂载时获取路由参数设置标题和课程ID
 onMounted(() => {
+
+  if (localStorage.getItem("blocklyDataScope")) {
+    blocklyDataScope.value = localStorage.getItem("blocklyDataScope").split(",");
+  }
+  
   const title = route.query.courseTitle
   if (title) {
     pageTitle.value = title
@@ -201,6 +219,12 @@ onMounted(() => {
 
 // 跳转到课程详情页面
 const goToProgrammingList = (courseType, index) => {
+  // 检查是否禁用
+  if (courseType.isDisabled) {
+    Message().notifyWarning('您的账号并未开放此课程!', true)
+    return
+  }
+
   // 设置当前选中项
   activeButton.value = index;
   // 跳转ProgrammingCourset页面,并传递课程信息作为参数
@@ -216,6 +240,24 @@ const goToProgrammingList = (courseType, index) => {
   })
 }
 
+// 禁用视频
+const disableBlockly = (blocklyId = categoryId.value) => {
+
+  // 未配置课程权限,不禁用视频
+  if (!blocklyDataScope.value || blocklyDataScope.value.length === 0) {
+    return false
+  }
+
+  //配置了课程权限,且视频id不在权限列表中
+  isDisabled.value = !blocklyDataScope.value.some(item => Number(item) === blocklyId)
+  // if (isDisabled.value) {
+  //   Message().notifyWarning('您的账号并未开放此课程!', true)
+  //   return isDisabled.value;
+  // }
+
+  return isDisabled.value;
+}
+
 </script>
 
 <style scoped lang="scss">
@@ -365,14 +407,24 @@ const goToProgrammingList = (courseType, index) => {
 }
 
 /* 鼠标悬浮/选中时的放大效果 */
-.new-white-box:hover,
-.new-white-box.active {
+.new-white-box:hover:not(.disabled),
+.new-white-box.active:not(.disabled) {
   transform: scale(1.1); /* 放大1.1倍 */
   z-index: 10; /* 确保放大时在顶层显示 */
   border: rpx(5) solid #D0D7F7; /* 边框效果 */
   box-shadow: 0 0 rpx(10) rgba(0, 0, 0, 0.5);
 }
+/* 禁用状态样式 */
+.new-white-box.disabled {
+  cursor: not-allowed;
+  filter: grayscale(80%);
+  pointer-events: none;
+}
 
+/* 禁用状态下的文字颜色 */
+.new-white-box.disabled .box-title {
+  color: #999;
+}
 
 
 /* 背景图容器 */