Browse Source

!131 ♥️发布 vue 版本 5.2.1 与 cloud 版本 2.2.0
Merge pull request !131 from 疯狂的狮子Li/dev

疯狂的狮子Li 4 months ago
parent
commit
ba24afce52

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "ruoyi-vue-plus",
-  "version": "5.2.0",
+  "version": "5.2.1",
   "description": "RuoYi-Vue-Plus多租户管理系统",
   "author": "LionLi",
   "license": "MIT",

+ 1 - 1
src/api/workflow/formManage/index.ts

@@ -25,7 +25,7 @@ export const listFormManage = (query?: FormManageQuery): AxiosPromise<FormManage
 export const selectListFormManage = (): AxiosPromise<FormManageVO[]> => {
   return request({
     url: '/workflow/formManage/list/selectList',
-    method: 'get',
+    method: 'get'
   });
 };
 

+ 2 - 2
src/api/workflow/formManage/types.ts

@@ -26,7 +26,7 @@ export interface FormManageVO {
   /**
    * 备注
    */
-  remork: string;
+  remark: string;
 }
 
 export interface FormManageForm extends BaseEntity {
@@ -53,7 +53,7 @@ export interface FormManageForm extends BaseEntity {
   /**
    * 备注
    */
-  remork?: string;
+  remark?: string;
 }
 
 export interface FormManageQuery extends PageQuery {

+ 2 - 2
src/api/workflow/model/index.ts

@@ -22,7 +22,7 @@ export const listModel = (query: ModelQuery): AxiosPromise<ModelVO[]> => {
  */
 export const getInfo = (id: string): AxiosPromise<ModelForm> => {
   return request({
-    url: '/workflow/model/getInfo/'+id,
+    url: '/workflow/model/getInfo/' + id,
     method: 'get'
   });
 };
@@ -101,4 +101,4 @@ export const copyModel = (data: ModelForm): AxiosPromise<void> => {
     method: 'post',
     data: data
   });
-};
+};

+ 3 - 3
src/api/workflow/model/types.ts

@@ -1,10 +1,10 @@
 export interface ModelForm {
-  id: string,
+  id: string;
   name: string;
   key: string;
   categoryCode: string;
-  xml:string,
-  svg:string,
+  xml: string;
+  svg: string;
   description: string;
 }
 

+ 0 - 5
src/api/workflow/nodeConfig/types.ts

@@ -35,9 +35,4 @@ export interface NodeConfigVO {
    * 表单管理
    */
   wfFormManageVo: FormManageVO;
-
 }
-
-
-
-

+ 1 - 1
src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts

