Преглед на файлове

前端与Vben仓库同步更新

zuohuaijun преди 4 години
родител
ревизия
fdde2cb946
променени са 33 файла, в които са добавени 170 реда и са изтрити 55 реда
  1. 5 2
      Vben2/src/components/Form/src/BasicForm.vue
  2. 3 2
      Vben2/src/components/Form/src/hooks/useFormEvents.ts
  3. 2 2
      Vben2/src/components/Form/src/hooks/useFormValues.ts
  4. 7 4
      Vben2/src/components/Table/src/components/settings/ColumnSetting.vue
  5. 2 2
      Vben2/src/components/Tree/index.ts
  6. 11 4
      Vben2/src/components/Tree/src/BasicTree.vue
  7. 1 1
      Vben2/src/components/Tree/src/components/TreeHeader.vue
  8. 1 1
      Vben2/src/components/Tree/src/hooks/useTree.ts
  9. 0 0
      Vben2/src/components/Tree/src/types/tree.ts
  10. 5 1
      Vben2/src/enums/appEnum.ts
  11. 0 1
      Vben2/src/hooks/core/useContext.ts
  12. 6 2
      Vben2/src/hooks/setting/useMenuSetting.ts
  13. 6 1
      Vben2/src/hooks/web/useECharts.ts
  14. 1 1
      Vben2/src/hooks/web/usePage.ts
  15. 1 0
      Vben2/src/hooks/web/usePermission.ts
  16. 9 5
      Vben2/src/layouts/default/sider/useLayoutSider.ts
  17. 11 0
      Vben2/src/router/helper/menuHelper.ts
  18. 15 1
      Vben2/src/router/helper/routeHelper.ts
  19. 1 0
      Vben2/src/router/index.ts
  20. 3 1
      Vben2/src/router/routes/index.ts
  21. 2 0
      Vben2/src/settings/projectSetting.ts
  22. 42 1
      Vben2/src/store/modules/permission.ts
  23. 12 0
      Vben2/src/utils/helper/treeHelper.ts
  24. 1 1
      Vben2/src/utils/http/axios/Axios.ts
  25. 2 2
      Vben2/src/utils/http/axios/index.ts
  26. 1 0
      Vben2/src/utils/index.ts
  27. 1 0
      Vben2/src/views/demo/system/account/index.vue
  28. 1 0
      Vben2/src/views/demo/system/dept/index.vue
  29. 1 0
      Vben2/src/views/demo/system/menu/index.vue
  30. 1 0
      Vben2/src/views/demo/system/role/index.vue
  31. 7 7
      Vben2/src/views/demo/tree/index.vue
  32. 1 0
      Vben2/types/config.d.ts
  33. 8 13
      doc/Vben2前端框架修改记录.txt

+ 5 - 2
Vben2/src/components/Form/src/BasicForm.vue

@@ -62,6 +62,7 @@
 
   import { basicProps } from './props';
   import { useDesign } from '/@/hooks/web/useDesign';
+  import { cloneDeep } from 'lodash-es';
 
   export default defineComponent({
     name: 'BasicForm',
@@ -132,9 +133,11 @@
           }
         }
         if (unref(getProps).showAdvancedButton) {
-          return schemas.filter((schema) => schema.component !== 'Divider') as FormSchema[];
+          return cloneDeep(
+            schemas.filter((schema) => schema.component !== 'Divider') as FormSchema[],
+          );
         } else {
-          return schemas as FormSchema[];
+          return cloneDeep(schemas as FormSchema[]);
         }
       });
 

+ 3 - 2
Vben2/src/components/Form/src/hooks/useFormEvents.ts

