Compare commits
52
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a02598c00 | ||
|
|
28a81f2e44 | ||
|
|
6f4891d677 | ||
|
|
a62a3de23c | ||
|
|
1d852da351 | ||
|
|
f0895e9419 | ||
|
|
1644070e97 | ||
|
|
4918552492 | ||
|
|
364dfb969d | ||
|
|
9726df3966 | ||
|
|
483af13741 | ||
|
|
25848ea99e | ||
|
|
9f13c29cd7 | ||
|
|
e1860a30fc | ||
|
|
34b929d352 | ||
|
|
1606dbd76f | ||
|
|
3c2d9100b5 | ||
|
|
2c8873402f | ||
|
|
e5727893bb | ||
|
|
335a1e6019 | ||
|
|
c0ee3182e1 | ||
|
|
9eb7b433b4 | ||
|
|
9193f0b84a | ||
|
|
076fc5deb1 | ||
|
|
58412035ad | ||
|
|
964db2dfce | ||
|
|
d58a75996e | ||
|
|
f5a5aaa255 | ||
|
|
1465a27a6e | ||
|
|
e5e43fe024 | ||
|
|
6c49b47344 | ||
|
|
358f11a0a3 | ||
|
|
6a83ed2aad | ||
|
|
e07c0b2b3a | ||
|
|
adadfcf8cb | ||
|
|
425386f6f4 | ||
|
|
ba24afce52 | ||
|
|
93d3371768 | ||
|
|
3f08ae6ac4 | ||
|
|
cc6284d3ac | ||
|
|
142effd4f2 | ||
|
|
e657a507e3 | ||
|
|
ebaec24213 | ||
|
|
7637582437 | ||
|
|
27d36f7970 | ||
|
|
762ebd4ede | ||
|
|
ad991e248a | ||
|
|
d1b58f0aaa | ||
|
|
1be1eaf7b4 | ||
|
|
fbcc967b14 | ||
|
|
817c65f7e2 | ||
|
|
b6dcc62f9c |
+5
-2
@@ -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
@@ -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
@@ -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",
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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'
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
});
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -128,7 +128,7 @@ const props = defineProps({
|
||||
//回显用户id
|
||||
userIdList: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
const deptTreeRef = ref(ElTree);
|
||||
|
||||
@@ -106,7 +106,7 @@ const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>();
|
||||
const props = defineProps({
|
||||
taskVariables: {
|
||||
type: Object as () => Record<string, any>,
|
||||
default: {}
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
//遮罩层
|
||||
|
||||
@@ -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,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 />
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[]]);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
Vendored
+1
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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
@@ -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
@@ -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">¥免费开源</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">¥免费开源</el-tag>
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -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 }
|
||||
);
|
||||
|
||||
@@ -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`
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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="开始日期"
|
||||
|
||||
@@ -321,7 +321,7 @@ const handleDelete = async (row?: TenantPkgVO) => {
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
proxy?.download(
|
||||
'system/tenantPackage/export',
|
||||
'system/tenant/package/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
|
||||
@@ -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[]) => {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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' },
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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
@@ -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'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user