Browse Source

1.1.3 修复切换用户后登录后菜单不加载bug以及菜单渲染两次的问题

liuyanpeng 1 day ago
parent
commit
3881114673

+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "name": "client-base-v5",
   "description": "Leanwo Prodog Client",
-  "version": "1.1.2",
+  "version": "1.1.3",
   "author": "yangzhijie1488 <yangzhijie1488@163.com>",
   "scripts": {
     "ins": "npm install --registry https://npm.leanwo.com",

+ 19 - 8
src/client/MenuWidget.vue

@@ -60,7 +60,7 @@ const props = defineProps({
     default: false,
   },
 });
-const roleStateInstance = ref(useRoleStateSingleton);
+const roleStateInstance = useRoleStateSingleton;
 const searchText = ref('');
 const openKeys = ref([]);
 const selectedKeys = ref([]);
@@ -74,7 +74,7 @@ const loadMenuData = () => {
   $.ajax({
     url: Common.getApiURL('MenuResourceV2/listCanVist'),
     type: 'POST',
-    data: roleStateInstance.value.userRoleOrTemplate == null ? null : JSON.stringify(roleStateInstance.value.userRoleOrTemplate),
+    data: roleStateInstance.userRoleOrTemplate.value == null ? null : JSON.stringify(roleStateInstance.userRoleOrTemplate.value),
     dataType: 'json',
     contentType: 'application/json',
     beforeSend: request => Common.addTokenToRequest(request),
@@ -216,20 +216,28 @@ const goApproval = () => {
   });
 };
 
-// 监听角色状态变化
-watch(() => roleStateInstance.value.userRoleOrTemplate, (newVal, oldVal) => {
-  if(newVal || newVal === null) loadMenuData();
+// 监听角色就绪 — 首次加载入口
+watch(roleStateInstance.roleReady, ready => {
+  if (ready && props.isShowMenu) {
+    loadMenuData();
+  }
+});
+
+// 监听角色状态变化 — 仅在角色已就绪后响应(用户手动切换角色)
+watch(roleStateInstance.userRoleOrTemplate, (newVal, oldVal) => {
+  if (!roleStateInstance.roleReady.value) return;
+  if (newVal || newVal === null) loadMenuData();
   if (newVal && oldVal && newVal.roleOrTemplateName !== oldVal.roleOrTemplateName) {
     router.push('/desktop/dashboard');
   }
-  if(newVal === null)  router.push('/desktop/dashboard');
+  if (newVal === null) router.push('/desktop/dashboard');
 });
 
 watch(() => props.isShowMenu, (newVal, oldVal) => {
   if (newVal) {
     loadMenuData();
   }
-}, { immediate: true });
+});
 
 // 监听搜索框输入
 watch(searchText, () => {
@@ -266,7 +274,10 @@ watch(searchText, () => {
 
 onMounted(() => {
   getLogoName();
-  // loadMenuData();
+  // 防御:若 MenuWidget 挂载时 roleReady 已为 true(极端时序),直接加载
+  if (roleStateInstance.roleReady.value) {
+    loadMenuData();
+  }
 });
 
 </script>

+ 7 - 1
src/client/RoleState.js

@@ -1,16 +1,22 @@
-import { reactive, ref } from 'vue';
+import { ref } from 'vue';
 
 function useRoleState() {
   const userRoleOrTemplate = ref();
+  const roleReady = ref(false);
 
   function setUserRoleOrTemplate(newUserRoleOrTemplate) {
     userRoleOrTemplate.value = newUserRoleOrTemplate;
   }
 
+  function markRoleReady() {
+    roleReady.value = true;
+  }
 
   return {
     userRoleOrTemplate,
+    roleReady,
     setUserRoleOrTemplate,
+    markRoleReady,
   };
 }
 

+ 47 - 31
src/client/top-nav-role-select.vue

@@ -24,12 +24,9 @@
 <script>
 import { DownOutlined } from '@ant-design/icons-vue';
 import Common from '../common/Common.js';
-import ClientResourceV2 from '../api/base/ClientResourceV2.js';
-import TokenClientResource from '../api/base/TokenClientResource.js';
-import { Notify, Uuid } from 'pc-component-v3';
+import { Notify } from 'pc-component-v3';
 import { useRoleStateSingleton } from './RoleState.js';
 import { UserStorageResource } from 'pc-component-v3';
-import { message } from 'ant-design-vue';
 
 export default {
   components: {
@@ -39,7 +36,6 @@ export default {
   data() {
     return {
       userRoleOrTemplateList: [],
-      loginClientName: '',
       roleStateInstance: useRoleStateSingleton,
     };
   },
@@ -51,16 +47,38 @@ export default {
   },
 
   mounted() {
-    this.listUserRoleOrTemplate();
+    this.init();
   },
 
   methods: {
-    handleRoleSelect(userRoleOrTemplate) {
-      this.roleStateInstance.setUserRoleOrTemplate(userRoleOrTemplate);
-      this.uploadSelectedRole(userRoleOrTemplate);
+    // 入口:先获取已保存的选中项,再加载角色列表,最后通知消费者就绪
+    async init() {
+      try {
+        const savedRole = await this.fetchSavedRole();
+        await this.loadRoleList(savedRole);
+      } finally {
+        // 无论角色列表加载成功或失败,都必须通知消费者初始化已完成
+        this.roleStateInstance.markRoleReady();
+      }
     },
 
-    async listUserRoleOrTemplate() {
+    // 仅从远端获取已保存的选中角色,不做任何副作用
+    async fetchSavedRole() {
+      const key = 'UserSelectedRole';
+      try {
+        const { errorCode, data } = await UserStorageResource.uniqueByKey(key);
+        if (errorCode === 0) {
+          return data ? JSON.parse(data) : null;
+        }
+        return null;
+      } catch (error) {
+        Common.processException(error);
+        return null;
+      }
+    },
+
+    // 加载角色列表后,将已保存的选中项匹配到列表并设置选中状态
+    async loadRoleList(savedRole) {
       try {
         const response = await $.ajax({
           url: Common.getApiURL('RoleResourceV3/listUserRoleOrTemplate'),
@@ -71,7 +89,7 @@ export default {
 
         if (response.errorCode === 0) {
           this.userRoleOrTemplateList = response.datas;
-          this.downloadSelectedRole();
+          this.applySavedRole(savedRole);
         } else {
           Notify.error('错误', response.errorMessage, false);
         }
@@ -80,6 +98,24 @@ export default {
       }
     },
 
+    // 在已加载的角色列表中匹配 savedRole,匹配不到或 savedRole 为 null 时显式选择「全部」
+    applySavedRole(savedRole) {
+      if (!savedRole) {
+        this.roleStateInstance.setUserRoleOrTemplate(null);
+      } else {
+        const matched = this.userRoleOrTemplateList.find(item =>
+          `${item.userRoleTemplateId}-${item.userRoleId}` ===
+          `${savedRole.userRoleTemplateId}-${savedRole.userRoleId}`,
+        );
+        this.roleStateInstance.setUserRoleOrTemplate(matched || null);
+      }
+    },
+
+    handleRoleSelect(userRoleOrTemplate) {
+      this.roleStateInstance.setUserRoleOrTemplate(userRoleOrTemplate);
+      this.uploadSelectedRole(userRoleOrTemplate);
+    },
+
     async uploadSelectedRole(userRoleOrTemplate) {
       const key = 'UserSelectedRole';
       const userStorageDtos = [{
@@ -93,26 +129,6 @@ export default {
         Common.processException(error);
       }
     },
-
-    async downloadSelectedRole() {
-      const key = 'UserSelectedRole';
-      
-      try {
-        const { errorCode, data } = await UserStorageResource.uniqueByKey(key);
-        if (errorCode === 0) {
-          const selectedRole = data ? JSON.parse(data) : null;
-          if (selectedRole) {
-            const matched = this.userRoleOrTemplateList.find(item => 
-              `${item.userRoleTemplateId}-${item.userRoleId}` === 
-              `${selectedRole.userRoleTemplateId}-${selectedRole.userRoleId}`,
-            );
-            this.roleStateInstance.setUserRoleOrTemplate(matched || null);
-          }
-        }
-      } catch (error) {
-        Common.processException(error);
-      }
-    },
   },
 };
 </script>

+ 5 - 1
src/dashboard/Dashboard.vue

@@ -41,7 +41,11 @@ export default defineComponent({
   },
 
   mounted: function () {
-    this.loadData();
+    // 仅在角色已初始化(非首次挂载)时才直接加载,
+    // 首次挂载由 watch(roleStateInstance.userRoleOrTemplate) 驱动
+    if (this.roleStateInstance.userRoleOrTemplate !== undefined) {
+      this.loadData();
+    }
   },
 
   beforeUnmount: function () {