@@ -39,7 +39,8 @@ export function useFormEvents({
     Object.keys(formModel).forEach((key) => {
       const schema = unref(getSchema).find((item) => item.field === key);
       const isInput = schema?.component && defaultValueComponents.includes(schema.component);
-      formModel[key] = isInput ? defaultValueRef.value[key] || '' : defaultValueRef.value[key];
+      const defaultValue = cloneDeep(defaultValueRef.value[key]);
+      formModel[key] = isInput ? defaultValue || '' : defaultValue;
     });
     nextTick(() => clearValidate());
 
@@ -100,7 +101,7 @@ export function useFormEvents({
           } catch (e) {
             // key not exist
             if (isDef(defaultValueRef.value[nestKey])) {
-              formModel[nestKey] = defaultValueRef.value[nestKey];
+              formModel[nestKey] = cloneDeep(defaultValueRef.value[nestKey]);
             }
           }
         });

+ 2 - 2
Vben2/src/components/Form/src/hooks/useFormValues.ts

@@ -3,7 +3,7 @@ import { dateUtil } from '/@/utils/dateUtil';
 import { unref } from 'vue';
 import type { Ref, ComputedRef } from 'vue';
 import type { FormProps, FormSchema } from '../types/form';
-import { set } from 'lodash-es';
+import { cloneDeep, set } from 'lodash-es';
 
 interface UseFormValuesContext {
   defaultValueRef: Ref<any>;
@@ -124,7 +124,7 @@ export function useFormValues({
         }
       }
     });
-    defaultValueRef.value = obj;
+    defaultValueRef.value = cloneDeep(obj);
   }
 
   return { handleFormValues, initDefault };

+ 7 - 4
Vben2/src/components/Table/src/components/settings/ColumnSetting.vue

@@ -184,9 +184,7 @@
       watchEffect(() => {
         const columns = table.getColumns();
         if (columns.length && !state.isInit) {
-          setTimeout(() => {
-            init();
-          }, 0);
+          init();
         }
       });
 
@@ -315,7 +313,12 @@
               }
 
               plainSortOptions.value = columns;
-              setColumns(columns);
+
+              setColumns(
+                columns
+                  .map((col: Options) => col.value)
+                  .filter((value: string) => state.checkedList.includes(value)),
+              );
             },
           });
           // 记录原始order 序列

+ 2 - 2
Vben2/src/components/Tree/index.ts

@@ -1,6 +1,6 @@
-import BasicTree from './src/Tree.vue';
+import BasicTree from './src/BasicTree.vue';
 import './style';
 
 export { BasicTree };
 export type { ContextMenuItem } from '/@/hooks/web/useContextMenu';
-export * from './src/tree';
+export * from './src/types/tree';

+ 11 - 4
Vben2/src/components/Tree/src/Tree.vue → Vben2/src/components/Tree/src/BasicTree.vue

@@ -1,6 +1,13 @@
 <script lang="tsx">
   import type { CSSProperties } from 'vue';
-  import type { FieldNames, TreeState, TreeItem, KeyType, CheckKeys, TreeActionType } from './tree';
+  import type {
+    FieldNames,
+    TreeState,
+    TreeItem,
+    KeyType,
+    CheckKeys,
+    TreeActionType,
+  } from './types/tree';
 
   import {
     defineComponent,
@@ -13,7 +20,7 @@
     watch,
     onMounted,
   } from 'vue';
-  import TreeHeader from './TreeHeader.vue';
+  import TreeHeader from './components/TreeHeader.vue';
   import { Tree, Spin, Empty } from 'ant-design-vue';
   import { TreeIcon } from './TreeIcon';
   import { ScrollContainer } from '/@/components/Container';
@@ -21,10 +28,10 @@
   import { isArray, isBoolean, isEmpty, isFunction } from '/@/utils/is';
   import { extendSlots, getSlot } from '/@/utils/helper/tsxHelper';
   import { filter, treeToList, eachTree } from '/@/utils/helper/treeHelper';
-  import { useTree } from './useTree';
+  import { useTree } from './hooks/useTree';
   import { useContextMenu } from '/@/hooks/web/useContextMenu';
   import { CreateContextOptions } from '/@/components/ContextMenu';
