Compare commits

...
Author SHA1 Message Date
疯狂的狮子Li 9a02598c00 !151 发布 vue 版本 5.2.3 与 cloud 版本 2.2.2
Merge pull request !151 from 疯狂的狮子Li/dev
2024-10-25 03:13:13 +00:00
疯狂的狮子Li 28a81f2e44 🎀发布 vue 版本 5.2.3 与 cloud 版本 2.2.2 2024-10-25 11:04:05 +08:00
疯狂的狮子Li 6f4891d677 update 优化 流程提交用户id使用字符串提交避免雪花id失真问题 2024-10-17 18:15:18 +08:00
疯狂的狮子Li a62a3de23c fix 修复 pr!150 sse开关缺少变量问题 2024-10-15 13:49:32 +08:00
疯狂的狮子Li 1d852da351 !150 增加SEE开关
Merge pull request !150 from iqitao/ss
2024-10-15 05:47:39 +00:00
陈西瓜i f0895e9419 add 增加注解 2024-10-14 20:50:20 +08:00
陈西瓜i 1644070e97 add SSE开关 2024-10-14 20:33:16 +08:00
疯狂的狮子Li 4918552492 fix 修复 请假日期选择格式不对问题 2024-10-12 10:58:32 +08:00
疯狂的狮子Li 364dfb969d update 优化代码 2024-10-07 10:45:25 +08:00
疯狂的狮子Li 9726df3966 fix 修复 登录日志excel导出名称错误 2024-09-18 09:42:24 +08:00
疯狂的狮子Li 483af13741 fix 修复 重新登录无法跳转到过期前页面问题 2024-09-06 18:06:16 +08:00
疯狂的狮子Li 25848ea99e fix 修复 重新登录无法跳转到过期前页面问题 2024-09-06 17:58:28 +08:00
疯狂的狮子Li 9f13c29cd7 update 优化 代码生成菜单id匹配写法 2024-09-04 16:16:46 +08:00
疯狂的狮子Li e1860a30fc fix 修复 租户套餐导出路径编写错误
Signed-off-by: 疯狂的狮子Li <15040126243@163.com>
2024-08-26 12:29:29 +00:00
疯狂的狮子Li 34b929d352 add 增加 同步租户字典功能 2024-08-26 17:56:35 +08:00
疯狂的狮子Li 1606dbd76f !141 发布 vue 版本 5.2.2 与 cloud 版本 2.2.1
Merge pull request !141 from 疯狂的狮子Li/dev
2024-08-26 03:45:16 +00:00
疯狂的狮子Li 3c2d9100b5 😴发布 vue 版本 5.2.2 与 cloud 版本 2.2.1 2024-08-26 11:40:53 +08:00
疯狂的狮子Li 2c8873402f update 优化 使用匹配模式简化预编译配置 2024-08-16 13:01:54 +08:00
疯狂的狮子Li e5727893bb update 优化 时间搜索组件统一 2024-08-15 20:42:29 +08:00
疯狂的狮子Li 335a1e6019 update 优化 oss 配置按钮 使用ossConfig权限标识符与oss权限分离 2024-08-08 18:19:58 +08:00
疯狂的狮子Li c0ee3182e1 fix 修复 租户套餐导出路径错误问题 2024-08-08 18:19:18 +08:00
疯狂的狮子Li 9eb7b433b4 update 优化 类型报错问题 2024-08-02 13:53:48 +08:00
疯狂的狮子Li 9193f0b84a update 优化 切换租户后刷新首页 2024-08-02 09:59:14 +08:00
疯狂的狮子Li 076fc5deb1 update 优化 实现表格行选中切换 2024-08-02 09:55:51 +08:00
疯狂的狮子Li 58412035ad update 优化 使用 vueuse 重构 websocket 实现 2024-07-29 15:02:59 +08:00
疯狂的狮子Li 964db2dfce update 优化 使用 vueuse 重构 websocket 实现 2024-07-29 15:02:41 +08:00
疯狂的狮子Li d58a75996e fix 修复 登出后重新登录 sse推送报错问题 2024-07-29 12:34:32 +08:00
疯狂的狮子Li f5a5aaa255 reset 回滚 代码修改 采用其他方案 2024-07-29 12:32:05 +08:00
疯狂的狮子Li 1465a27a6e fix 修复 登出后重新登录 sse推送报错问题 2024-07-29 12:29:25 +08:00
疯狂的狮子Li e5e43fe024 update 优化 删除无用代码 2024-07-27 22:10:22 +08:00
疯狂的狮子Li 6c49b47344 update element-plus 2.7.5 => 2.7.8
update vue 3.4.25 => 3.4.34
update vite 5.2.10 => 5.2.12
2024-07-27 15:08:13 +08:00
疯狂的狮子Li 358f11a0a3 reset 回滚 错误修复 2024-07-27 15:07:33 +08:00
疯狂的狮子Li 6a83ed2aad update 优化 代码生成器编辑页禁用缓存 防止同步后页面不更新问题 2024-07-27 14:15:19 +08:00
疯狂的狮子Li e07c0b2b3a fix 修复 代码生成同步点击取消报错问题 2024-07-27 14:08:07 +08:00
疯狂的狮子Li adadfcf8cb update 优化 调整默认推送使用SSE 2024-07-26 16:24:40 +08:00
疯狂的狮子Li 425386f6f4 add 增加 sse 推送功能 2024-07-26 16:06:17 +08:00
疯狂的狮子Li ba24afce52 !131 ♥️发布 vue 版本 5.2.1 与 cloud 版本 2.2.0
Merge pull request !131 from 疯狂的狮子Li/dev
2024-07-09 03:02:34 +00:00
疯狂的狮子Li 93d3371768 ♥️发布 vue 版本 5.2.1 与 cloud 版本 2.2.0 2024-07-09 10:53:49 +08:00
疯狂的狮子Li 3f08ae6ac4 fix 修复 富文本编辑器 添加之后内容未清理问题 2024-07-02 16:51:03 +08:00
疯狂的狮子Li cc6284d3ac fix 修复 字段命名错误 2024-07-01 12:52:19 +08:00
疯狂的狮子Li 142effd4f2 !130 feat: 动态创建组件实例时, 设置路由name为组件名 解决缓存问题
Merge pull request !130 from 玲娜贝er/dev
2024-06-30 08:13:16 +00:00
dap e657a507e3 feat: 动态创建组件实例时, 设置路由name为组件名 解决缓存问题 2024-06-30 10:50:04 +08:00
疯狂的狮子Li ebaec24213 update 优化 eslint 2024-06-28 10:44:13 +08:00
疯狂的狮子Li 7637582437 update 优化 eslint 2024-06-28 10:18:26 +08:00
疯狂的狮子Li 27d36f7970 !129 feat: 路由name重复检查
Merge pull request !129 from 玲娜贝er/dev
2024-06-26 04:02:28 +00:00
dap 762ebd4ede chore: 增加提示 2024-06-26 11:59:41 +08:00
dap ad991e248a feat: 路由name重复检查 2024-06-26 11:34:40 +08:00
疯狂的狮子Li d1b58f0aaa fix 修复 单词拼写错误 2024-06-24 14:59:46 +08:00
疯狂的狮子Li 1be1eaf7b4 !128 fix: 选人无法回显
Merge pull request !128 from 玲娜贝er/dev
2024-06-24 00:37:32 +00:00
dap fbcc967b14 fix: 由于没有await 导致执行顺序不可控 2024-06-24 08:21:19 +08:00
疯狂的狮子Li 817c65f7e2 !126 fix: 进入审批页面会多次加载用户列表和部门等接口 进入点击取消之后也会重新加载接口
Merge pull request !126 from 玲娜贝er/dev
2024-06-21 04:31:25 +00:00
张代鹏 b6dcc62f9c refactor: 改为懒加载窗口 2024-06-21 12:07:19 +08:00
55 changed files with 318 additions and 359 deletions
+5 -2
View File
@@ -28,5 +28,8 @@ VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3C
# 客户端id
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
# websocket 开关
VITE_APP_WEBSOCKET = true
# websocket 开关 默认使用sse推送
VITE_APP_WEBSOCKET = false
# sse 开关
VITE_APP_SSE = true
+5 -2
View File
@@ -31,5 +31,8 @@ VITE_APP_RSA_PRIVATE_KEY = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3C
# 客户端id
VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e'
# websocket 开关
VITE_APP_WEBSOCKET = true
# websocket 开关 默认使用sse推送
VITE_APP_WEBSOCKET = false
# sse 开关
VITE_APP_SSE = true
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "ruoyi-vue-plus",
"version": "5.2.0",
"version": "5.2.3",
"description": "RuoYi-Vue-Plus多租户管理系统",
"author": "LionLi",
"license": "MIT",
@@ -30,7 +30,7 @@
"diagram-js": "12.3.0",
"didi": "9.0.2",
"echarts": "5.5.0",
"element-plus": "2.7.5",
"element-plus": "2.7.8",
"file-saver": "2.0.5",
"fuse.js": "7.0.0",
"highlight.js": "11.9.0",
@@ -40,7 +40,7 @@
"nprogress": "0.2.0",
"pinia": "2.1.7",
"screenfull": "6.0.2",
"vue": "3.4.25",
"vue": "3.4.34",
"vue-cropper": "1.1.1",
"vue-i18n": "9.10.2",
"vue-router": "4.3.2",
@@ -81,7 +81,7 @@
"unplugin-icons": "0.18.5",
"unplugin-vue-components": "0.26.0",
"unplugin-vue-setup-extend-plus": "1.0.1",
"vite": "5.2.10",
"vite": "5.2.12",
"vite-plugin-compression": "0.5.1",
"vite-plugin-svg-icons": "2.0.1",
"vitest": "1.5.0",
+4
View File
@@ -51,6 +51,10 @@ export function register(data: any) {
* 注销
*/
export function logout() {
request({
url: '/resource/sse/close',
method: 'get'
});
return request({
url: '/auth/logout',
method: 'post'
+8
View File
@@ -91,3 +91,11 @@ export function syncTenantPackage(tenantId: string | number, packageId: string |
params: data
});
}
// 同步租户字典
export function syncTenantDict() {
return request({
url: '/system/tenant/syncTenantDict',
method: 'get',
});
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
-63
View File
@@ -1,63 +0,0 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { NodeConfigVO, NodeConfigForm, NodeConfigQuery } from '@/api/workflow/nodeConfig/types';
/**
* 查询节点配置列表
* @param query
* @returns {*}
*/
export const listNodeConfig = (query?: NodeConfigQuery): AxiosPromise<NodeConfigVO[]> => {
return request({
url: '/workflow/nodeConfig/list',
method: 'get',
params: query
});
};
/**
* 查询节点配置详细
* @param id
*/
export const getNodeConfig = (id: string | number): AxiosPromise<NodeConfigVO> => {
return request({
url: '/workflow/nodeConfig/' + id,
method: 'get'
});
};
/**
* 新增节点配置
* @param data
*/
export const addNodeConfig = (data: NodeConfigForm) => {
return request({
url: '/workflow/nodeConfig',
method: 'post',
data: data
});
};
/**
* 修改节点配置
* @param data
*/
export const updateNodeConfig = (data: NodeConfigForm) => {
return request({
url: '/workflow/nodeConfig',
method: 'put',
data: data
});
};
/**
* 删除节点配置
* @param id
*/
export const delNodeConfig = (id: string | number | Array<string | number>) => {
return request({
url: '/workflow/nodeConfig/' + id,
method: 'delete'
});
};
-5
View File
@@ -35,9 +35,4 @@ export interface NodeConfigVO {
* 表单管理
*/
wfFormManageVo: FormManageVO;
}
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -128,7 +128,7 @@ const props = defineProps({
//回显用户id
userIdList: {
type: Array,
default: []
default: () => []
}
});
const deptTreeRef = ref(ElTree);
+1 -1
View File
@@ -106,7 +106,7 @@ const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>();
const props = defineProps({
taskVariables: {
type: Object as () => Record<string, any>,
default: {}
default: () => {}
}
});
//遮罩层
+9 -17
View File
@@ -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
View File
@@ -28,4 +28,4 @@ export default (ops?: Options): Return => {
openDialog,
closeDialog
};
};
};
+7 -7
View File
@@ -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 />
+2
View File
@@ -128,6 +128,7 @@ const dynamicTenantEvent = async (tenantId: string) => {
dynamic.value = true;
proxy?.$tab.closeAllPage();
proxy?.$router.push('/');
proxy?.$tab.refreshPage();
}
};
@@ -136,6 +137,7 @@ const dynamicClearEvent = async () => {
dynamic.value = false;
proxy?.$tab.closeAllPage();
proxy?.$router.push('/');
proxy?.$tab.refreshPage();
};
/** 租户列表 */
@@ -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) => {
+5
View File
@@ -27,6 +27,7 @@ import { AppMain, Navbar, Settings, TagsView } from './components';
import useAppStore from '@/store/modules/app';
import useSettingsStore from '@/store/modules/settings';
import { initWebSocket } from '@/utils/websocket';
import { initSSE } from "@/utils/sse";
const settingsStore = useSettingsStore();
const theme = computed(() => settingsStore.theme);
@@ -71,6 +72,10 @@ onMounted(() => {
initWebSocket(protocol + window.location.host + import.meta.env.VITE_APP_BASE_API + '/resource/websocket');
});
onMounted(() => {
initSSE(import.meta.env.VITE_APP_BASE_API + '/resource/sse');
});
const handleClickOutside = () => {
useAppStore().closeSideBar({ withoutAnimation: false });
};
+2 -1
View File
@@ -40,6 +40,7 @@ router.beforeEach(async (to, from, next) => {
router.addRoute(route); // 动态添加可访问路由表
}
});
// @ts-ignore
next({ path: to.path, replace: true, params: to.params, query: to.query, hash: to.hash, name: to.name as string }); // hack方法 确保addRoutes已完成
}
} else {
@@ -53,7 +54,7 @@ router.beforeEach(async (to, from, next) => {
next();
} else {
const redirect = encodeURIComponent(to.fullPath || '/');
next(`/login?redirect=${redirect}`) // 否则全部重定向到登录页
next(`/login?redirect=${redirect}`); // 否则全部重定向到登录页
NProgress.done();
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
import router from '@/router';
import { RouteLocationMatched, RouteLocationNormalized } from 'vue-router';
import {RouteLocationMatched, RouteLocationNormalized, RouteLocationRaw} from 'vue-router';
import useTagsViewStore from '@/store/modules/tagsView';
export default {
@@ -41,7 +41,7 @@ export default {
});
},
// 关闭当前tab页签,打开新页签
closeOpenPage(obj: RouteLocationNormalized): void {
closeOpenPage(obj: RouteLocationRaw): void {
useTagsViewStore().delView(router.currentRoute.value);
if (obj !== undefined) {
router.push(obj);
+1 -1
View File
@@ -159,7 +159,7 @@ export const dynamicRoutes: RouteRecordRaw[] = [
path: 'index/:tableId(\\d+)',
component: () => import('@/views/tool/gen/editTable.vue'),
name: 'GenEdit',
meta: { title: '修改生成配置', activeMenu: '/tool/gen', icon: '' }
meta: { title: '修改生成配置', activeMenu: '/tool/gen', icon: '', noCache: true }
}
]
},
+54 -6
View File
@@ -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', () => {
@@ -19,13 +21,13 @@ export const usePermissionStore = defineStore('permission', () => {
const sidebarRouters = ref<RouteRecordRaw[]>([]);
const getRoutes = (): RouteRecordRaw[] => {
return routes.value;
return routes.value as RouteRecordRaw[];
};
const getSidebarRoutes = (): RouteRecordRaw[] => {
return sidebarRouters.value;
return sidebarRouters.value as RouteRecordRaw[];
};
const getTopbarRoutes = (): RouteRecordRaw[] => {
return topbarRouters.value;
return topbarRouters.value as RouteRecordRaw[];
};
const setRoutes = (newRoutes: RouteRecordRaw[]): void => {
@@ -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;
+11 -11
View File
@@ -6,10 +6,10 @@ export const useTagsViewStore = defineStore('tagsView', () => {
const iframeViews = ref<RouteLocationNormalized[]>([]);
const getVisitedViews = (): RouteLocationNormalized[] => {
return visitedViews.value;
return visitedViews.value as RouteLocationNormalized[];
};
const getIframeViews = (): RouteLocationNormalized[] => {
return iframeViews.value;
return iframeViews.value as RouteLocationNormalized[];
};
const getCachedViews = (): string[] => {
return cachedViews.value;
@@ -31,7 +31,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
const delIframeView = (view: RouteLocationNormalized): Promise<RouteLocationNormalized[]> => {
return new Promise((resolve) => {
iframeViews.value = iframeViews.value.filter((item: RouteLocationNormalized) => item.path !== view.path);
resolve([...iframeViews.value]);
resolve([...iframeViews.value as RouteLocationNormalized[]]);
});
};
const addVisitedView = (view: RouteLocationNormalized): void => {
@@ -54,7 +54,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
delCachedView(view);
}
resolve({
visitedViews: [...visitedViews.value],
visitedViews: [...visitedViews.value as RouteLocationNormalized[]],
cachedViews: [...cachedViews.value]
});
});
@@ -68,7 +68,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
break;
}
}
resolve([...visitedViews.value]);
resolve([...visitedViews.value as RouteLocationNormalized[]]);
});
};
const delCachedView = (view?: RouteLocationNormalized): Promise<string[]> => {
@@ -92,7 +92,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
delOthersVisitedViews(view);
delOthersCachedViews(view);
resolve({
visitedViews: [...visitedViews.value],
visitedViews: [...visitedViews.value as RouteLocationNormalized[]],
cachedViews: [...cachedViews.value]
});
});
@@ -103,7 +103,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
visitedViews.value = visitedViews.value.filter((v: RouteLocationNormalized) => {
return v.meta?.affix || v.path === view.path;
});
resolve([...visitedViews.value]);
resolve([...visitedViews.value as RouteLocationNormalized[]]);
});
};
const delOthersCachedViews = (view: RouteLocationNormalized): Promise<string[]> => {
@@ -124,7 +124,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
delAllVisitedViews();
delAllCachedViews();
resolve({
visitedViews: [...visitedViews.value],
visitedViews: [...visitedViews.value as RouteLocationNormalized[]],
cachedViews: [...cachedViews.value]
});
});
@@ -132,7 +132,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
const delAllVisitedViews = (): Promise<RouteLocationNormalized[]> => {
return new Promise((resolve) => {
visitedViews.value = visitedViews.value.filter((tag: RouteLocationNormalized) => tag.meta?.affix);
resolve([...visitedViews.value]);
resolve([...visitedViews.value as RouteLocationNormalized[]]);
});
};
@@ -167,7 +167,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
}
return false;
});
resolve([...visitedViews.value]);
resolve([...visitedViews.value as RouteLocationNormalized[]]);
});
};
const delLeftTags = (view: RouteLocationNormalized): Promise<RouteLocationNormalized[]> => {
@@ -186,7 +186,7 @@ export const useTagsViewStore = defineStore('tagsView', () => {
}
return false;
});
resolve([...visitedViews.value]);
resolve([...visitedViews.value as RouteLocationNormalized[]]);
});
};
+1
View File
@@ -19,6 +19,7 @@ interface ImportMetaEnv {
VITE_APP_RSA_PRIVATE_KEY: string;
VITE_APP_CLIENT_ID: string;
VITE_APP_WEBSOCKET: string;
VITE_APP_SSE: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
+39
View File
@@ -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);
}
})
);
};
}
+8 -2
View File
@@ -10,6 +10,7 @@ import FileSaver from 'file-saver';
import { getLanguage } from '@/lang';
import { encryptBase64, encryptWithAes, generateAesKey, decryptWithAes, decryptBase64 } from '@/utils/crypto';
import { encrypt, decrypt } from '@/utils/jsencrypt';
import router from "@/router";
const encryptHeader = 'encrypt-key';
let downloadLoadingInstance: LoadingInstance;
@@ -134,8 +135,13 @@ service.interceptors.response.use(
}).then(() => {
isRelogin.show = false;
useUserStore().logout().then(() => {
location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index';
});
router.replace({
path: '/login',
query: {
redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/')
}
})
});
}).catch(() => {
isRelogin.show = false;
});
+45
View File
@@ -0,0 +1,45 @@
import { getToken } from '@/utils/auth';
import { ElNotification } from 'element-plus';
import useNoticeStore from '@/store/modules/notice';
// 初始化
export const initSSE = (url: any) => {
if (import.meta.env.VITE_APP_SSE === 'false') {
return;
}
url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID
const {
data,
error
} = useEventSource(url, [], {
autoReconnect: {
retries: 10,
delay: 3000,
onFailed() {
console.log('Failed to connect after 10 retries');
}
}
});
watch(error, () => {
console.log('SSE connection error:', error.value);
error.value = null;
});
watch(data, () => {
if (!data.value) return;
useNoticeStore().addNotice({
message: data.value,
read: false,
time: new Date().toLocaleString()
});
ElNotification({
title: '消息',
message: data.value,
type: 'success',
duration: 3000
});
data.value = null;
});
};
+40 -128
View File
@@ -1,139 +1,51 @@
/**
* @module initWebSocket 初始化
* @module websocketonopen 连接成功
* @module websocketonerror 连接失败
* @module websocketclose 断开连接
* @module resetHeart 重置心跳
* @module sendSocketHeart 心跳发送
* @module reconnect 重连
* @module sendMsg 发送数据
* @module websocketonmessage 接收数据
* @module test 测试收到消息传递
* @description socket 通信
* @param {any} url socket地址
* @param {any} websocket websocket 实例
* @param {any} heartTime 心跳定时器实例
* @param {number} socketHeart 心跳次数
* @param {number} HeartTimeOut 心跳超时时间
* @param {number} socketError 错误次数
*/
import { getToken } from '@/utils/auth';
import { ElNotification } from 'element-plus';
import useNoticeStore from '@/store/modules/notice';
let socketUrl: any = ''; // socket地址
let websocket: any = null; // websocket 实例
let heartTime: any = null; // 心跳定时器实例
let socketHeart = 0 as number; // 心跳次数
const HeartTimeOut = 10000; // 心跳超时时间 10000 = 10s
let socketError = 0 as number; // 错误次数
// 初始化socket
export const initWebSocket = (url: any) => {
if (import.meta.env.VITE_APP_WEBSOCKET === 'false') {
return;
}
socketUrl = url;
// 初始化 websocket
websocket = new WebSocket(url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID);
websocketonopen();
websocketonmessage();
websocketonerror();
websocketclose();
sendSocketHeart();
return websocket;
};
// socket 连接成功
export const websocketonopen = () => {
websocket.onopen = function () {
console.log('连接 websocket 成功');
resetHeart();
};
};
// socket 连接失败
export const websocketonerror = () => {
websocket.onerror = function (e: any) {
console.log('连接 websocket 失败', e);
};
};
// socket 断开链接
export const websocketclose = () => {
websocket.onclose = function (e: any) {
console.log('断开连接', e);
};
};
// socket 重置心跳
export const resetHeart = () => {
socketHeart = 0;
socketError = 0;
clearInterval(heartTime);
sendSocketHeart();
};
// socket心跳发送
export const sendSocketHeart = () => {
heartTime = setInterval(() => {
// 如果连接正常则发送心跳
if (websocket.readyState == 1) {
// if (socketHeart <= 30) {
websocket.send(
JSON.stringify({
type: 'ping'
})
);
socketHeart = socketHeart + 1;
} else {
// 重连
reconnect();
url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID
useWebSocket(url, {
autoReconnect: {
// 重连最大次数
retries: 3,
// 重连间隔
delay: 1000,
onFailed() {
console.log('websocket重连失败');
},
},
heartbeat: {
message: JSON.stringify({type: 'ping'}),
// 发送心跳的间隔
interval: 10000,
// 接收到心跳response的超时时间
pongTimeout: 2000,
},
onConnected() {
console.log('websocket已经连接');
},
onDisconnected() {
console.log('websocket已经断开');
},
onMessage: (_, e) => {
if (e.data.indexOf('ping') > 0) {
return;
}
useNoticeStore().addNotice({
message: e.data,
read: false,
time: new Date().toLocaleString()
});
ElNotification({
title: '消息',
message: e.data,
type: 'success',
duration: 3000
});
}
}, HeartTimeOut);
};
// socket重连
export const reconnect = () => {
if (socketError <= 2) {
clearInterval(heartTime);
initWebSocket(socketUrl);
socketError = socketError + 1;
// eslint-disable-next-line prettier/prettier
console.log('socket重连', socketError);
} else {
// eslint-disable-next-line prettier/prettier
console.log('重试次数已用完');
clearInterval(heartTime);
}
};
// socket 发送数据
export const sendMsg = (data: any) => {
websocket.send(data);
};
// socket 接收数据
export const websocketonmessage = () => {
websocket.onmessage = function (e: any) {
if (e.data.indexOf('heartbeat') > 0) {
resetHeart();
}
if (e.data.indexOf('ping') > 0) {
return;
}
useNoticeStore().addNotice({
message: e.data,
read: false,
time: new Date().toLocaleString()
});
ElNotification({
title: '消息',
message: e.data,
type: 'success',
duration: 3000
});
return e.data;
};
});
};
+2 -2
View File
@@ -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.3</span></p>
<p>
<el-tag type="danger">&yen;免费开源</el-tag>
</p>
@@ -77,7 +77,7 @@
* 分布式监控 Prometheus、Grafana 全方位性能监控<br />
* 其余与 Vue 版本一致<br />
</p>
<p><b>当前版本:</b> <span>v2.2.0</span></p>
<p><b>当前版本:</b> <span>v2.2.2</span></p>
<p>
<el-tag type="danger">&yen;免费开源</el-tag>
</p>
+2 -2
View File
@@ -97,7 +97,7 @@ const tenantEnabled = ref(true);
// 注册开关
const register = ref(false);
const redirect = ref(undefined);
const redirect = ref('/');
const loginRef = ref<ElFormInstance>();
// 租户列表
const tenantList = ref<TenantVO[]>([]);
@@ -105,7 +105,7 @@ const tenantList = ref<TenantVO[]>([]);
watch(
() => router.currentRoute.value,
(newRoute: any) => {
redirect.value = newRoute.query && newRoute.query.redirect;
redirect.value = newRoute.query && decodeURIComponent(newRoute.query.redirect);
},
{ immediate: true }
);
+2 -2
View File
@@ -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>
@@ -198,7 +198,7 @@ const handleExport = () => {
{
...queryParams.value
},
`config_${new Date().getTime()}.xlsx`
`logininfor_${new Date().getTime()}.xlsx`
);
};
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+13
View File
@@ -49,6 +49,9 @@
<el-col :span="1.5">
<el-button v-hasPermi="['system:dict:remove']" type="danger" plain icon="Refresh" @click="handleRefreshCache">刷新缓存</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-if="userId === 1" type="success" plain icon="Refresh" @click="handleSyncTenantDict">同步租户字典</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar>
</el-row>
</template>
@@ -109,11 +112,15 @@
<script setup name="Dict" lang="ts">
import useDictStore from '@/store/modules/dict';
import useUserStore from "@/store/modules/user";
import { listType, getType, delType, addType, updateType, refreshCache } from '@/api/system/dict/type';
import { DictTypeForm, DictTypeQuery, DictTypeVO } from '@/api/system/dict/type/types';
import { syncTenantDict } from "@/api/system/tenant";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const userStore = useUserStore();
const userId = ref(userStore.userId);
const typeList = ref<DictTypeVO[]>([]);
const loading = ref(true);
const showSearch = ref(true);
@@ -239,6 +246,12 @@ const handleRefreshCache = async () => {
proxy?.$modal.msgSuccess('刷新成功');
useDictStore().cleanDict();
};
/**同步租户字典*/
const handleSyncTenantDict = async () => {
await proxy?.$modal.confirm('确认要同步所有租户字典吗?');
let res = await syncTenantDict();
proxy?.$modal.msgSuccess(res.msg);
};
onMounted(() => {
getList();
+1 -1
View File
@@ -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>
+4 -4
View File
@@ -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"
@@ -60,7 +60,7 @@
>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['system:oss:list']" type="info" plain icon="Operation" @click="handleOssConfig">配置管理</el-button>
<el-button v-hasPermi="['system:ossConfig:list']" type="info" plain icon="Operation" @click="handleOssConfig">配置管理</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar>
</el-row>
@@ -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() {
+2 -2
View File
@@ -11,14 +11,14 @@
<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>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
+1 -1
View File
@@ -321,7 +321,7 @@ const handleDelete = async (row?: TenantPkgVO) => {
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'system/tenantPackage/export',
'system/tenant/package/export',
{
...queryParams.value
},
+2 -2
View File
@@ -80,8 +80,8 @@ const tableRef = ref<ElTableInstance>();
/** 单击选中行数据 */
const clickRow = (row: RoleVO) => {
// ele的方法有问题,selected应该为可选参数
tableRef.value?.toggleRowSelection(row, false);
row.flag = !row.flag
tableRef.value?.toggleRowSelection(row, row.flag);
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: RoleVO[]) => {
+2 -1
View File
@@ -39,11 +39,12 @@
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
></el-date-picker>
</el-form-item>
<el-form-item>
+3 -3
View File
@@ -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';
@@ -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
View File
@@ -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
View File
@@ -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;
-1
View File
@@ -274,7 +274,6 @@ const setSubTableColumns = (value: string) => {
/** 查询菜单下拉树结构 */
const getMenuTreeselect = async () => {
const res = await listMenu();
res.data.forEach((m) => (m.menuId = m.menuId.toString()));
const data = proxy?.handleTree<MenuOptionsType>(res.data, 'menuId');
if (data) {
+4 -4
View File
@@ -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 },
-1
View File
@@ -176,7 +176,6 @@ const handleSelectionChange = (selection: LeaveVO[]) => {
/** 新增按钮操作 */
const handleAdd = () => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.push(`/workflow/leaveEdit/index/add/add`);
proxy.$router.push({
path: `/workflow/leaveEdit/index`,
query: {
+4 -2
View File
@@ -23,10 +23,12 @@
<el-form-item label="请假时间">
<el-date-picker
v-model="leaveTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
range-separator="To"
start-placeholder="开始时间"
end-placeholder="结束时间"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
@change="changeLeaveTime()"
/>
</el-form-item>
@@ -190,8 +192,8 @@ const handleStartWorkFlow = async (data: LeaveVO) => {
taskVariables.value = {
entity: data,
leaveDays: data.leaveDays,
userList: [1, 3],
userList2: [1, 3]
userList: ["1", "3"],
userList2: ["1", "3"]
};
submitFormData.value.variables = taskVariables.value;
const resp = await startWorkFlow(submitFormData.value);
+1 -55
View File
@@ -75,61 +75,7 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
'diagram-js/lib/draw/BaseRenderer',
'tiny-svg',
'image-conversion',
'element-plus/es/components/text/style/css',
'element-plus/es/components/collapse-item/style/css',
'element-plus/es/components/collapse/style/css',
'element-plus/es/components/space/style/css',
'element-plus/es/components/container/style/css',
'element-plus/es/components/aside/style/css',
'element-plus/es/components/main/style/css',
'element-plus/es/components/header/style/css',
'element-plus/es/components/button-group/style/css',
'element-plus/es/components/radio-button/style/css',
'element-plus/es/components/checkbox-group/style/css',
'element-plus/es/components/form/style/css',
'element-plus/es/components/form-item/style/css',
'element-plus/es/components/button/style/css',
'element-plus/es/components/input/style/css',
'element-plus/es/components/input-number/style/css',
'element-plus/es/components/switch/style/css',
'element-plus/es/components/upload/style/css',
'element-plus/es/components/menu/style/css',
'element-plus/es/components/col/style/css',
'element-plus/es/components/icon/style/css',
'element-plus/es/components/row/style/css',
'element-plus/es/components/tag/style/css',
'element-plus/es/components/dialog/style/css',
'element-plus/es/components/loading/style/css',
'element-plus/es/components/radio/style/css',
'element-plus/es/components/radio-group/style/css',
'element-plus/es/components/popover/style/css',
'element-plus/es/components/scrollbar/style/css',
'element-plus/es/components/tooltip/style/css',
'element-plus/es/components/dropdown/style/css',
'element-plus/es/components/dropdown-menu/style/css',
'element-plus/es/components/dropdown-item/style/css',
'element-plus/es/components/sub-menu/style/css',
'element-plus/es/components/menu-item/style/css',
'element-plus/es/components/divider/style/css',
'element-plus/es/components/card/style/css',
'element-plus/es/components/link/style/css',
'element-plus/es/components/breadcrumb/style/css',
'element-plus/es/components/breadcrumb-item/style/css',
'element-plus/es/components/table/style/css',
'element-plus/es/components/tree-select/style/css',
'element-plus/es/components/table-column/style/css',
'element-plus/es/components/select/style/css',
'element-plus/es/components/option/style/css',
'element-plus/es/components/pagination/style/css',
'element-plus/es/components/tree/style/css',
'element-plus/es/components/alert/style/css',
'element-plus/es/components/checkbox/style/css',
'element-plus/es/components/date-picker/style/css',
'element-plus/es/components/transfer/style/css',
'element-plus/es/components/tabs/style/css',
'element-plus/es/components/image/style/css',
'element-plus/es/components/tab-pane/style/css'
'element-plus/es/components/**/css'
]
}
};