@@ -40,7 +40,7 @@ class CustomContextPadProvider extends ContextPadProvider {
     rules: Rules,
     translate
   ) {
-    // @ts-ignore
+    // @ts-expect-error 忽略异常
     super(config, injector, eventBus, contextPad, modeling, elementFactory, connect, create, popupMenu, canvas, rules, translate);
 
     this._contextPad = contextPad;

+ 1 - 1
src/components/Editor/index.vue

@@ -110,7 +110,7 @@ watch(
   () => props.modelValue,
   (v: string) => {
     if (v !== content.value) {
-      content.value = v === undefined ? '<p></p>' : v;
+      content.value = v || '<p></p>';
     }
   },
   { immediate: true }

+ 1 - 1
src/components/ImagePreview/index.vue

@@ -38,7 +38,7 @@ const realSrcList = computed(() => {
   let real_src_list = props.src.split(',');
   let srcList: string[] = [];
   real_src_list.forEach((item: string) => {
-    if(item.trim() === '') {
+    if (item.trim() === '') {
       return;
     }
     return srcList.push(item);

+ 1 - 1
src/components/Process/multiInstanceUser.vue

@@ -128,7 +128,7 @@ const props = defineProps({
   //回显用户id
   userIdList: {
     type: Array,
-    default: []
+    default: () => []
   }
 });
 const deptTreeRef = ref(ElTree);

+ 1 - 1
src/components/Process/submitVerify.vue

@@ -106,7 +106,7 @@ const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>();
 const props = defineProps({
   taskVariables: {
     type: Object as () => Record<string, any>,
-    default: {}
+    default: () => {}
   }
 });
 //遮罩层

+ 9 - 17
src/components/UserSelect/index.vue

@@ -29,16 +29,11 @@
                     <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
                   </el-form-item>
                   <el-form-item label="手机号码" prop="phonenumber">
-                    <el-input
-                      v-model="queryParams.phonenumber"
-                      placeholder="请输入手机号码"
-                      clearable
-                      @keyup.enter="handleQuery"
-                    />
+                    <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
                   </el-form-item>
                   <el-form-item>
                     <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-                    <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+                    <el-button icon="Refresh" @click="() => resetQuery()">重置</el-button>
                   </el-form-item>
                 </el-form>
               </el-card>
@@ -223,13 +218,13 @@ const handleQuery = () => {
   getList();
 };
 /** 重置按钮操作 */
-const resetQuery = () => {
+const resetQuery = (refresh = true) => {
   dateRange.value = ['', ''];
   queryFormRef.value?.resetFields();
   queryParams.value.pageNum = 1;
   queryParams.value.deptId = undefined;
   deptTreeRef.value?.setCurrentKey(undefined);
-  handleQuery();
+  refresh && handleQuery();
 };
 
 const handleCheckboxChange = (checked) => {
@@ -288,23 +283,20 @@ const close = () => {
 
 watch(
   () => userDialog.visible.value,
-  (newValue: boolean) => {
+  async (newValue: boolean) => {
     if (newValue) {
-      initSelectUser();
+      await getTreeSelect(); // 初始化部门数据
+      await getList(); // 初始化列表数据
+      await initSelectUser();
     } else {
       tableRef.value.clearCheckboxReserve();
       tableRef.value.clearCheckboxRow();
-      resetQuery();
+      resetQuery(false);
       selectUserList.value = [];
     }
   }
 );
 
-onMounted(() => {
-  getTreeSelect(); // 初始化部门数据
-  getList(); // 初始化列表数据
-});
-
 defineExpose({
   open: userDialog.openDialog,
   close: userDialog.closeDialog

+ 1 - 1
src/hooks/useDialog.ts

@@ -28,4 +28,4 @@ export default (ops?: Options): Return => {
     openDialog,
     closeDialog
   };
-};
+};

+ 7 - 7
src/layout/components/AppMain.vue

@@ -1,13 +1,13 @@
 <template>
   <section class="app-main">
     <router-view v-slot="{ Component, route }">
-      <transition :enter-active-class="animante" mode="out-in">
-        <div>
-          <keep-alive :include="tagsViewStore.cachedViews" v-if="!route.meta.noCache">
-            <component v-if="!route.meta.link" :is="Component" :key="route.path" />
-          </keep-alive>
-          <component v-if="!route.meta.link && route.meta.noCache" :is="Component" :key="route.path" />
-        </div>
+      <transition v-if="!route.meta.noCache" :enter-active-class="animante" mode="out-in">
+        <keep-alive v-if="!route.meta.noCache" :include="tagsViewStore.cachedViews">
+          <component :is="Component" v-if="!route.meta.link" :key="route.path" />
+        </keep-alive>
+      </transition>
+      <transition v-if="route.meta.noCache" :enter-active-class="animante" mode="out-in">
+        <component :is="Component" v-if="!route.meta.link && route.meta.noCache" :key="route.path" />
       </transition>
     </router-view>
     <iframe-toggle />

+ 1 - 1
src/layout/components/SocialCallback/index.vue

@@ -18,7 +18,7 @@ const code = route.query.code as string;
 const state = route.query.state as string;
 const source = route.query.source as string;
 const stateJson = JSON.parse(atob(state));
-const tenantId = stateJson.tenantId as string ? stateJson.tenantId as string : '000000';
+const tenantId = (stateJson.tenantId as string) ? (stateJson.tenantId as string) : '000000';
 const domain = stateJson.domain as string;
 
 const processResponse = async (res: any) => {

+ 1 - 1
src/permission.ts

@@ -53,7 +53,7 @@ router.beforeEach(async (to, from, next) => {
       next();
     } else {
       const redirect = encodeURIComponent(to.fullPath || '/');
-      next(`/login?redirect=${redirect}`) // 否则全部重定向到登录页
+      next(`/login?redirect=${redirect}`); // 否则全部重定向到登录页
       NProgress.done();
     }
   }

+ 51 - 3
src/store/modules/permission.ts

@@ -9,6 +9,8 @@ import Layout from '@/layout/index.vue';
 import ParentView from '@/components/ParentView/index.vue';
 import InnerLink from '@/layout/components/InnerLink/index.vue';
 
+import { createCustomNameComponent } from '@/utils/createCustomNameComponent';
+
 // 匹配views里面所有的.vue文件
 const modules = import.meta.glob('./../../views/**/*.vue');
 export const usePermissionStore = defineStore('permission', () => {
@@ -58,6 +60,8 @@ export const usePermissionStore = defineStore('permission', () => {
     setSidebarRouters(constantRoutes.concat(sidebarRoutes));
     setDefaultRoutes(sidebarRoutes);
     setTopbarRoutes(defaultRoutes);
+    // 路由name重复检查
+    duplicateRouteChecker(asyncRoutes, sidebarRoutes);
     return new Promise<RouteRecordRaw[]>((resolve) => resolve(rewriteRoutes));
   };
 
@@ -80,7 +84,7 @@ export const usePermissionStore = defineStore('permission', () => {
       } else if (route.component?.toString() === 'InnerLink') {
         route.component = InnerLink;
       } else {
-        route.component = loadView(route.component);
+        route.component = loadView(route.component, route.name as string);
       }
       if (route.children != null && route.children && route.children.length) {
         route.children = filterAsyncRouter(route.children, route, type);
@@ -151,12 +155,12 @@ export const filterDynamicRoutes = (routes: RouteRecordRaw[]) => {
   return res;
 };
 
-export const loadView = (view: any) => {
+export const loadView = (view: any, name: string) => {
   let res;
   for (const path in modules) {
     const dir = path.split('views/')[1].split('.vue')[0];
     if (dir === view) {
-      res = () => modules[path]();
+      res = createCustomNameComponent(modules[path], { name });
     }
   }
   return res;
@@ -167,4 +171,48 @@ export const usePermissionStoreHook = () => {
   return usePermissionStore(store);
 };
 
+interface Route {
+  name?: string | symbol;
+  path: string;
+  children?: Route[];
+}
+
+/**
+ * 检查路由name是否重复
+ * @param localRoutes 本地路由
+ * @param routes 动态路由
+ */
+function duplicateRouteChecker(localRoutes: Route[], routes: Route[]) {
+  // 展平
+  function flatRoutes(routes: Route[]) {
+    const res: Route[] = [];
+    routes.forEach((route) => {
+      if (route.children) {
+        res.push(...flatRoutes(route.children));
+      } else {
+        res.push(route);
+      }
+    });
+    return res;
+  }
+
+  const allRoutes = flatRoutes([...localRoutes, ...routes]);
+
+  const nameList: string[] = [];
+  allRoutes.forEach((route) => {
+    const name = route.name.toString();
+    if (name && nameList.includes(name)) {
+      const message = `路由名称: [${name}] 重复, 会造成 404`;
+      console.error(message);
+      ElNotification({
+        title: '路由名称重复',
+        message,
+        type: 'error'
+      });
+      return;
+    }
+    nameList.push(route.name.toString());
+  });
+}
+
 export default usePermissionStore;

+ 39 - 0
src/utils/createCustomNameComponent.tsx

@@ -0,0 +1,39 @@
+/**
+ * 后台返回的路由动态生成name 解决缓存问题
+ * 感谢 @fourteendp
+ * 详见 https://github.com/vbenjs/vue-vben-admin/issues/3927
+ */
+import { Component, defineComponent, h } from 'vue';
+
+interface Options {
+  name?: string;
+}
+
+export function createCustomNameComponent(loader: () => Promise<any>, options: Options = {}): () => Promise<Component> {
+  const { name } = options;
+  let component: Component | null = null;
+
+  const load = async () => {
+    try {
+      const { default: loadedComponent } = await loader();
+      component = loadedComponent;
+    } catch (error) {
+      console.error(`Cannot resolve component ${name}, error:`, error);
+    }
+  };
+
+  return async () => {
+    if (!component) {
+      await load();
+    }
+
+    return Promise.resolve(
+      defineComponent({
+        name,
+        render() {
+          return h(component as Component);
+        }
+      })
+    );
+  };
+}

+ 1 - 1
src/views/index.vue

@@ -33,7 +33,7 @@
           * 部署方式 Docker 容器编排 一键部署业务集群<br />
           * 国际化 SpringMessage Spring标准国际化方案<br />
         </p>
-        <p><b>当前版本:</b> <span>v5.2.0</span></p>
+        <p><b>当前版本:</b> <span>v5.2.1</span></p>
         <p>
           <el-tag type="danger">&yen;免费开源</el-tag>
         </p>

+ 1 - 1
src/views/monitor/logininfor/index.vue

@@ -11,7 +11,7 @@
               <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="登录状态" clearable >
+              <el-select v-model="queryParams.status" placeholder="登录状态" clearable>
                 <el-option v-for="dict in sys_common_status" :key="dict.value" :label="dict.label" :value="dict.value" />
               </el-select>
             </el-form-item>

+ 2 - 2
src/views/monitor/operlog/index.vue

@@ -14,12 +14,12 @@
               <el-input v-model="queryParams.operName" placeholder="请输入操作人员" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="类型" prop="businessType">
-              <el-select v-model="queryParams.businessType" placeholder="操作类型" clearable >
+              <el-select v-model="queryParams.businessType" placeholder="操作类型" clearable>
                 <el-option v-for="dict in sys_oper_type" :key="dict.value" :label="dict.label" :value="dict.value" />
               </el-select>
             </el-form-item>
             <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="操作状态" clearable >
+              <el-select v-model="queryParams.status" placeholder="操作状态" clearable>
                 <el-option v-for="dict in sys_common_status" :key="dict.value" :label="dict.label" :value="dict.value" />
               </el-select>
             </el-form-item>

+ 1 - 1
src/views/system/client/index.vue

@@ -10,7 +10,7 @@
             <el-input v-model="queryParams.clientSecret" placeholder="请输入客户端秘钥" clearable @keyup.enter="handleQuery" />
           </el-form-item>
           <el-form-item label="状态" prop="status">
-            <el-select v-model="queryParams.status" placeholder="状态" clearable >
+            <el-select v-model="queryParams.status" placeholder="状态" clearable>
               <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
             </el-select>
           </el-form-item>

+ 1 - 1
src/views/system/config/index.vue

@@ -11,7 +11,7 @@
               <el-input v-model="queryParams.configKey" placeholder="请输入参数键名" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="系统内置" prop="configType">
-              <el-select v-model="queryParams.configType" placeholder="系统内置" clearable >
+              <el-select v-model="queryParams.configType" placeholder="系统内置" clearable>
                 <el-option v-for="dict in sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" />
               </el-select>
             </el-form-item>

+ 1 - 1
src/views/system/dept/index.vue

@@ -11,7 +11,7 @@
               <el-input v-model="queryParams.deptCategory" placeholder="请输入类别编码" clearable style="width: 240px" @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="部门状态" clearable >
+              <el-select v-model="queryParams.status" placeholder="部门状态" clearable>
                 <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
               </el-select>
             </el-form-item>

+ 1 - 1
src/views/system/menu/index.vue

@@ -8,7 +8,7 @@
               <el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="菜单状态" clearable >
+              <el-select v-model="queryParams.status" placeholder="菜单状态" clearable>
                 <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
               </el-select>
             </el-form-item>

+ 3 - 3
src/views/system/oss/index.vue

@@ -13,7 +13,7 @@
             <el-form-item label="文件后缀" prop="fileSuffix">
               <el-input v-model="queryParams.fileSuffix" placeholder="请输入文件后缀" clearable @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="创建时间" style="width: 308px;">
+            <el-form-item label="创建时间" style="width: 308px">
               <el-date-picker
                 v-model="dateRangeCreateTime"
                 value-format="YYYY-MM-DD HH:mm:ss"
@@ -198,9 +198,9 @@ const getList = async () => {
   showTable.value = true;
 };
 function checkFileSuffix(fileSuffix: string | string[]) {
-  const arr = [".png", ".jpg", ".jpeg"];
+  const arr = ['.png', '.jpg', '.jpeg'];
   const suffixArray = Array.isArray(fileSuffix) ? fileSuffix : [fileSuffix];
-  return suffixArray.some(suffix => arr.includes(suffix.toLowerCase()));
+  return suffixArray.some((suffix) => arr.includes(suffix.toLowerCase()));
 }
 /** 取消按钮 */
 function cancel() {

+ 1 - 1
src/views/system/role/index.vue

@@ -11,7 +11,7 @@
               <el-input v-model="queryParams.roleKey" placeholder="请输入权限字符" clearable @keyup.enter="handleQuery" />
             </el-form-item>
             <el-form-item label="状态" prop="status">
-              <el-select v-model="queryParams.status" placeholder="角色状态" clearable >
+              <el-select v-model="queryParams.status" placeholder="角色状态" clearable>
                 <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
               </el-select>
             </el-form-item>

+ 3 - 3
src/views/system/user/profile/index.vue

@@ -58,8 +58,8 @@
             <el-tab-pane label="第三方应用" name="thirdParty">
               <thirdParty :auths="state.auths" />
             </el-tab-pane>
-            <el-tab-pane label="在线设备" name="onlinDevice">
-              <onlinDevice :devices="state.devices" />
+            <el-tab-pane label="在线设备" name="onlineDevice">
+              <onlineDevice :devices="state.devices" />
             </el-tab-pane>
           </el-tabs>
         </el-card>
@@ -73,7 +73,7 @@ import UserAvatar from './userAvatar.vue';
 import UserInfo from './userInfo.vue';
 import ResetPwd from './resetPwd.vue';
 import ThirdParty from './thirdParty.vue';
-import OnlinDevice from './onlineDevice.vue';
+import OnlineDevice from './onlineDevice.vue';
 import { getAuthList } from '@/api/system/social/auth';
 import { getUserProfile } from '@/api/system/user';
 import { getOnline } from '@/api/monitor/online';

+ 1 - 3
src/views/system/user/profile/onlineDevice.vue

@@ -18,8 +18,7 @@
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template #default="scope">
           <el-tooltip content="删除" placement="top">
-            <el-button link type="primary" icon="Delete" @click="handldDelOnline(scope.row)">
-            </el-button>
+            <el-button link type="primary" icon="Delete" @click="handldDelOnline(scope.row)"> </el-button>
           </el-tooltip>
         </template>
       </el-table-column>
@@ -55,5 +54,4 @@ const handldDelOnline = (row: any) => {
     })
     .catch(() => {});
 };
-
 </script>

+ 1 - 1
src/views/system/user/profile/resetPwd.vue

@@ -45,7 +45,7 @@ const rules = ref({
       message: '长度在 6 到 20 个字符',
       trigger: 'blur'
     },
-    { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
+    { pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\\ |', trigger: 'blur' }
   ],
   confirmPassword: [
     { required: true, message: '确认密码不能为空', trigger: 'blur' },

+ 1 - 1
src/views/system/user/profile/thirdParty.vue

@@ -58,7 +58,7 @@
 <script lang="ts" setup>
 import { authUnlock, authBinding } from '@/api/system/social/auth';
 import { propTypes } from '@/utils/propTypes';
-import useUserStore from "@/store/modules/user";
+import useUserStore from '@/store/modules/user';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 

+ 4 - 4
src/views/workflow/formManage/index.vue

@@ -46,7 +46,7 @@
           </template>
         </el-table-column>
         <el-table-column label="地址" align="center" prop="router" />
-        <el-table-column label="备注" align="center" prop="remork" />
+        <el-table-column label="备注" align="center" prop="remark" />
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
             <el-tooltip content="修改" placement="top">
@@ -82,8 +82,8 @@
             </template>
           </el-input>
         </el-form-item>
-        <el-form-item label="备注" prop="remork">
-          <el-input v-model="form.remork" type="textarea" placeholder="请输入内容" />
+        <el-form-item label="备注" prop="remark">
+          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
         </el-form-item>
       </el-form>
       <template #footer>
@@ -123,7 +123,7 @@ const initFormData: FormManageForm = {
   id: undefined,
   formName: undefined,
   formType: 'static',
-  remork: undefined
+  remark: undefined
 };
 const data = reactive<PageData<FormManageForm, FormManageQuery>>({
   form: { ...initFormData },