Selaa lähdekoodia

1、调整获取web角色路由权限逻辑
2、调整用户信息、获取结构
3、禁用主租户注册

liyanbo 2 kuukautta sitten
vanhempi
sitoutus
5d7a7bbfba

+ 4 - 3
package-lock.json

@@ -17,6 +17,7 @@
         "@vue-office/pptx": "^1.0.1",
         "axios": "^1.10.0",
         "crypto-js": "^4.2.0",
+        "dayjs": "^1.11.19",
         "element-plus": "^2.10.2",
         "highlight.js": "^11.11.1",
         "hls.js": "^1.6.7",
@@ -4074,9 +4075,9 @@
       }
     },
     "node_modules/dayjs": {
-      "version": "1.11.13",
-      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
-      "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
+      "version": "1.11.19",
+      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
+      "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
       "license": "MIT"
     },
     "node_modules/debug": {

+ 1 - 0
package.json

@@ -18,6 +18,7 @@
     "@vue-office/pptx": "^1.0.1",
     "axios": "^1.10.0",
     "crypto-js": "^4.2.0",
+    "dayjs": "^1.11.19",
     "element-plus": "^2.10.2",
     "highlight.js": "^11.11.1",
     "hls.js": "^1.6.7",

+ 6 - 0
src/api/date/dateUtil.js

@@ -0,0 +1,6 @@
+import dayjs from "dayjs";
+
+export function formatLocalDateTime(time, format = 'YYYY-MM-DD HH:mm:ss') {
+    if (!time) return '' // 处理空值,避免报错
+    return dayjs(time).format(format)
+}

+ 0 - 40
src/components/HomePage.vue

@@ -110,41 +110,8 @@ const updatePlatformTitle = () => {
 // 获取当前路由对象
 const router = useRouter()
 
-
-// 检查课程权限的通用函数
-const checkCoursePermission = (courseName) => {
-  // 从本地存储获取课程权限配置
-  const coursePermissionsStr = localStorage.getItem('coursePermissions');
-  let hasPermission = true; 
-  
-  if (coursePermissionsStr) {
-    try {
-      const coursePermissions = JSON.parse(coursePermissionsStr);
-      // 获取对应课程的权限状态
-      const permission = coursePermissions[courseName];
-      // 检查是否无权限
-      if (permission === '无权限') {
-        hasPermission = false;
-      }
-    } catch (error) {
-      console.error('解析课程权限配置失败:', error);
-    }
-  }
-  
-  return hasPermission;
-}
-
 // 处理按钮点击事件
 const handleButtonClick = (button) => {
-  // 检查课程权限
-  const hasPermission = checkCoursePermission(button.name);
-  
-  if (!hasPermission) {
-    // 无权限时弹框提示
-    ElMessage.warning('未激活课程,无法访问');
-    return;
-  }
-  
   selectedButton.value = button.name
   router.push(button.route)
 }
@@ -162,13 +129,6 @@ const indexImages = ref([intelligenceImg, roomImg, testImg, studyImg])
 
 // 智能课
 const goToAIGeneralCourse = title => {
-  // 检查课程权限
-  const hasPermission = checkCoursePermission('课程权限');
-  if (!hasPermission) {
-    // 无权限时弹框提示
-    ElMessage.warning('未激活课程,无法访问');
-    return;
-  }
   router.push({ path: '/ai-general-course', state: { title } })
 }
 

+ 44 - 40
src/components/user/UserInfoPopover.vue

@@ -2,7 +2,7 @@
   <!-- 用户信息下拉菜单 -->
   <el-dropdown @visible-change="handleVisibleChange">
     <div class="user-name-box">
-      {{ userName }}
+      {{ userInfo.nickname }}
       <!-- 根据下拉框状态显示不同的箭头图标 -->
       <el-icon v-if="!dropdownVisible" class="arrow-icon"><ArrowDownBold /></el-icon>
       <el-icon v-else class="arrow-icon"><ArrowUpBold /></el-icon>
@@ -19,10 +19,23 @@
             <p>已激活课程</p>
           </div>
           <div class="bottom-inner-box">
-            <div v-for="(course, index) in courses" :key="index" class="course-item">
+            <div class="course-item">
               <div class="check-circle">✓</div>
-              <span>{{ course.name }}</span>
-              <span>{{ course.expireDate }}{{ course.expireDate !== '无权限' ? '到期' : '' }}</span>
+              <span>通识课:</span>
+              <span v-if="userInfo.isRegister">{{ userInfo.courseExpireTime ? userInfo.courseExpireTime+' 到期' : '无权限' }}</span>
+              <span v-else>{{userInfo.roleRouteSet.includes(ROLE_KEY.COURSE) ? '已开通' : '无权限'}}</span>
+            </div>
+            <div class="course-item">
+              <div class="check-circle">✓</div>
+              <span>编程课:</span>
+              <span v-if="userInfo.isRegister">{{ userInfo.blocklyExpireTime ? userInfo.blocklyExpireTime+' 到期' : '无权限' }}</span>
+              <span v-else>{{userInfo.roleRouteSet.includes(ROLE_KEY.BLOCKLY) ? '已开通' : '未开通'}}</span>
+            </div>
+            <div class="course-item">
+              <div class="check-circle">✓</div>
+              <span>AI实验课:</span>
+              <span v-if="userInfo.isRegister">{{ userInfo.aiCourseExpireTime ? userInfo.aiCourseExpireTime+' 到期' : '无权限' }}</span>
+              <span v-else>{{userInfo.roleRouteSet.includes(ROLE_KEY.AI_COURSE) ? '已开通' : '未开通'}}</span>
             </div>
           </div>
         </div>
@@ -58,32 +71,25 @@ import { homeRoutes } from "@/router/index.js"
 import {activateInviteCode, getUserInfo} from '@/api/user/user.js'
 // 图标
 import { ArrowUpBold, ArrowDownBold } from '@element-plus/icons-vue'
-
-// 激活码响应式变量
-const activationCode = ref('')
-
-// 课程列表响应式变量
-const courses = ref([])
-
-// 用户名响应式变量
-const userName = ref()
+import {formatLocalDateTime} from "@/api/date/dateUtil.js";
+import {CONFIG, ROLE_KEY, setCacheWithExpiry} from "@/utils/roleUtils.js";
+// 激活码
+const activationCode = ref("")
+// 用户名信息变量
 const userInfo = ref({
   userId: null,
   userName: import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME,
-  nickname: '',
-  courseExpireTime: '',
-  blocklyExpireTime: '',
-  aiCourseExpireTime: ''
+  nickname: import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME,
+  isRegister: true,
+  roleRouteSet: [],
+  courseExpireTime: null,
+  blocklyExpireTime: null,
+  aiCourseExpireTime: null,
 })
 
 // 下拉框可见性状态
 const dropdownVisible = ref(false)
 
-// 更新用户名
-const updateUserName = () => {
-  userInfo.value.userName = localStorage.getItem('userName') || import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME
-}
-
 // 处理下拉框显示/隐藏事件
 const handleVisibleChange = (visible) => {
   dropdownVisible.value = visible
@@ -91,6 +97,8 @@ const handleVisibleChange = (visible) => {
 
 // 获取用户信息
 const fetchUserInfo = async () => {
+  userInfo.value.userName = localStorage.getItem('userName') || import.meta.env.VITE_APP_DEFAULT_LOGIN_USERNAME
+
   try {
     const userId = localStorage.getItem('userId');
     // 检查userId是否存在
@@ -99,24 +107,22 @@ const fetchUserInfo = async () => {
       return;
     }
     const res = await getUserInfo(userId);
+
     console.log('用户信息:', res);
     if (res.code === 0 && res.data) {
-      // 更新用户名
-      userName.value = res.data.username;
-      localStorage.setItem('userName', res.data.username);
-      // 更新课程信息
-      courses.value = [
-        { name: '课程权限', expireDate: res.data.courseExpireTime || '无权限' },
-        { name: 'AI编程课', expireDate: res.data.blocklyExpireTime || '无权限' },
-        { name: 'AI实验课', expireDate: res.data.aiCourseExpireTime || '无权限' }
-      ];
-      // 将课程权限信息存储在localStorage中,以便其他组件使用
-      const coursePermissions = {
-        '课程权限': res.data.courseExpireTime || '无权限',
-        '编程课': res.data.blocklyExpireTime || '无权限',
-        'AI实验课': res.data.aiCourseExpireTime || '无权限'
-      };
-      localStorage.setItem('coursePermissions', JSON.stringify(coursePermissions));
+      let user = res.data;
+
+      userInfo.value = {...user}
+      if (user.isRegister) {
+        userInfo.value.courseExpireTime = formatLocalDateTime(user.courseExpireTime);
+        userInfo.value.blocklyExpireTime = formatLocalDateTime(user.blocklyExpireTime);
+        userInfo.value.aiCourseExpireTime = formatLocalDateTime(user.aiCourseExpireTime);
+      }
+      localStorage.setItem('userName', user.nickname || user.userName);
+      localStorage.setItem('userInfo', user.nickname || user.userName);
+
+      //缓存用户角色路由
+      setCacheWithExpiry(CONFIG.USER_ROLE_ROUTE_KEY, user.roleRouteSet);
     }
   } catch (error) {
     console.error('获取用户信息失败:', error);
@@ -158,8 +164,6 @@ const handleActivation = () => {
 }
 
 onMounted(() => {
-  // 初始化用户名
-  updateUserName()
   // 获取用户信息
   fetchUserInfo()
   // storage事件监听器,监听其他标签页对localStorage的修改

+ 24 - 9
src/utils/roleUtils.js

@@ -8,20 +8,19 @@ const CONFIG = {
     EXPIRY_SUFFIX: '_expiry',
     EXPIRY_TIME: 24 * 60 * 60 * 1000 // 24小时
 }
+const ROLE_KEY = {
+    COURSE: 'course',
+    BLOCKLY: 'blockly',
+    AI_COURSE: 'aiCourse'
+}
 
 /**
  * 刷新角色路由缓存
  * @returns {Promise<Array>} - 角色路由数组
  */
-export const refreshRoleRoute = async (refresh = true) => {
+export const refreshRoleRoute = async () => {
     try {
 
-        // 检查缓存是否存在且未过期
-        const cachedData = localStorage.getItem(CONFIG.USER_ROLE_ROUTE_KEY);
-        if (!refresh && cachedData && !isCacheExpired(CONFIG.USER_ROLE_ROUTE_KEY)) {
-            return JSON.parse(cachedData);
-        }
-
         // 缓存不存在或已过期,从服务器获取
         const res = await getRoleRoute();
         if (res.code === 0) {
@@ -31,7 +30,8 @@ export const refreshRoleRoute = async (refresh = true) => {
 
             return res.data;
         } else {
-            throw new Error('获取角色路由数据失败');
+            console.error(`获取角色路由数据失败:`, res.msg);
+            return [];
         }
     } catch (error) {
         console.error(`获取角色路由数据失败:`, error);
@@ -70,4 +70,19 @@ const setCacheWithExpiry = (key, data) => {
 };
 
 
-export { CONFIG };
+/**
+ * 取指定key的缓存
+ * @returns {any} - 缓存数据
+ */
+const getRoleRouteCache = () => {
+    // 检查缓存是否存在且未过期
+    const cachedData = localStorage.getItem(CONFIG.USER_ROLE_ROUTE_KEY);
+    if (cachedData && !isCacheExpired(CONFIG.USER_ROLE_ROUTE_KEY)) {
+        return JSON.parse(cachedData);
+    }
+
+    return refreshRoleRoute();
+}
+
+
+export { CONFIG,ROLE_KEY,setCacheWithExpiry,getRoleRouteCache };

+ 6 - 0
src/views/RegisterLogin.vue

@@ -178,6 +178,12 @@ const handleRegister = async () => {
     await loginFormRef.value.validate();
     // 获取租户名称
     const tenantName = loginForm.value.tenantName;
+
+    if (tenantName === import.meta.env.VITE_APP_TITLE) {
+      ElMessage.error('此租户不支持注册!');
+      return;
+    }
+
     // 获取租户ID
     const tenantId = await getTenantId(tenantName);
     if (!tenantId) {