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
30 changed files with 175 additions and 288 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.1",
"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',
});
}
-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'
});
};
+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();
};
/** 租户列表 */
+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 });
};
+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 {
+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 }
}
]
},
+3 -3
View File
@@ -21,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 => {
+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;
+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.1</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 }
);
+1 -1
View File
@@ -198,7 +198,7 @@ const handleExport = () => {
{
...queryParams.value
},
`config_${new Date().getTime()}.xlsx`
`logininfor_${new Date().getTime()}.xlsx`
);
};
+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
@@ -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>
+1 -1
View File
@@ -18,7 +18,7 @@
<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>
-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) {
-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'
]
}
};