-  import { treeEmits, treeProps } from './tree';
+  import { treeEmits, treeProps } from './types/tree';
   import { createBEM } from '/@/utils/bem';
 
   export default defineComponent({

+ 1 - 1
Vben2/src/components/Tree/src/TreeHeader.vue → Vben2/src/components/Tree/src/components/TreeHeader.vue

@@ -40,7 +40,7 @@
   import { useI18n } from '/@/hooks/web/useI18n';
   import { useDebounceFn } from '@vueuse/core';
   import { createBEM } from '/@/utils/bem';
-  import { ToolbarEnum } from './tree';
+  import { ToolbarEnum } from '../types/tree';
 
   const searchValue = ref('');
 

+ 1 - 1
Vben2/src/components/Tree/src/useTree.ts → Vben2/src/components/Tree/src/hooks/useTree.ts

@@ -1,4 +1,4 @@
-import type { InsertNodeParams, KeyType, FieldNames, TreeItem } from './tree';
+import type { InsertNodeParams, KeyType, FieldNames, TreeItem } from '../types/tree';
 import type { Ref, ComputedRef } from 'vue';
 import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
 

+ 0 - 0
Vben2/src/components/Tree/src/tree.ts → Vben2/src/components/Tree/src/types/tree.ts


+ 5 - 1
Vben2/src/enums/appEnum.ts

@@ -30,14 +30,18 @@ export enum SessionTimeoutProcessingEnum {
  */
 export enum PermissionModeEnum {
   // role
+  // 角色权限
   ROLE = 'ROLE',
   // black
+  // 后端
   BACK = 'BACK',
   // route mapping
+  // 路由映射
   ROUTE_MAPPING = 'ROUTE_MAPPING',
 }
 
-//  Route switching animation
+// Route switching animation
+// 路由切换动画
 export enum RouterTransitionEnum {
   ZOOM_FADE = 'zoom-fade',
   ZOOM_OUT = 'zoom-out',

+ 0 - 1
Vben2/src/hooks/core/useContext.ts

@@ -35,7 +35,6 @@ export function createContext<T>(
 }
 
 export function useContext<T>(key: InjectionKey<T>, native?: boolean): T;
-export function useContext<T>(key: InjectionKey<T>, defaultValue?: any, native?: boolean): T;
 
 export function useContext<T>(
   key: InjectionKey<T> = Symbol(),

+ 6 - 2
Vben2/src/hooks/setting/useMenuSetting.ts

@@ -101,8 +101,12 @@ export function useMenuSetting() {
   });
 
   const getMiniWidthNumber = computed(() => {
-    const { collapsedShowTitle } = appStore.getMenuSetting;
-    return collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH;
+    const { collapsedShowTitle, siderHidden } = appStore.getMenuSetting;
+    return siderHidden
+      ? 0
+      : collapsedShowTitle
+      ? SIDE_BAR_SHOW_TIT_MINI_WIDTH
+      : SIDE_BAR_MINI_WIDTH;
   });
 
   const getCalcContentWidth = computed(() => {

+ 6 - 1
Vben2/src/hooks/web/useECharts.ts

@@ -79,7 +79,12 @@ export function useECharts(
   }
 
   function resize() {
-    chartInstance?.resize();
+    chartInstance?.resize({
+      animation: {
+        duration: 300,
+        easing: 'quadraticIn',
+      },
+    });
   }
 
   watch(

+ 1 - 1
Vben2/src/hooks/web/usePage.ts

@@ -7,7 +7,7 @@ import { unref } from 'vue';
 import { useRouter } from 'vue-router';
 import { REDIRECT_NAME } from '/@/router/constant';
 
-export type RouteLocationRawEx = Omit<RouteLocationRaw, 'path'> & { path: PageEnum };
+export type RouteLocationRawEx = RouteLocationRaw & { path: PageEnum };
 
 function handleError(e: Error) {
   console.error(e);

+ 1 - 0
Vben2/src/hooks/web/usePermission.ts

@@ -39,6 +39,7 @@ export function usePermission() {
 
   /**
    * Reset and regain authority resource information
+   * 重置和重新获得权限资源信息
    * @param id
    */
   async function resume() {

+ 9 - 5
Vben2/src/layouts/default/sider/useLayoutSider.ts

@@ -1,26 +1,30 @@
 import type { Ref } from 'vue';
 
-import { computed, unref, onMounted, nextTick, ref } from 'vue';
+import { computed, unref, onMounted, nextTick } from 'vue';
 
 import { TriggerEnum } from '/@/enums/menuEnum';
 
 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
 import { useDebounceFn } from '@vueuse/core';
+import { useAppStore } from '/@/store/modules/app';
 
 /**
  * Handle related operations of menu events
  */
 export function useSiderEvent() {
-  const brokenRef = ref(false);
-
+  const appStore = useAppStore();
   const { getMiniWidthNumber } = useMenuSetting();
 
   const getCollapsedWidth = computed(() => {
-    return unref(brokenRef) ? 0 : unref(getMiniWidthNumber);
+    return unref(getMiniWidthNumber);
   });
 
   function onBreakpointChange(broken: boolean) {
-    brokenRef.value = broken;
+    appStore.setProjectConfig({
+      menuSetting: {
+        siderHidden: broken,
+      },
+    });
   }
 
   return { getCollapsedWidth, onBreakpointChange };

+ 11 - 0
Vben2/src/router/helper/menuHelper.ts

@@ -11,14 +11,18 @@ export function getAllParentPath<T = Recordable>(treeData: T[], path: string) {
   return (menuList || []).map((item) => item.path);
 }
 
+// 路径处理
 function joinParentPath(menus: Menu[], parentPath = '') {
   for (let index = 0; index < menus.length; index++) {
     const menu = menus[index];
     // https://next.router.vuejs.org/guide/essentials/nested-routes.html
     // Note that nested paths that start with / will be treated as a root path.
+    // 请注意,以 / 开头的嵌套路径将被视为根路径。
     // This allows you to leverage the component nesting without having to use a nested URL.
+    // 这允许你利用组件嵌套,而无需使用嵌套 URL。
     if (!(menu.path.startsWith('/') || isUrl(menu.path))) {
       // path doesn't start with /, nor is it a url, join parent path
+      // 路径不以 / 开头,也不是 url,加入父路径
       menu.path = `${parentPath}/${menu.path}`;
     }
     if (menu?.children?.length) {
@@ -37,14 +41,18 @@ export function transformMenuModule(menuModule: MenuModule): Menu {
   return menuList[0];
 }
 
+// 将路由转换成菜单
 export function transformRouteToMenu(routeModList: AppRouteModule[], routerMapping = false) {
+  // 借助 lodash 深拷贝
   const cloneRouteModList = cloneDeep(routeModList);
   const routeList: AppRouteRecordRaw[] = [];
 
+  // 对路由项进行修改
   cloneRouteModList.forEach((item) => {
     if (routerMapping && item.meta.hideChildrenInMenu && typeof item.redirect === 'string') {
       item.path = item.redirect;
     }
+
     if (item.meta?.single) {
       const realItem = item?.children?.[0];
       realItem && routeList.push(realItem);
@@ -52,6 +60,7 @@ export function transformRouteToMenu(routeModList: AppRouteModule[], routerMappi
       routeList.push(item);
     }
   });
+  // 提取树指定结构
   const list = treeMap(routeList, {
     conversion: (node: AppRouteRecordRaw) => {
       const { meta: { title, hideMenu = false } = {} } = node;
@@ -66,6 +75,7 @@ export function transformRouteToMenu(routeModList: AppRouteModule[], routerMappi
       };
     },
   });
+  // 路径处理
   joinParentPath(list);
   return cloneDeep(list);
 }
@@ -74,6 +84,7 @@ export function transformRouteToMenu(routeModList: AppRouteModule[], routerMappi
  * config menu with given params
  */
 const menuParamRegex = /(?::)([\s\S]+?)((?=\/)|$)/g;
+
 export function configureDynamicParamsMenu(menu: Menu, params: RouteParams) {
   const { path, paramPath } = toRaw(menu);
   let realPath = paramPath ? paramPath : path;

+ 15 - 1
Vben2/src/router/helper/routeHelper.ts

@@ -68,6 +68,7 @@ function dynamicImport(
 }
 
 // Turn background objects into routing objects
+// 将背景对象变成路由对象
 export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
   routeList.forEach((route) => {
     const component = route.component as string;
@@ -94,35 +95,46 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul
 
 /**
  * Convert multi-level routing to level 2 routing
+ * 将多级路由转换为 2 级路由
  */
 export function flatMultiLevelRoutes(routeModules: AppRouteModule[]) {
   const modules: AppRouteModule[] = cloneDeep(routeModules);
+
   for (let index = 0; index < modules.length; index++) {
     const routeModule = modules[index];
+    // 判断级别是否 多级 路由
     if (!isMultipleRoute(routeModule)) {
+      // 声明终止当前循环, 即跳过此次循环,进行下一轮
       continue;
     }
+    // 路由等级提升
     promoteRouteLevel(routeModule);
   }
   return modules;
 }
 
 // Routing level upgrade
+// 路由等级提升
 function promoteRouteLevel(routeModule: AppRouteModule) {
   // Use vue-router to splice menus
+  // 使用vue-router拼接菜单
+  // createRouter 创建一个可以被 Vue 应用程序使用的路由实例
   let router: Router | null = createRouter({
     routes: [routeModule as unknown as RouteRecordNormalized],
     history: createWebHashHistory(),
   });
-
+  // getRoutes: 获取所有 路由记录的完整列表。
   const routes = router.getRoutes();
+  // 将所有子路由添加到二级路由
   addToChildren(routes, routeModule.children || [], routeModule);
   router = null;
 
+  // omit lodash的函数 对传入的item对象的children进行删除
   routeModule.children = routeModule.children?.map((item) => omit(item, 'children'));
 }
 
 // Add all sub-routes to the secondary route
+// 将所有子路由添加到二级路由
 function addToChildren(
   routes: RouteRecordNormalized[],
   children: AppRouteRecordRaw[],
@@ -145,7 +157,9 @@ function addToChildren(
 }
 
 // Determine whether the level exceeds 2 levels
+// 判断级别是否超过2级
 function isMultipleRoute(routeModule: AppRouteModule) {
+  // Reflect.has 与 in 操作符 相同, 用于检查一个对象(包括它原型链上)是否拥有某个属性
   if (!routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length) {
     return false;
   }

+ 1 - 0
Vben2/src/router/index.ts

@@ -36,6 +36,7 @@ export function resetRouter() {
 }
 
 // config router
+// 配置路由器
 export function setupRouter(app: App<Element>) {
   app.use(router);
 }

+ 3 - 1
Vben2/src/router/routes/index.ts

@@ -6,10 +6,11 @@ import { mainOutRoutes } from './mainOut';
 import { PageEnum } from '/@/enums/pageEnum';
 import { t } from '/@/hooks/web/useI18n';
 
+// import.meta.globEager() 直接引入所有的模块 Vite 独有的功能
 const modules = import.meta.globEager('./modules/**/*.ts');
-
 const routeModuleList: AppRouteModule[] = [];
 
+// 加入到路由集合中
 Object.keys(modules).forEach((key) => {
   const mod = modules[key].default || {};
   const modList = Array.isArray(mod) ? [...mod] : [mod];
@@ -18,6 +19,7 @@ Object.keys(modules).forEach((key) => {
 
 export const asyncRoutes = [PAGE_NOT_FOUND_ROUTE, ...routeModuleList];
 
+// 根路由
 export const RootRoute: AppRouteRecordRaw = {
   path: '/',
   name: 'Root',

+ 2 - 0
Vben2/src/settings/projectSetting.ts

@@ -83,6 +83,8 @@ const setting: ProjectConfig = {
     fixed: true,
     // Menu collapse
     collapsed: false,
+    // When sider hide because of the responsive layout
+    siderHidden: false,
     // Whether to display the menu name when folding the menu
     collapsedShowTitle: false,
     // Whether it can be dragged

+ 42 - 1
Vben2/src/store/modules/permission.ts

@@ -26,26 +26,37 @@ import { PageEnum } from '/@/enums/pageEnum';
 
 interface PermissionState {
   // Permission code list
+  // 权限代码列表
   permCodeList: string[] | number[];
   // Whether the route has been dynamically added
+  // 路由是否动态添加
   isDynamicAddedRoute: boolean;
   // To trigger a menu update
+  // 触发菜单更新
   lastBuildMenuTime: number;
   // Backstage menu list
+  // 后台菜单列表
   backMenuList: Menu[];
+  // 菜单列表
   frontMenuList: Menu[];
 }
+
 export const usePermissionStore = defineStore({
   id: 'app-permission',
   state: (): PermissionState => ({
+    // 权限代码列表
     permCodeList: [],
     // Whether the route has been dynamically added
+    // 路由是否动态添加
     isDynamicAddedRoute: false,
     // To trigger a menu update
+    // 触发菜单更新
     lastBuildMenuTime: 0,
     // Backstage menu list
+    // 后台菜单列表
     backMenuList: [],
     // menu List
+    // 菜单列表
     frontMenuList: [],
   }),
   getters: {
@@ -96,6 +107,8 @@ export const usePermissionStore = defineStore({
       const codeList = await getPermCode();
       this.setPermCodeList(codeList);
     },
+
+    // 构建路由
     async buildRoutesAction(): Promise<AppRouteRecordRaw[]> {
       const { t } = useI18n();
       const userStore = useUserStore();
@@ -105,16 +118,21 @@ export const usePermissionStore = defineStore({
       const roleList = toRaw(userStore.getRoleList) || [];
       const { permissionMode = projectSetting.permissionMode } = appStore.getProjectConfig;
 
+      // 路由过滤器 在 函数filter 作为回调传入遍历使用
       const routeFilter = (route: AppRouteRecordRaw) => {
         const { meta } = route;
+        // 抽出角色
         const { roles } = meta || {};
         if (!roles) return true;
+        // 进行角色权限判断
         return roleList.some((role) => roles.includes(role));
       };
 
       const routeRemoveIgnoreFilter = (route: AppRouteRecordRaw) => {
         const { meta } = route;
+        // ignoreRoute 为true 则路由仅用于菜单生成,不会在实际的路由表中出现
         const { ignoreRoute } = meta || {};
+        // arr.filter 返回 true 表示该元素通过测试
         return !ignoreRoute;
       };
 
@@ -124,6 +142,7 @@ export const usePermissionStore = defineStore({
       const patchHomeAffix = (routes: AppRouteRecordRaw[]) => {
         if (!routes || routes.length === 0) return;
         let homePath: string = userStore.getUserInfo.homePath || PageEnum.BASE_HOME;
+
         function patcher(routes: AppRouteRecordRaw[], parentPath = '') {
           if (parentPath) parentPath = parentPath + '/';
           routes.forEach((route: AppRouteRecordRaw) => {
@@ -140,6 +159,7 @@ export const usePermissionStore = defineStore({
             children && children.length > 0 && patcher(children, currentPath);
           });
         }
+
         try {
           patcher(routes);
         } catch (e) {
@@ -149,29 +169,44 @@ export const usePermissionStore = defineStore({
       };
 
       switch (permissionMode) {
+        // 角色权限
         case PermissionModeEnum.ROLE:
+          // 对非一级路由进行过滤
           routes = filter(asyncRoutes, routeFilter);
+          // 对一级路由根据角色权限过滤
           routes = routes.filter(routeFilter);
           // Convert multi-level routing to level 2 routing
+          // 将多级路由转换为 2 级路由
           routes = flatMultiLevelRoutes(routes);
           break;
 
+        // 路由映射, 默认进入该case
         case PermissionModeEnum.ROUTE_MAPPING:
+          // 对非一级路由进行过滤
           routes = filter(asyncRoutes, routeFilter);
+          // 对一级路由再次根据角色权限过滤
           routes = routes.filter(routeFilter);
+          // 将路由转换成菜单
           const menuList = transformRouteToMenu(routes, true);
+          // 移除掉 ignoreRoute: true 的路由 非一级路由
           routes = filter(routes, routeRemoveIgnoreFilter);
+          // 移除掉 ignoreRoute: true 的路由 一级路由;
           routes = routes.filter(routeRemoveIgnoreFilter);
+          // 对菜单进行排序
           menuList.sort((a, b) => {
             return (a.meta?.orderNo || 0) - (b.meta?.orderNo || 0);
           });
 
+          // 设置菜单列表
           this.setFrontMenuList(menuList);
+
           // Convert multi-level routing to level 2 routing
+          // 将多级路由转换为 2 级路由
           routes = flatMultiLevelRoutes(routes);
           break;
 
         //  If you are sure that you do not need to do background dynamic permissions, please comment the entire judgment below
+        //  如果确定不需要做后台动态权限,请在下方评论整个判断
         case PermissionModeEnum.BACK:
           const { createMessage } = useMessage();
 
@@ -181,23 +216,28 @@ export const usePermissionStore = defineStore({
           });
 
           // !Simulate to obtain permission codes from the background,
+          // 模拟从后台获取权限码,
           // this function may only need to be executed once, and the actual project can be put at the right time by itself
+          // 这个功能可能只需要执行一次,实际项目可以自己放在合适的时间
           let routeList: AppRouteRecordRaw[] = [];
           try {
-            this.changePermissionCode();
+            await this.changePermissionCode();
             routeList = (await getMenuList()) as AppRouteRecordRaw[];
           } catch (error) {
             console.error(error);
           }
 
           // Dynamically introduce components
+          // 动态引入组件
           routeList = transformObjToRoute(routeList);
 
           //  Background routing to menu structure
+          //  后台路由到菜单结构
           const backMenuList = transformRouteToMenu(routeList);
           this.setBackMenuList(backMenuList);
 
           // remove meta.ignoreRoute item
+          // 删除 meta.ignoreRoute 项
           routeList = filter(routeList, routeRemoveIgnoreFilter);
           routeList = routeList.filter(routeRemoveIgnoreFilter);
 
@@ -214,6 +254,7 @@ export const usePermissionStore = defineStore({
 });
 
 // Need to be used outside the setup
+// 需要在设置之外使用
 export function usePermissionStoreWithOut() {
   return usePermissionStore(store);
 }

+ 12 - 0
Vben2/src/utils/helper/treeHelper.ts

@@ -3,15 +3,19 @@ interface TreeHelperConfig {
   children: string;
   pid: string;
 }
+
+// 默认配置
 const DEFAULT_CONFIG: TreeHelperConfig = {
   id: 'id',
   children: 'children',
   pid: 'pid',
 };
 
+// 获取配置。  Object.assign 从一个或多个源对象复制到目标对象
 const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config);
 
 // tree from list
+// 列表中的树
 export function listToTree<T = any>(list: any[], config: Partial<TreeHelperConfig> = {}): T[] {
   const conf = getConfig(config) as TreeHelperConfig;
   const nodeMap = new Map();
@@ -123,18 +127,24 @@ export function findPathAll(tree: any, func: Fn, config: Partial<TreeHelperConfi
 export function filter<T = any>(
   tree: T[],
   func: (n: T) => boolean,
+  // Partial 将 T 中的所有属性设为可选
   config: Partial<TreeHelperConfig> = {},
 ): T[] {
+  // 获取配置
   config = getConfig(config);
   const children = config.children as string;
+
   function listFilter(list: T[]) {
     return list
       .map((node: any) => ({ ...node }))
       .filter((node) => {
+        // 递归调用 对含有children项  进行再次调用自身函数 listFilter
         node[children] = node[children] && listFilter(node[children]);
+        // 执行传入的回调 func 进行过滤
         return func(node) || (node[children] && node[children].length);
       });
   }
+
   return listFilter(tree);
 }
 
@@ -157,6 +167,7 @@ export function forEach<T = any>(
 
 /**
  * @description: Extract tree specified structure
+ * @description: 提取树指定结构
  */
 export function treeMap<T = any>(treeData: T[], opt: { children?: string; conversion: Fn }): T[] {
   return treeData.map((item) => treeMapEach(item, opt));
@@ -164,6 +175,7 @@ export function treeMap<T = any>(treeData: T[], opt: { children?: string; conver
 
 /**
  * @description: Extract tree specified structure
+ * @description: 提取树指定结构
  */
 export function treeMapEach(
   data: any,

+ 1 - 1
Vben2/src/utils/http/axios/Axios.ts

@@ -61,7 +61,7 @@ export class VAxios {
   }
 
   /**
-   * @description: Interceptor configuration
+   * @description: Interceptor configuration 拦截器配置
    */
   private setupInterceptors() {
     const transform = this.getTransform();

+ 2 - 2
Vben2/src/utils/http/axios/index.ts

@@ -153,7 +153,6 @@ const transform: AxiosTransform = {
    * @description: 响应拦截器处理
    */
   responseInterceptors: (res: AxiosResponse<any>) => {
-    // checkStatus(res.data.code, res.data.message);
     return res;
   },
 
@@ -205,6 +204,7 @@ const transform: AxiosTransform = {
 
 function createAxios(opt?: Partial<CreateAxiosOptions>) {
   return new VAxios(
+    // 深度合并
     deepMerge(
       {
         // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
@@ -239,7 +239,7 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
           // 接口拼接地址
           urlPrefix: urlPrefix,
           //  是否加入时间戳
-          joinTime: false,
+          joinTime: true,
           // 忽略重复请求
           ignoreCancelToken: true,
           // 是否携带token

+ 1 - 0
Vben2/src/utils/index.ts

@@ -32,6 +32,7 @@ export function setObjToUrlParams(baseUrl: string, obj: any): string {
   return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters;
 }
 
+// 深度合并
 export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
   let key: string;
   for (key in target) {

+ 1 - 0
Vben2/src/views/demo/system/account/index.vue

@@ -24,6 +24,7 @@
               tooltip: '删除此账号',
               popConfirm: {
                 title: '是否确认删除',
+                placement: 'left',
                 confirm: handleDelete.bind(null, record),
               },
             },

+ 1 - 0
Vben2/src/views/demo/system/dept/index.vue

@@ -16,6 +16,7 @@
               color: 'error',
               popConfirm: {
                 title: '是否确认删除',
+                placement: 'left',
                 confirm: handleDelete.bind(null, record),
               },
             },

+ 1 - 0
Vben2/src/views/demo/system/menu/index.vue

@@ -16,6 +16,7 @@
               color: 'error',
               popConfirm: {
                 title: '是否确认删除',
+                placement: 'left',
                 confirm: handleDelete.bind(null, record),
               },
             },

+ 1 - 0
Vben2/src/views/demo/system/role/index.vue

@@ -16,6 +16,7 @@
               color: 'error',
               popConfirm: {
                 title: '是否确认删除',
+                placement: 'left',
                 confirm: handleDelete.bind(null, record),
               },
             },

+ 7 - 7
Vben2/src/views/demo/tree/index.vue

@@ -59,7 +59,8 @@
   import { treeData } from './data';
   import { PageWrapper } from '/@/components/Page';
   import { Card, Row, Col, Spin } from 'ant-design-vue';
-  import { cloneDeep } from 'lodash-es';
+  import { cloneDeep, uniq } from 'lodash-es';
+  import { isArray } from '/@/utils/is';
 
   export default defineComponent({
     components: { BasicTree, PageWrapper, Card, Row, Col, Spin },
@@ -107,7 +108,7 @@
 
       function onLoadData(treeNode) {
         return new Promise((resolve: (value?: unknown) => void) => {
-          if (!treeNode.children) {
+          if (isArray(treeNode.children) && treeNode.children.length > 0) {
             resolve();
             return;
           }
@@ -119,15 +120,14 @@
                 { title: `Child Node ${treeNode.eventKey}-1`, key: `${treeNode.eventKey}-1` },
               ];
               asyncTreeAction.updateNodeByKey(treeNode.eventKey, { children: nodeChildren });
-              asyncTreeAction.setExpandedKeys([
-                treeNode.eventKey,
-                ...asyncTreeAction.getExpandedKeys(),
-              ]);
+              asyncTreeAction.setExpandedKeys(
+                uniq([treeNode.eventKey, ...asyncTreeAction.getExpandedKeys()]),
+              );
             }
 
             resolve();
             return;
-          }, 1000);
+          }, 300);
         });
       }
       return {

+ 1 - 0
Vben2/types/config.d.ts

@@ -16,6 +16,7 @@ export interface MenuSetting {
   bgColor: string;
   fixed: boolean;
   collapsed: boolean;
+  siderHidden: boolean;
   canDrag: boolean;
   show: boolean;
   hidden: boolean;

+ 8 - 13
doc/Vben2前端框架修改记录.txt

@@ -48,27 +48,22 @@ src/components/Upload/src/UploadPreviewModal.vue
 src/components/Upload/src/props.ts	
 8、全局组件注册修改
 src/components/registerGlobComp.ts
-9、隐藏顶部消息通知、中英文切换、
+9、隐藏顶部消息通知、中英文切换、文档菜单、增加密码修改
 src\layouts\default\header\index.vue
-10、隐藏顶部用户下面的文档菜单
 src\layouts\default\header\components\user-dropdown\index.vue
-11、Tree组件添加滚动条
-src\components\Tree\src\Tree.vue
-12、改成中文
+10、改成中文
 Vben2/index.html	
-13、去掉时间戳
-\src\utils\http\axios
-14、解决表格设置不加载列名选项的问题
+11、解决表格设置不加载列名选项的问题
 /src/components/Table/src/components/settings/ColumnSetting.vue 
-15、增加注册常量下拉框
+12、增加注册常量下拉框
 Vben2/src/main.ts	
-16、增加缓存所有常量下拉框数据
+13、增加缓存所有常量下拉框数据
 Vben2/src/router/guard/permissionGuard.ts	
-17、增加获取所有常量下拉框
+14、增加获取所有常量下拉框
 Vben2/src/store/modules/user.ts	
-18、增加常量下拉框帮助类
+15、增加常量下拉框帮助类
 Vben2/src/utils/helper/constSelectorHelper.ts	
-19、增加登录滑动验证
+16、增加登录滑动验证
 Vben2/src/views/sys/login/LoginForm.vue