mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 00:10:25 +08:00 
			
		
		
		
	refactor: PageTable组件重构、使用useFetch封装接口请求
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
				
			|||||||
import request from './request';
 | 
					import request from './request';
 | 
				
			||||||
import { randomUuid } from './utils/string';
 | 
					import { useApiFetch } from './useRequest';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 可用于各模块定义各自api请求
 | 
					 * 可用于各模块定义各自api请求
 | 
				
			||||||
@@ -21,8 +21,6 @@ class Api {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    beforeHandler: Function;
 | 
					    beforeHandler: Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static abortControllers: Map<string, AbortController> = new Map();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    constructor(url: string, method: string) {
 | 
					    constructor(url: string, method: string) {
 | 
				
			||||||
        this.url = url;
 | 
					        this.url = url;
 | 
				
			||||||
        this.method = method;
 | 
					        this.method = method;
 | 
				
			||||||
@@ -46,68 +44,38 @@ class Api {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 请求对应的该api
 | 
					     * 响应式使用该api
 | 
				
			||||||
 | 
					     * @param params 响应式params
 | 
				
			||||||
 | 
					     * @param reqOptions 其他可选值
 | 
				
			||||||
 | 
					     * @returns
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    useApi<T>(params: any = null, reqOptions: RequestInit = {}) {
 | 
				
			||||||
 | 
					        return useApiFetch<T>(this, params, reqOptions);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * fetch 请求对应的该api
 | 
				
			||||||
     * @param {Object} param 请求该api的参数
 | 
					     * @param {Object} param 请求该api的参数
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    request(param: any = null, options: any = {}): Promise<any> {
 | 
					    async request(param: any = null, options: any = {}): Promise<any> {
 | 
				
			||||||
 | 
					        const { execute, data } = this.useApi(param, options);
 | 
				
			||||||
 | 
					        await execute();
 | 
				
			||||||
 | 
					        return data.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * xhr 请求对应的该api
 | 
				
			||||||
 | 
					     * @param {Object} param 请求该api的参数
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async xhrReq(param: any = null, options: any = {}): Promise<any> {
 | 
				
			||||||
        if (this.beforeHandler) {
 | 
					        if (this.beforeHandler) {
 | 
				
			||||||
            this.beforeHandler(param);
 | 
					            this.beforeHandler(param);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return request.request(this.method, this.url, param, options);
 | 
					        return request.xhrReq(this.method, this.url, param, options);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 允许取消的请求, 使用Api.cancelReq(key) 取消请求
 | 
					 | 
				
			||||||
     * @param key 用于取消该key关联的请求
 | 
					 | 
				
			||||||
     * @param {Object} param 请求该api的参数
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    allowCancelReq(key: string, param: any = null, options: RequestInit = {}): Promise<any> {
 | 
					 | 
				
			||||||
        let controller = Api.abortControllers.get(key);
 | 
					 | 
				
			||||||
        if (!controller) {
 | 
					 | 
				
			||||||
            controller = new AbortController();
 | 
					 | 
				
			||||||
            Api.abortControllers.set(key, controller);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        options.signal = controller.signal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return this.request(param, options);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**    静态方法     **/
 | 
					    /**    静态方法     **/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 取消请求
 | 
					 | 
				
			||||||
     * @param key 请求key
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    static cancelReq(key: string) {
 | 
					 | 
				
			||||||
        let controller = Api.abortControllers.get(key);
 | 
					 | 
				
			||||||
        if (controller) {
 | 
					 | 
				
			||||||
            controller.abort();
 | 
					 | 
				
			||||||
            Api.removeAbortKey(key);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static removeAbortKey(key: string) {
 | 
					 | 
				
			||||||
        if (key) {
 | 
					 | 
				
			||||||
            console.log('remove abort key: ', key);
 | 
					 | 
				
			||||||
            Api.abortControllers.delete(key);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 根据旧key生成新的abort key,可能旧key未取消,造成多余无用对象
 | 
					 | 
				
			||||||
     * @param oldKey 旧key
 | 
					 | 
				
			||||||
     * @returns key
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    static genAbortKey(oldKey: string) {
 | 
					 | 
				
			||||||
        if (!oldKey) {
 | 
					 | 
				
			||||||
            return randomUuid();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (Api.abortControllers.get(oldKey)) {
 | 
					 | 
				
			||||||
            return oldKey;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return randomUuid();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 静态工厂,返回Api对象,并设置url与method属性
 | 
					     * 静态工厂,返回Api对象,并设置url与method属性
 | 
				
			||||||
     * @param url url
 | 
					     * @param url url
 | 
				
			||||||
@@ -151,3 +119,8 @@ class Api {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Api;
 | 
					export default Api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class PageRes {
 | 
				
			||||||
 | 
					    list: any[] = [];
 | 
				
			||||||
 | 
					    total: number = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,10 +4,12 @@ import { getClientId, getToken } from './utils/storage';
 | 
				
			|||||||
import { templateResolve } from './utils/string';
 | 
					import { templateResolve } from './utils/string';
 | 
				
			||||||
import { ElMessage } from 'element-plus';
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
import axios from 'axios';
 | 
					import axios from 'axios';
 | 
				
			||||||
 | 
					import { useApiFetch } from './useRequest';
 | 
				
			||||||
 | 
					import Api from './Api';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    request,
 | 
					    request,
 | 
				
			||||||
    fetchReq,
 | 
					    xhrReq,
 | 
				
			||||||
    get,
 | 
					    get,
 | 
				
			||||||
    post,
 | 
					    post,
 | 
				
			||||||
    put,
 | 
					    put,
 | 
				
			||||||
@@ -30,7 +32,7 @@ export interface Result {
 | 
				
			|||||||
    data?: any;
 | 
					    data?: any;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum ResultEnum {
 | 
					export enum ResultEnum {
 | 
				
			||||||
    SUCCESS = 200,
 | 
					    SUCCESS = 200,
 | 
				
			||||||
    ERROR = 400,
 | 
					    ERROR = 400,
 | 
				
			||||||
    PARAM_ERROR = 405,
 | 
					    PARAM_ERROR = 405,
 | 
				
			||||||
@@ -38,7 +40,7 @@ enum ResultEnum {
 | 
				
			|||||||
    NO_PERMISSION = 501,
 | 
					    NO_PERMISSION = 501,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const baseUrl: string = config.baseApiUrl;
 | 
					export const baseUrl: string = config.baseApiUrl;
 | 
				
			||||||
// const baseUrl: string = 'http://localhost:18888/api';
 | 
					// const baseUrl: string = 'http://localhost:18888/api';
 | 
				
			||||||
// const baseWsUrl: string = config.baseWsUrl;
 | 
					// const baseWsUrl: string = config.baseWsUrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,14 +117,15 @@ axiosInst.interceptors.response.use(
 | 
				
			|||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 请求uri
 | 
					 * xhr请求url
 | 
				
			||||||
 * 该方法已处理请求结果中code != 200的message提示,如需其他错误处理(取消加载状态,重置对象状态等等),可catch继续处理
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {Object} method 请求方法(GET,POST,PUT,DELTE等)
 | 
					 * @param method 请求方法
 | 
				
			||||||
 * @param {Object} uri    uri
 | 
					 * @param url url
 | 
				
			||||||
 * @param {Object} params 参数
 | 
					 * @param params 参数
 | 
				
			||||||
 | 
					 * @param options 可选
 | 
				
			||||||
 | 
					 * @returns
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function request(method: string, url: string, params: any = null, options: any = {}): Promise<any> {
 | 
					export function xhrReq(method: string, url: string, params: any = null, options: any = {}) {
 | 
				
			||||||
    if (!url) {
 | 
					    if (!url) {
 | 
				
			||||||
        throw new Error('请求url不能为空');
 | 
					        throw new Error('请求url不能为空');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -157,6 +160,21 @@ function request(method: string, url: string, params: any = null, options: any =
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * fetch请求url
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 该方法已处理请求结果中code != 200的message提示,如需其他错误处理(取消加载状态,重置对象状态等等),可catch继续处理
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {Object} method 请求方法(GET,POST,PUT,DELTE等)
 | 
				
			||||||
 | 
					 * @param {Object} uri    uri
 | 
				
			||||||
 | 
					 * @param {Object} params 参数
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					async function request(method: string, url: string, params: any = null, options: any = {}): Promise<any> {
 | 
				
			||||||
 | 
					    const { execute, data } = useApiFetch(Api.create(url, method), params, options);
 | 
				
			||||||
 | 
					    await execute();
 | 
				
			||||||
 | 
					    return data.value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * get请求uri
 | 
					 * get请求uri
 | 
				
			||||||
 * 该方法已处理请求结果中code != 200的message提示,如需其他错误处理(取消加载状态,重置对象状态等等),可catch继续处理
 | 
					 * 该方法已处理请求结果中code != 200的message提示,如需其他错误处理(取消加载状态,重置对象状态等等),可catch继续处理
 | 
				
			||||||
@@ -190,64 +208,6 @@ export function joinClientParams(): string {
 | 
				
			|||||||
    return `token=${getToken()}&clientId=${getClientId()}`;
 | 
					    return `token=${getToken()}&clientId=${getClientId()}`;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function fetchReq(method: string, url: string, params: any = null, options: RequestInit = {}): Promise<any> {
 | 
					 | 
				
			||||||
    options.method = method;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (params) {
 | 
					 | 
				
			||||||
        // post和put使用json格式传参
 | 
					 | 
				
			||||||
        if (method === 'post' || method === 'put') {
 | 
					 | 
				
			||||||
            options.body = JSON.stringify(params);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            const searchParam = new URLSearchParams();
 | 
					 | 
				
			||||||
            Object.keys(params).forEach((key) => {
 | 
					 | 
				
			||||||
                const val = params[key];
 | 
					 | 
				
			||||||
                if (val) {
 | 
					 | 
				
			||||||
                    searchParam.append(key, val);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            url = `${url}?${searchParam.toString()}`;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Part 1: Add headers and attach auth token
 | 
					 | 
				
			||||||
    const headers = new Headers(options.headers || {});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const token = getToken();
 | 
					 | 
				
			||||||
    if (token) {
 | 
					 | 
				
			||||||
        headers.set('Authorization', token);
 | 
					 | 
				
			||||||
        headers.set('ClientId', getClientId());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    options.headers = headers;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        const res: Response = await fetch(`${baseUrl}${url}`, options);
 | 
					 | 
				
			||||||
        if (!res.ok) {
 | 
					 | 
				
			||||||
            throw new Error(`请求响应错误: 状态码=${res.status}`);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const jsonRes = await res.json();
 | 
					 | 
				
			||||||
        // 获取请求返回结果
 | 
					 | 
				
			||||||
        const result: Result = jsonRes;
 | 
					 | 
				
			||||||
        return parseResult(result);
 | 
					 | 
				
			||||||
    } catch (e: any) {
 | 
					 | 
				
			||||||
        const rejectPromise = Promise.reject(e);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (e?.name == 'AbortError') {
 | 
					 | 
				
			||||||
            console.log('请求已取消');
 | 
					 | 
				
			||||||
            return rejectPromise;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (e.message) {
 | 
					 | 
				
			||||||
            notifyErrorMsg(e.message);
 | 
					 | 
				
			||||||
            return rejectPromise;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        notifyErrorMsg('网络请求错误');
 | 
					 | 
				
			||||||
        console.error(e);
 | 
					 | 
				
			||||||
        return rejectPromise;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function parseResult(result: Result) {
 | 
					function parseResult(result: Result) {
 | 
				
			||||||
    if (result.code === ResultEnum.SUCCESS) {
 | 
					    if (result.code === ResultEnum.SUCCESS) {
 | 
				
			||||||
        return result.data;
 | 
					        return result.data;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										134
									
								
								mayfly_go_web/src/common/useRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								mayfly_go_web/src/common/useRequest.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,134 @@
 | 
				
			|||||||
 | 
					import router from '../router';
 | 
				
			||||||
 | 
					import { getClientId, getToken } from './utils/storage';
 | 
				
			||||||
 | 
					import { templateResolve } from './utils/string';
 | 
				
			||||||
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
 | 
					import { createFetch } from '@vueuse/core';
 | 
				
			||||||
 | 
					import Api from './Api';
 | 
				
			||||||
 | 
					import { Result, ResultEnum } from './request';
 | 
				
			||||||
 | 
					import config from './config';
 | 
				
			||||||
 | 
					import { unref } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const baseUrl: string = config.baseApiUrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useCustomFetch = createFetch({
 | 
				
			||||||
 | 
					    baseUrl: baseUrl,
 | 
				
			||||||
 | 
					    combination: 'chain',
 | 
				
			||||||
 | 
					    options: {
 | 
				
			||||||
 | 
					        immediate: false,
 | 
				
			||||||
 | 
					        timeout: 60000,
 | 
				
			||||||
 | 
					        // beforeFetch in pre-configured instance will only run when the newly spawned instance do not pass beforeFetch
 | 
				
			||||||
 | 
					        async beforeFetch({ options }) {
 | 
				
			||||||
 | 
					            const token = getToken();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const headers = new Headers(options.headers || {});
 | 
				
			||||||
 | 
					            if (token) {
 | 
				
			||||||
 | 
					                headers.set('Authorization', token);
 | 
				
			||||||
 | 
					                headers.set('ClientId', getClientId());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            options.headers = headers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return { options };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        async afterFetch(ctx) {
 | 
				
			||||||
 | 
					            const result: Result = await ctx.response.json();
 | 
				
			||||||
 | 
					            ctx.data = result;
 | 
				
			||||||
 | 
					            return ctx;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function useApiFetch<T>(api: Api, params: any = null, reqOptions: RequestInit = {}) {
 | 
				
			||||||
 | 
					    const uaf = useCustomFetch<T>(api.url, {
 | 
				
			||||||
 | 
					        beforeFetch({ url, options }) {
 | 
				
			||||||
 | 
					            options.method = api.method;
 | 
				
			||||||
 | 
					            if (!params) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let paramsValue = unref(params);
 | 
				
			||||||
 | 
					            if (api.beforeHandler) {
 | 
				
			||||||
 | 
					                paramsValue = api.beforeHandler(paramsValue);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let apiUrl = url;
 | 
				
			||||||
 | 
					            // 简单判断该url是否是restful风格
 | 
				
			||||||
 | 
					            if (apiUrl.indexOf('{') != -1) {
 | 
				
			||||||
 | 
					                apiUrl = templateResolve(apiUrl, paramsValue);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (paramsValue) {
 | 
				
			||||||
 | 
					                const method = options.method?.toLowerCase();
 | 
				
			||||||
 | 
					                // post和put使用json格式传参
 | 
				
			||||||
 | 
					                if (method === 'post' || method === 'put') {
 | 
				
			||||||
 | 
					                    options.body = JSON.stringify(paramsValue);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    const searchParam = new URLSearchParams();
 | 
				
			||||||
 | 
					                    Object.keys(paramsValue).forEach((key) => {
 | 
				
			||||||
 | 
					                        const val = paramsValue[key];
 | 
				
			||||||
 | 
					                        if (val) {
 | 
				
			||||||
 | 
					                            searchParam.append(key, val);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                    apiUrl = `${apiUrl}?${searchParam.toString()}`;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                url: apiUrl,
 | 
				
			||||||
 | 
					                options: {
 | 
				
			||||||
 | 
					                    ...options,
 | 
				
			||||||
 | 
					                    ...reqOptions,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        execute: async function () {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                await uaf.execute(true);
 | 
				
			||||||
 | 
					            } catch (e: any) {
 | 
				
			||||||
 | 
					                const rejectPromise = Promise.reject(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (e?.name == 'AbortError') {
 | 
				
			||||||
 | 
					                    console.log('请求已取消');
 | 
				
			||||||
 | 
					                    return rejectPromise;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                console.error(e);
 | 
				
			||||||
 | 
					                ElMessage.error('网络请求错误');
 | 
				
			||||||
 | 
					                return rejectPromise;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const result: Result = uaf.data.value as any;
 | 
				
			||||||
 | 
					            if (!result) {
 | 
				
			||||||
 | 
					                ElMessage.error('网络请求失败');
 | 
				
			||||||
 | 
					                return Promise.reject(result);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 如果返回为成功结果,则将结果的data赋值给响应式data
 | 
				
			||||||
 | 
					            if (result.code === ResultEnum.SUCCESS) {
 | 
				
			||||||
 | 
					                uaf.data.value = result.data;
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 如果提示没有权限,则移除token,使其重新登录
 | 
				
			||||||
 | 
					            if (result.code === ResultEnum.NO_PERMISSION) {
 | 
				
			||||||
 | 
					                router.push({
 | 
				
			||||||
 | 
					                    path: '/401',
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 如果返回的code不为成功,则会返回对应的错误msg,则直接统一通知即可。忽略登录超时或没有权限的提示(直接跳转至401页面)
 | 
				
			||||||
 | 
					            if (result.msg && result?.code != ResultEnum.NO_PERMISSION) {
 | 
				
			||||||
 | 
					                ElMessage.error(result.msg);
 | 
				
			||||||
 | 
					                uaf.error.value = new Error(result.msg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return Promise.reject(result);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        isFetching: uaf.isFetching,
 | 
				
			||||||
 | 
					        data: uaf.data,
 | 
				
			||||||
 | 
					        abort: uaf.abort,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
            <div class="query" ref="queryRef">
 | 
					            <div class="query" ref="queryRef">
 | 
				
			||||||
                <div>
 | 
					                <div>
 | 
				
			||||||
                    <div v-if="props.query.length > 0">
 | 
					                    <div v-if="props.query.length > 0">
 | 
				
			||||||
                        <el-form :model="props.queryForm" label-width="auto" :size="props.size">
 | 
					                        <el-form :model="queryForm_" label-width="auto" :size="props.size">
 | 
				
			||||||
                            <el-row
 | 
					                            <el-row
 | 
				
			||||||
                                v-for="i in Math.ceil((props.query.length + 1) / (defaultQueryCount + 1))"
 | 
					                                v-for="i in Math.ceil((props.query.length + 1) / (defaultQueryCount + 1))"
 | 
				
			||||||
                                :key="i"
 | 
					                                :key="i"
 | 
				
			||||||
@@ -104,9 +104,9 @@
 | 
				
			|||||||
                v-bind="$attrs"
 | 
					                v-bind="$attrs"
 | 
				
			||||||
                :max-height="tableMaxHeight"
 | 
					                :max-height="tableMaxHeight"
 | 
				
			||||||
                @selection-change="handleSelectionChange"
 | 
					                @selection-change="handleSelectionChange"
 | 
				
			||||||
                :data="props.data"
 | 
					                :data="state.data"
 | 
				
			||||||
                highlight-current-row
 | 
					                highlight-current-row
 | 
				
			||||||
                v-loading="loadingData"
 | 
					                v-loading="state.loading"
 | 
				
			||||||
                :size="props.size"
 | 
					                :size="props.size"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
                <el-table-column v-if="props.showSelection" type="selection" width="40" />
 | 
					                <el-table-column v-if="props.showSelection" type="selection" width="40" />
 | 
				
			||||||
@@ -171,9 +171,9 @@
 | 
				
			|||||||
                    @size-change="handleSizeChange"
 | 
					                    @size-change="handleSizeChange"
 | 
				
			||||||
                    style="text-align: right"
 | 
					                    style="text-align: right"
 | 
				
			||||||
                    layout="prev, pager, next, total, sizes, jumper"
 | 
					                    layout="prev, pager, next, total, sizes, jumper"
 | 
				
			||||||
                    :total="props.total"
 | 
					                    :total="state.total"
 | 
				
			||||||
                    v-model:current-page="state.pageNum"
 | 
					                    v-model:current-page="queryForm_.pageNum"
 | 
				
			||||||
                    v-model:page-size="state.pageSize"
 | 
					                    v-model:page-size="queryForm_.pageSize"
 | 
				
			||||||
                    :page-sizes="pageSizes"
 | 
					                    :page-sizes="pageSizes"
 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
            </el-row>
 | 
					            </el-row>
 | 
				
			||||||
@@ -182,11 +182,13 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { toRefs, watch, reactive, onMounted } from 'vue';
 | 
					import { toRefs, watch, reactive, onMounted, Ref } from 'vue';
 | 
				
			||||||
import { TableColumn, TableQuery } from './index';
 | 
					import { TableColumn, TableQuery } from './index';
 | 
				
			||||||
import EnumTag from '@/components/enumtag/EnumTag.vue';
 | 
					import EnumTag from '@/components/enumtag/EnumTag.vue';
 | 
				
			||||||
import { useThemeConfig } from '@/store/themeConfig';
 | 
					import { useThemeConfig } from '@/store/themeConfig';
 | 
				
			||||||
import { storeToRefs } from 'pinia';
 | 
					import { storeToRefs } from 'pinia';
 | 
				
			||||||
 | 
					import { useVModel } from '@vueuse/core';
 | 
				
			||||||
 | 
					import Api from '@/common/Api';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const emit = defineEmits(['update:queryForm', 'update:pageNum', 'update:pageSize', 'update:selectionData', 'pageChange']);
 | 
					const emit = defineEmits(['update:queryForm', 'update:pageNum', 'update:pageSize', 'update:selectionData', 'pageChange']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -216,22 +218,19 @@ const props = defineProps({
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        required: true,
 | 
					        required: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    // 表格数据
 | 
					    // 调用分页数据的api
 | 
				
			||||||
    data: {
 | 
					    pageApi: {
 | 
				
			||||||
        type: Array,
 | 
					        type: Api,
 | 
				
			||||||
        required: true,
 | 
					        required: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    total: {
 | 
					    // 数据处理回调函数,用于将请求回来的数据二次加工处理等
 | 
				
			||||||
        type: [Number],
 | 
					    dataHandlerFn: {
 | 
				
			||||||
        default: 0,
 | 
					        type: Function,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    pageNum: {
 | 
					    // 懒加载,即需要手动调用search方法才可调接口获取数据,不会在mounted的时候调用。
 | 
				
			||||||
        type: Number,
 | 
					    lazy: {
 | 
				
			||||||
        default: 1,
 | 
					        type: Boolean,
 | 
				
			||||||
    },
 | 
					        default: false,
 | 
				
			||||||
    pageSize: {
 | 
					 | 
				
			||||||
        type: [Number],
 | 
					 | 
				
			||||||
        default: 10,
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    // 查询条件配置
 | 
					    // 查询条件配置
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
@@ -244,7 +243,10 @@ const props = defineProps({
 | 
				
			|||||||
    queryForm: {
 | 
					    queryForm: {
 | 
				
			||||||
        type: Object,
 | 
					        type: Object,
 | 
				
			||||||
        default: function () {
 | 
					        default: function () {
 | 
				
			||||||
            return {};
 | 
					            return {
 | 
				
			||||||
 | 
					                pageNum: 1,
 | 
				
			||||||
 | 
					                pageSize: 10,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
@@ -253,56 +255,36 @@ const { themeConfig } = storeToRefs(useThemeConfig());
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    pageSizes: [] as any, // 可选每页显示的数据量
 | 
					    pageSizes: [] as any, // 可选每页显示的数据量
 | 
				
			||||||
    pageSize: 10,
 | 
					 | 
				
			||||||
    pageNum: 1,
 | 
					 | 
				
			||||||
    isOpenMoreQuery: false,
 | 
					    isOpenMoreQuery: false,
 | 
				
			||||||
    defaultQueryCount: 2, // 默认显示的查询参数个数,展开后每行显示查询条件个数为该值加1。第一行用最后一列来占用按钮
 | 
					    defaultQueryCount: 2, // 默认显示的查询参数个数,展开后每行显示查询条件个数为该值加1。第一行用最后一列来占用按钮
 | 
				
			||||||
    queryForm_: {} as any,
 | 
					    loading: false,
 | 
				
			||||||
    loadingData: false,
 | 
					    data: [],
 | 
				
			||||||
 | 
					    total: 0,
 | 
				
			||||||
    // 输入框宽度
 | 
					    // 输入框宽度
 | 
				
			||||||
    inputWidth_: '200px' as any,
 | 
					    inputWidth_: '200px' as any,
 | 
				
			||||||
    formatVal: '', // 格式化后的值
 | 
					    formatVal: '', // 格式化后的值
 | 
				
			||||||
    tableMaxHeight: window.innerHeight - 240 + 'px',
 | 
					    tableMaxHeight: window.innerHeight - 240 + 'px',
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { pageSizes, isOpenMoreQuery, defaultQueryCount, queryForm_, inputWidth_, formatVal, loadingData, tableMaxHeight } = toRefs(state);
 | 
					const { pageSizes, isOpenMoreQuery, defaultQueryCount, inputWidth_, formatVal, tableMaxHeight } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const queryForm_: Ref<any> = useVModel(props, 'queryForm', emit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(
 | 
					watch(
 | 
				
			||||||
    () => props.queryForm,
 | 
					    () => state.data,
 | 
				
			||||||
    (newValue: any) => {
 | 
					 | 
				
			||||||
        state.queryForm_ = newValue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
watch(
 | 
					 | 
				
			||||||
    () => props.pageNum,
 | 
					 | 
				
			||||||
    (newValue: any) => {
 | 
					 | 
				
			||||||
        state.pageNum = newValue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
watch(
 | 
					 | 
				
			||||||
    () => props.pageSize,
 | 
					 | 
				
			||||||
    (newValue: any) => {
 | 
					 | 
				
			||||||
        state.pageSize = newValue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
watch(
 | 
					 | 
				
			||||||
    () => props.data,
 | 
					 | 
				
			||||||
    (newValue: any) => {
 | 
					    (newValue: any) => {
 | 
				
			||||||
        if (newValue && newValue.length > 0) {
 | 
					        if (newValue && newValue.length > 0) {
 | 
				
			||||||
            props.columns.forEach((item) => {
 | 
					            props.columns.forEach((item) => {
 | 
				
			||||||
                if (item.autoWidth && item.show) {
 | 
					                if (item.autoWidth && item.show) {
 | 
				
			||||||
                    item.autoCalculateMinWidth(props.data);
 | 
					                    item.autoCalculateMinWidth(state.data);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    let pageSize = props.pageSize;
 | 
					    let pageSize = queryForm_.value.pageSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 如果pageSize设为0,则使用系统全局配置的pageSize
 | 
					    // 如果pageSize设为0,则使用系统全局配置的pageSize
 | 
				
			||||||
    if (!pageSize) {
 | 
					    if (!pageSize) {
 | 
				
			||||||
@@ -311,12 +293,10 @@ onMounted(() => {
 | 
				
			|||||||
        if (!pageSize) {
 | 
					        if (!pageSize) {
 | 
				
			||||||
            pageSize = 10;
 | 
					            pageSize = 10;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        emit('update:pageSize', pageSize);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state.pageNum = props.pageNum;
 | 
					    queryForm_.value.pageNum = 1;
 | 
				
			||||||
    state.pageSize = pageSize;
 | 
					    queryForm_.value.pageSize = pageSize;
 | 
				
			||||||
    state.queryForm_ = props.queryForm;
 | 
					 | 
				
			||||||
    state.pageSizes = [pageSize, pageSize * 2, pageSize * 3, pageSize * 4, pageSize * 5];
 | 
					    state.pageSizes = [pageSize, pageSize * 2, pageSize * 3, pageSize * 4, pageSize * 5];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 如果没传输入框宽度,则根据组件size设置默认宽度
 | 
					    // 如果没传输入框宽度,则根据组件size设置默认宽度
 | 
				
			||||||
@@ -329,6 +309,10 @@ onMounted(() => {
 | 
				
			|||||||
    window.addEventListener('resize', () => {
 | 
					    window.addEventListener('resize', () => {
 | 
				
			||||||
        calcuTableHeight();
 | 
					        calcuTableHeight();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!props.lazy) {
 | 
				
			||||||
 | 
					        await reqPageApi();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const calcuTableHeight = () => {
 | 
					const calcuTableHeight = () => {
 | 
				
			||||||
@@ -360,14 +344,28 @@ const handleSelectionChange = (val: any) => {
 | 
				
			|||||||
    emit('update:selectionData', val);
 | 
					    emit('update:selectionData', val);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const handlePageChange = () => {
 | 
					const reqPageApi = async () => {
 | 
				
			||||||
    emit('update:pageNum', state.pageNum);
 | 
					    try {
 | 
				
			||||||
 | 
					        state.loading = true;
 | 
				
			||||||
 | 
					        const res = await props.pageApi?.request(queryForm_.value);
 | 
				
			||||||
 | 
					        if (props.dataHandlerFn) {
 | 
				
			||||||
 | 
					            state.data = await props.dataHandlerFn(res.list);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            state.data = res.list;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        state.total = res.total;
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					        state.loading = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const handlePageChange = (val: number) => {
 | 
				
			||||||
 | 
					    queryForm_.value.pageNum = val;
 | 
				
			||||||
    execQuery();
 | 
					    execQuery();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const handleSizeChange = () => {
 | 
					const handleSizeChange = () => {
 | 
				
			||||||
    changePageNum(1);
 | 
					    changePageNum(1);
 | 
				
			||||||
    emit('update:pageSize', state.pageSize);
 | 
					 | 
				
			||||||
    execQuery();
 | 
					    execQuery();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -379,31 +377,24 @@ const queryData = () => {
 | 
				
			|||||||
const reset = () => {
 | 
					const reset = () => {
 | 
				
			||||||
    // 将查询参数绑定的值置空,并重新粗发查询接口
 | 
					    // 将查询参数绑定的值置空,并重新粗发查询接口
 | 
				
			||||||
    for (let qi of props.query) {
 | 
					    for (let qi of props.query) {
 | 
				
			||||||
        state.queryForm_[qi.prop] = null;
 | 
					        queryForm_.value[qi.prop] = null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    changePageNum(1);
 | 
					    changePageNum(1);
 | 
				
			||||||
    emit('update:queryForm', state.queryForm_);
 | 
					 | 
				
			||||||
    execQuery();
 | 
					    execQuery();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const changePageNum = (pageNum: number) => {
 | 
					const changePageNum = (pageNum: number) => {
 | 
				
			||||||
    state.pageNum = pageNum;
 | 
					    queryForm_.value.pageNum = pageNum;
 | 
				
			||||||
    emit('update:pageNum', state.pageNum);
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const execQuery = () => {
 | 
					const execQuery = async () => {
 | 
				
			||||||
    emit('pageChange');
 | 
					    await reqPageApi();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					defineExpose({
 | 
				
			||||||
 * 是否正在加载数据
 | 
					    search: execQuery,
 | 
				
			||||||
 */
 | 
					});
 | 
				
			||||||
const loading = (loading: boolean) => {
 | 
					 | 
				
			||||||
    state.loadingData = loading;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
defineExpose({ loading });
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<style scoped lang="scss">
 | 
					<style scoped lang="scss">
 | 
				
			||||||
.page-table {
 | 
					.page-table {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,7 +77,7 @@
 | 
				
			|||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div class="dialog-footer">
 | 
					                <div class="dialog-footer">
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -155,11 +155,12 @@ const state = reactive({
 | 
				
			|||||||
        remark: '',
 | 
					        remark: '',
 | 
				
			||||||
        instanceId: null as any,
 | 
					        instanceId: null as any,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    btnLoading: false,
 | 
					 | 
				
			||||||
    instances: [] as any,
 | 
					    instances: [] as any,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, allDatabases, databaseList, form, btnLoading } = toRefs(state);
 | 
					const { dialogVisible, allDatabases, form, databaseList } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveDbExec } = dbApi.saveDb.useApi(form);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, async (newValue: any) => {
 | 
					watch(props, async (newValue: any) => {
 | 
				
			||||||
    state.dialogVisible = newValue.visible;
 | 
					    state.dialogVisible = newValue.visible;
 | 
				
			||||||
@@ -216,22 +217,15 @@ const open = async () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const btnOk = async () => {
 | 
					const btnOk = async () => {
 | 
				
			||||||
    dbForm.value.validate(async (valid: boolean) => {
 | 
					    dbForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            const reqForm = { ...state.form };
 | 
					 | 
				
			||||||
            dbApi.saveDb.request(reqForm).then(() => {
 | 
					 | 
				
			||||||
                ElMessage.success('保存成功');
 | 
					 | 
				
			||||||
                emit('val-change', state.form);
 | 
					 | 
				
			||||||
                state.btnLoading = true;
 | 
					 | 
				
			||||||
                setTimeout(() => {
 | 
					 | 
				
			||||||
                    state.btnLoading = false;
 | 
					 | 
				
			||||||
                }, 1000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                cancel();
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await saveDbExec();
 | 
				
			||||||
 | 
					        ElMessage.success('保存成功');
 | 
				
			||||||
 | 
					        emit('val-change', state.form);
 | 
				
			||||||
 | 
					        cancel();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,16 +2,12 @@
 | 
				
			|||||||
    <div class="db-list">
 | 
					    <div class="db-list">
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
            ref="pageTableRef"
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="dbApi.dbs"
 | 
				
			||||||
            :query="queryConfig"
 | 
					            :query="queryConfig"
 | 
				
			||||||
            v-model:query-form="query"
 | 
					            v-model:query-form="query"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="state.selectionData"
 | 
					            v-model:selection-data="state.selectionData"
 | 
				
			||||||
            :data="datas"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					            :columns="columns"
 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #tagPathSelect>
 | 
					            <template #tagPathSelect>
 | 
				
			||||||
                <el-select @focus="getTags" v-model="query.tagPath" placeholder="请选择标签" filterable clearable style="width: 200px">
 | 
					                <el-select @focus="getTags" v-model="query.tagPath" placeholder="请选择标签" filterable clearable style="width: 200px">
 | 
				
			||||||
@@ -140,7 +136,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <el-dialog v-model="infoDialog.visible" :before-close="onBeforeCloseInfoDialog" :close-on-click-modal="false">
 | 
					        <el-dialog v-model="infoDialog.visible" :before-close="onBeforeCloseInfoDialog" :close-on-click-modal="false">
 | 
				
			||||||
            <el-descriptions title="详情" :column="3" border>
 | 
					            <el-descriptions title="详情" :column="3" border>
 | 
				
			||||||
                <el-descriptions-item :span="3" label="标签路径">{{ infoDialog.data?.tagPath }}</el-descriptions-item>
 | 
					                <!-- <el-descriptions-item :span="3" label="标签路径">{{ infoDialog.data?.tagPath }}</el-descriptions-item> -->
 | 
				
			||||||
                <el-descriptions-item :span="2" label="名称">{{ infoDialog.data?.name }}</el-descriptions-item>
 | 
					                <el-descriptions-item :span="2" label="名称">{{ infoDialog.data?.name }}</el-descriptions-item>
 | 
				
			||||||
                <el-descriptions-item :span="1" label="id">{{ infoDialog.data?.id }}</el-descriptions-item>
 | 
					                <el-descriptions-item :span="1" label="id">{{ infoDialog.data?.id }}</el-descriptions-item>
 | 
				
			||||||
                <el-descriptions-item :span="3" label="数据库">{{ infoDialog.data?.database }}</el-descriptions-item>
 | 
					                <el-descriptions-item :span="3" label="数据库">{{ infoDialog.data?.database }}</el-descriptions-item>
 | 
				
			||||||
@@ -158,12 +154,12 @@
 | 
				
			|||||||
            </el-descriptions>
 | 
					            </el-descriptions>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <db-edit @val-change="valChange" :title="dbEditDialog.title" v-model:visible="dbEditDialog.visible" v-model:db="dbEditDialog.data"></db-edit>
 | 
					        <db-edit @val-change="search" :title="dbEditDialog.title" v-model:visible="dbEditDialog.visible" v-model:db="dbEditDialog.data"></db-edit>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted, defineAsyncComponent } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, defineAsyncComponent, Ref } from 'vue';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import { dbApi } from './api';
 | 
					import { dbApi } from './api';
 | 
				
			||||||
import config from '@/common/config';
 | 
					import config from '@/common/config';
 | 
				
			||||||
@@ -206,8 +202,7 @@ const actionBtns = hasPerms([perms.base, perms.saveDb]);
 | 
				
			|||||||
const actionColumn = TableColumn.new('action', '操作').isSlot().setMinWidth(220).fixedRight().alignCenter();
 | 
					const actionColumn = TableColumn.new('action', '操作').isSlot().setMinWidth(220).fixedRight().alignCenter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const route = useRoute();
 | 
					const route = useRoute();
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    row: {} as any,
 | 
					    row: {} as any,
 | 
				
			||||||
    dbId: 0,
 | 
					    dbId: 0,
 | 
				
			||||||
@@ -227,8 +222,6 @@ const state = reactive({
 | 
				
			|||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
        pageSize: 0,
 | 
					        pageSize: 0,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    datas: [],
 | 
					 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    infoDialog: {
 | 
					    infoDialog: {
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
        data: null as any,
 | 
					        data: null as any,
 | 
				
			||||||
@@ -265,33 +258,19 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { db, tags, selectionData, query, datas, total, infoDialog, sqlExecLogDialog, exportDialog, dbEditDialog } = toRefs(state);
 | 
					const { db, tags, selectionData, query, infoDialog, sqlExecLogDialog, exportDialog, dbEditDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    if (Object.keys(actionBtns).length > 0) {
 | 
					    if (Object.keys(actionBtns).length > 0) {
 | 
				
			||||||
        columns.value.push(actionColumn);
 | 
					        columns.value.push(actionColumn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    search();
 | 
					    if (route.query.tagPath) {
 | 
				
			||||||
 | 
					        state.query.tagPath = route.query.tagPath as string;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    try {
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (route.query.tagPath) {
 | 
					 | 
				
			||||||
            state.query.tagPath = route.query.tagPath as string;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        let res: any = await dbApi.dbs.request(state.query);
 | 
					 | 
				
			||||||
        // 切割数据库
 | 
					 | 
				
			||||||
        res.list?.forEach((e: any) => {
 | 
					 | 
				
			||||||
            e.popoverSelectDbVisible = false;
 | 
					 | 
				
			||||||
            e.dbs = e.database.split(' ');
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        state.datas = res.list;
 | 
					 | 
				
			||||||
        state.total = res.total;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showInfo = async (info: any) => {
 | 
					const showInfo = async (info: any) => {
 | 
				
			||||||
@@ -352,10 +331,6 @@ const editDb = async (data: any) => {
 | 
				
			|||||||
    state.dbEditDialog.visible = true;
 | 
					    state.dbEditDialog.visible = true;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const valChange = () => {
 | 
					 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const deleteDb = async () => {
 | 
					const deleteDb = async () => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        await ElMessageBox.confirm(`确定删除【${state.selectionData.map((x: any) => x.name).join(', ')}】库?`, '提示', {
 | 
					        await ElMessageBox.confirm(`确定删除【${state.selectionData.map((x: any) => x.name).join(', ')}】库?`, '提示', {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,6 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div class="db-sql-exec-log">
 | 
					    <div class="db-sql-exec-log">
 | 
				
			||||||
        <page-table
 | 
					        <page-table ref="pageTableRef" :page-api="dbApi.getSqlExecs" height="100%" :query="queryConfig" v-model:query-form="query" :columns="columns">
 | 
				
			||||||
            height="100%"
 | 
					 | 
				
			||||||
            ref="sqlExecDialogPageTableRef"
 | 
					 | 
				
			||||||
            :query="queryConfig"
 | 
					 | 
				
			||||||
            v-model:query-form="query"
 | 
					 | 
				
			||||||
            :data="data"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="searchSqlExecLog()"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
            <template #dbSelect>
 | 
					            <template #dbSelect>
 | 
				
			||||||
                <el-select v-model="query.db" placeholder="请选择数据库" style="width: 200px" filterable clearable>
 | 
					                <el-select v-model="query.db" placeholder="请选择数据库" style="width: 200px" filterable clearable>
 | 
				
			||||||
                    <el-option v-for="item in dbs" :key="item" :label="`${item}`" :value="item"> </el-option>
 | 
					                    <el-option v-for="item in dbs" :key="item" :label="`${item}`" :value="item"> </el-option>
 | 
				
			||||||
@@ -39,7 +28,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { toRefs, watch, reactive, onMounted } from 'vue';
 | 
					import { toRefs, watch, reactive, onMounted, Ref, ref } from 'vue';
 | 
				
			||||||
import { dbApi } from './api';
 | 
					import { dbApi } from './api';
 | 
				
			||||||
import { DbSqlExecTypeEnum } from './enums';
 | 
					import { DbSqlExecTypeEnum } from './enums';
 | 
				
			||||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
					import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			||||||
@@ -74,9 +63,9 @@ const columns = [
 | 
				
			|||||||
    TableColumn.new('action', '操作').isSlot().setMinWidth(90).fixedRight().alignCenter(),
 | 
					    TableColumn.new('action', '操作').isSlot().setMinWidth(90).fixedRight().alignCenter(),
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    data: [],
 | 
					 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    dbs: [],
 | 
					    dbs: [],
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
        dbId: 0,
 | 
					        dbId: 0,
 | 
				
			||||||
@@ -97,21 +86,18 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { data, query, total, rollbackSqlDialog } = toRefs(state);
 | 
					const { query, rollbackSqlDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {});
 | 
				
			||||||
    searchSqlExecLog();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, async () => {
 | 
					watch(props, async () => {
 | 
				
			||||||
 | 
					    state.query.dbId = props.dbId;
 | 
				
			||||||
 | 
					    state.query.pageNum = 1;
 | 
				
			||||||
    await searchSqlExecLog();
 | 
					    await searchSqlExecLog();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const searchSqlExecLog = async () => {
 | 
					const searchSqlExecLog = async () => {
 | 
				
			||||||
    state.query.dbId = props.dbId;
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
    const res = await dbApi.getSqlExecs.request(state.query);
 | 
					 | 
				
			||||||
    state.data = res.list;
 | 
					 | 
				
			||||||
    state.total = res.total;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const onShowRollbackSql = async (sqlExecLog: any) => {
 | 
					const onShowRollbackSql = async (sqlExecLog: any) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,9 +71,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div class="dialog-footer">
 | 
					                <div class="dialog-footer">
 | 
				
			||||||
                    <el-button @click="testConn" :loading="state.testConnBtnLoading" type="success">测试连接</el-button>
 | 
					                    <el-button @click="testConn" :loading="testConnBtnLoading" type="success">测试连接</el-button>
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -168,15 +168,17 @@ const state = reactive({
 | 
				
			|||||||
        remark: '',
 | 
					        remark: '',
 | 
				
			||||||
        sshTunnelMachineId: null as any,
 | 
					        sshTunnelMachineId: null as any,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    subimtForm: {},
 | 
				
			||||||
    // 原密码
 | 
					    // 原密码
 | 
				
			||||||
    pwd: '',
 | 
					    pwd: '',
 | 
				
			||||||
    // 原用户名
 | 
					    // 原用户名
 | 
				
			||||||
    oldUserName: null,
 | 
					    oldUserName: null,
 | 
				
			||||||
    btnLoading: false,
 | 
					 | 
				
			||||||
    testConnBtnLoading: false,
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, tabActiveName, form, pwd, btnLoading } = toRefs(state);
 | 
					const { dialogVisible, tabActiveName, form, subimtForm, pwd } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveInstanceExec } = dbApi.saveInstance.useApi(subimtForm);
 | 
				
			||||||
 | 
					const { isFetching: testConnBtnLoading, execute: testConnExec } = dbApi.testConn.useApi(subimtForm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, (newValue: any) => {
 | 
					watch(props, (newValue: any) => {
 | 
				
			||||||
    state.dialogVisible = newValue.visible;
 | 
					    state.dialogVisible = newValue.visible;
 | 
				
			||||||
@@ -214,18 +216,14 @@ const getReqForm = async () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const testConn = async () => {
 | 
					const testConn = async () => {
 | 
				
			||||||
    dbForm.value.validate(async (valid: boolean) => {
 | 
					    dbForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            state.testConnBtnLoading = true;
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                await dbApi.testConn.request(await getReqForm());
 | 
					 | 
				
			||||||
                ElMessage.success('连接成功');
 | 
					 | 
				
			||||||
            } finally {
 | 
					 | 
				
			||||||
                state.testConnBtnLoading = false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state.subimtForm = await getReqForm();
 | 
				
			||||||
 | 
					        await testConnExec();
 | 
				
			||||||
 | 
					        ElMessage.success('连接成功');
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -237,21 +235,16 @@ const btnOk = async () => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dbForm.value.validate(async (valid: boolean) => {
 | 
					    dbForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            dbApi.saveInstance.request(await getReqForm()).then(() => {
 | 
					 | 
				
			||||||
                ElMessage.success('保存成功');
 | 
					 | 
				
			||||||
                emit('val-change', state.form);
 | 
					 | 
				
			||||||
                state.btnLoading = true;
 | 
					 | 
				
			||||||
                setTimeout(() => {
 | 
					 | 
				
			||||||
                    state.btnLoading = false;
 | 
					 | 
				
			||||||
                }, 1000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                cancel();
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state.subimtForm = await getReqForm();
 | 
				
			||||||
 | 
					        await saveInstanceExec();
 | 
				
			||||||
 | 
					        ElMessage.success('保存成功');
 | 
				
			||||||
 | 
					        emit('val-change', state.form);
 | 
				
			||||||
 | 
					        cancel();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,16 +2,12 @@
 | 
				
			|||||||
    <div class="db-list">
 | 
					    <div class="db-list">
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
            ref="pageTableRef"
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="dbApi.instances"
 | 
				
			||||||
            :query="queryConfig"
 | 
					            :query="queryConfig"
 | 
				
			||||||
            v-model:query-form="query"
 | 
					            v-model:query-form="query"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="state.selectionData"
 | 
					            v-model:selection-data="state.selectionData"
 | 
				
			||||||
            :data="datas"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					            :columns="columns"
 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #queryRight>
 | 
					            <template #queryRight>
 | 
				
			||||||
                <el-button v-auth="perms.saveInstance" type="primary" icon="plus" @click="editInstance(false)">添加</el-button>
 | 
					                <el-button v-auth="perms.saveInstance" type="primary" icon="plus" @click="editInstance(false)">添加</el-button>
 | 
				
			||||||
@@ -56,7 +52,7 @@
 | 
				
			|||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <instance-edit
 | 
					        <instance-edit
 | 
				
			||||||
            @val-change="valChange"
 | 
					            @val-change="search"
 | 
				
			||||||
            :title="instanceEditDialog.title"
 | 
					            :title="instanceEditDialog.title"
 | 
				
			||||||
            v-model:visible="instanceEditDialog.visible"
 | 
					            v-model:visible="instanceEditDialog.visible"
 | 
				
			||||||
            v-model:data="instanceEditDialog.data"
 | 
					            v-model:data="instanceEditDialog.data"
 | 
				
			||||||
@@ -65,7 +61,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted, defineAsyncComponent } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, defineAsyncComponent, Ref } from 'vue';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import { dbApi } from './api';
 | 
					import { dbApi } from './api';
 | 
				
			||||||
import { dateFormat } from '@/common/utils/date';
 | 
					import { dateFormat } from '@/common/utils/date';
 | 
				
			||||||
@@ -96,8 +92,7 @@ const columns = ref([
 | 
				
			|||||||
// 该用户拥有的的操作列按钮权限
 | 
					// 该用户拥有的的操作列按钮权限
 | 
				
			||||||
const actionBtns = hasPerms([perms.saveInstance]);
 | 
					const actionBtns = hasPerms([perms.saveInstance]);
 | 
				
			||||||
const actionColumn = TableColumn.new('action', '操作').isSlot().setMinWidth(110).fixedRight().alignCenter();
 | 
					const actionColumn = TableColumn.new('action', '操作').isSlot().setMinWidth(110).fixedRight().alignCenter();
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    row: {},
 | 
					    row: {},
 | 
				
			||||||
@@ -115,8 +110,6 @@ const state = reactive({
 | 
				
			|||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
        pageSize: 0,
 | 
					        pageSize: 0,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    datas: [],
 | 
					 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    infoDialog: {
 | 
					    infoDialog: {
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
        data: null as any,
 | 
					        data: null as any,
 | 
				
			||||||
@@ -128,24 +121,16 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { selectionData, query, datas, total, infoDialog, instanceEditDialog } = toRefs(state);
 | 
					const { selectionData, query, infoDialog, instanceEditDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    if (Object.keys(actionBtns).length > 0) {
 | 
					    if (Object.keys(actionBtns).length > 0) {
 | 
				
			||||||
        columns.value.push(actionColumn);
 | 
					        columns.value.push(actionColumn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = () => {
 | 
				
			||||||
    try {
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
        let res: any = await dbApi.instances.request(state.query);
 | 
					 | 
				
			||||||
        state.datas = res.list;
 | 
					 | 
				
			||||||
        state.total = res.total;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showInfo = (info: any) => {
 | 
					const showInfo = (info: any) => {
 | 
				
			||||||
@@ -164,10 +149,6 @@ const editInstance = async (data: any) => {
 | 
				
			|||||||
    state.instanceEditDialog.visible = true;
 | 
					    state.instanceEditDialog.visible = true;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const valChange = () => {
 | 
					 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const deleteInstance = async () => {
 | 
					const deleteInstance = async () => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        await ElMessageBox.confirm(`确定删除数据库实例【${state.selectionData.map((x: any) => x.name).join(', ')}】?`, '提示', {
 | 
					        await ElMessageBox.confirm(`确定删除数据库实例【${state.selectionData.map((x: any) => x.name).join(', ')}】?`, '提示', {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ export const dbApi = {
 | 
				
			|||||||
        if (param.sql) {
 | 
					        if (param.sql) {
 | 
				
			||||||
            param.sql = Base64.encode(param.sql);
 | 
					            param.sql = Base64.encode(param.sql);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        return param;
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
    // 保存sql
 | 
					    // 保存sql
 | 
				
			||||||
    saveSql: Api.newPost('/dbs/{id}/sql'),
 | 
					    saveSql: Api.newPost('/dbs/{id}/sql'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,7 +111,7 @@
 | 
				
			|||||||
                                :table="dt.table"
 | 
					                                :table="dt.table"
 | 
				
			||||||
                                :columns="dt.tableColumn"
 | 
					                                :columns="dt.tableColumn"
 | 
				
			||||||
                                :loading="dt.loading"
 | 
					                                :loading="dt.loading"
 | 
				
			||||||
                                :loading-key="dt.loadingKey"
 | 
					                                :abort-fn="dt.abortFn"
 | 
				
			||||||
                                :height="tableDataHeight"
 | 
					                                :height="tableDataHeight"
 | 
				
			||||||
                                empty-text="tips: select *开头的单表查询或点击表名默认查询的数据,可双击数据在线修改"
 | 
					                                empty-text="tips: select *开头的单表查询或点击表名默认查询的数据,可双击数据在线修改"
 | 
				
			||||||
                                @change-updated-field="changeUpdatedField($event, dt)"
 | 
					                                @change-updated-field="changeUpdatedField($event, dt)"
 | 
				
			||||||
@@ -128,7 +128,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { h, nextTick, onMounted, reactive, toRefs, ref, onBeforeUnmount } from 'vue';
 | 
					import { h, nextTick, onMounted, reactive, toRefs, ref } from 'vue';
 | 
				
			||||||
import { getToken } from '@/common/utils/storage';
 | 
					import { getToken } from '@/common/utils/storage';
 | 
				
			||||||
import { notBlank } from '@/common/assert';
 | 
					import { notBlank } from '@/common/assert';
 | 
				
			||||||
import { format as sqlFormatter } from 'sql-formatter';
 | 
					import { format as sqlFormatter } from 'sql-formatter';
 | 
				
			||||||
@@ -151,7 +151,6 @@ import syssocket from '@/common/syssocket';
 | 
				
			|||||||
import SvgIcon from '@/components/svgIcon/index.vue';
 | 
					import SvgIcon from '@/components/svgIcon/index.vue';
 | 
				
			||||||
import { getDbDialect } from '../../dialect';
 | 
					import { getDbDialect } from '../../dialect';
 | 
				
			||||||
import { Splitpanes, Pane } from 'splitpanes';
 | 
					import { Splitpanes, Pane } from 'splitpanes';
 | 
				
			||||||
import Api from '@/common/Api';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const emits = defineEmits(['saveSqlSuccess']);
 | 
					const emits = defineEmits(['saveSqlSuccess']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -178,12 +177,15 @@ class ExecResTab {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    sql: string;
 | 
					    sql: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    loading: boolean;
 | 
					    /**
 | 
				
			||||||
 | 
					     * 响应式loading
 | 
				
			||||||
    loadingKey: string;
 | 
					     */
 | 
				
			||||||
 | 
					    loading: any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dbTableRef: any;
 | 
					    dbTableRef: any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    abortFn: Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tableColumn: any[] = [];
 | 
					    tableColumn: any[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    data: any[] = [];
 | 
					    data: any[] = [];
 | 
				
			||||||
@@ -252,12 +254,6 @@ onMounted(async () => {
 | 
				
			|||||||
    await getNowDbInst().loadDbHints(props.dbName);
 | 
					    await getNowDbInst().loadDbHints(props.dbName);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onBeforeUnmount(() => {
 | 
					 | 
				
			||||||
    state.execResTabs.forEach((x: ExecResTab) => {
 | 
					 | 
				
			||||||
        Api.removeAbortKey(x.loadingKey);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const onRemoveTab = (targetId: number) => {
 | 
					const onRemoveTab = (targetId: number) => {
 | 
				
			||||||
    let activeTab = state.activeTab;
 | 
					    let activeTab = state.activeTab;
 | 
				
			||||||
    const tabs = [...state.execResTabs];
 | 
					    const tabs = [...state.execResTabs];
 | 
				
			||||||
@@ -339,7 +335,7 @@ const onRunSql = async (newTab = false) => {
 | 
				
			|||||||
        // 不是新建tab执行,则在当前激活的tab上执行sql
 | 
					        // 不是新建tab执行,则在当前激活的tab上执行sql
 | 
				
			||||||
        i = state.execResTabs.findIndex((x) => x.id == state.activeTab);
 | 
					        i = state.execResTabs.findIndex((x) => x.id == state.activeTab);
 | 
				
			||||||
        execRes = state.execResTabs[i];
 | 
					        execRes = state.execResTabs[i];
 | 
				
			||||||
        if (execRes.loading) {
 | 
					        if (execRes.loading?.value) {
 | 
				
			||||||
            ElMessage.error('当前结果集tab正在执行, 请使用新标签执行');
 | 
					            ElMessage.error('当前结果集tab正在执行, 请使用新标签执行');
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -349,18 +345,19 @@ const onRunSql = async (newTab = false) => {
 | 
				
			|||||||
    state.activeTab = id;
 | 
					    state.activeTab = id;
 | 
				
			||||||
    const startTime = new Date().getTime();
 | 
					    const startTime = new Date().getTime();
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
        execRes.loading = true;
 | 
					 | 
				
			||||||
        execRes.errorMsg = '';
 | 
					        execRes.errorMsg = '';
 | 
				
			||||||
        execRes.sql = '';
 | 
					        execRes.sql = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 用于取消执行
 | 
					        const { data, execute, isFetching, abort } = getNowDbInst().execSql(props.dbName, sql, execRemark);
 | 
				
			||||||
        const loadingKey = Api.genAbortKey(execRes.loadingKey);
 | 
					        execRes.loading = isFetching;
 | 
				
			||||||
        execRes.loadingKey = loadingKey;
 | 
					        execRes.abortFn = abort;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const colAndData: any = await getNowDbInst().runSql(props.dbName, sql, execRemark, loadingKey);
 | 
					        await execute();
 | 
				
			||||||
 | 
					        const colAndData: any = data.value;
 | 
				
			||||||
        if (!colAndData.res || colAndData.res.length === 0) {
 | 
					        if (!colAndData.res || colAndData.res.length === 0) {
 | 
				
			||||||
            ElMessage.warning('未查询到结果集');
 | 
					            ElMessage.warning('未查询到结果集');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 要实时响应,故需要用索引改变数据才生效
 | 
					        // 要实时响应,故需要用索引改变数据才生效
 | 
				
			||||||
        state.execResTabs[i].data = colAndData.res;
 | 
					        state.execResTabs[i].data = colAndData.res;
 | 
				
			||||||
        // 兼容表格字段配置
 | 
					        // 兼容表格字段配置
 | 
				
			||||||
@@ -378,7 +375,6 @@ const onRunSql = async (newTab = false) => {
 | 
				
			|||||||
        execRes.errorMsg = e.msg;
 | 
					        execRes.errorMsg = e.msg;
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    } finally {
 | 
					    } finally {
 | 
				
			||||||
        state.execResTabs[i].loading = false;
 | 
					 | 
				
			||||||
        execRes.sql = sql;
 | 
					        execRes.sql = sql;
 | 
				
			||||||
        execRes.execTime = new Date().getTime() - startTime;
 | 
					        execRes.execTime = new Date().getTime() - startTime;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -96,7 +96,7 @@
 | 
				
			|||||||
                                <SvgIcon class="is-loading" name="loading" color="var(--el-color-primary)" :size="28" />
 | 
					                                <SvgIcon class="is-loading" name="loading" color="var(--el-color-primary)" :size="28" />
 | 
				
			||||||
                                <el-text class="ml5" tag="b">执行时间 - {{ state.execTime.toFixed(1) }}s</el-text>
 | 
					                                <el-text class="ml5" tag="b">执行时间 - {{ state.execTime.toFixed(1) }}s</el-text>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                            <div v-if="loadingKey" class="mt10">
 | 
					                            <div v-if="loading && abortFn" class="mt10">
 | 
				
			||||||
                                <el-button @click="cancelLoading" type="info" size="small" plain>取 消</el-button>
 | 
					                                <el-button @click="cancelLoading" type="info" size="small" plain>取 消</el-button>
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
@@ -133,7 +133,6 @@ import { ContextmenuItem, Contextmenu } from '@/components/contextmenu';
 | 
				
			|||||||
import SvgIcon from '@/components/svgIcon/index.vue';
 | 
					import SvgIcon from '@/components/svgIcon/index.vue';
 | 
				
			||||||
import { exportCsv, exportFile } from '@/common/utils/export';
 | 
					import { exportCsv, exportFile } from '@/common/utils/export';
 | 
				
			||||||
import { dateStrFormat } from '@/common/utils/date';
 | 
					import { dateStrFormat } from '@/common/utils/date';
 | 
				
			||||||
import Api from '@/common/Api';
 | 
					 | 
				
			||||||
import { useIntervalFn } from '@vueuse/core';
 | 
					import { useIntervalFn } from '@vueuse/core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const emits = defineEmits(['dataDelete', 'sortChange', 'deleteData', 'selectionChange', 'changeUpdatedField']);
 | 
					const emits = defineEmits(['dataDelete', 'sortChange', 'deleteData', 'selectionChange', 'changeUpdatedField']);
 | 
				
			||||||
@@ -165,8 +164,8 @@ const props = defineProps({
 | 
				
			|||||||
        type: Boolean,
 | 
					        type: Boolean,
 | 
				
			||||||
        default: false,
 | 
					        default: false,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    loadingKey: {
 | 
					    abortFn: {
 | 
				
			||||||
        type: String,
 | 
					        type: Function,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    emptyText: {
 | 
					    emptyText: {
 | 
				
			||||||
        type: String,
 | 
					        type: String,
 | 
				
			||||||
@@ -441,10 +440,8 @@ const endLoading = () => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const cancelLoading = async () => {
 | 
					const cancelLoading = async () => {
 | 
				
			||||||
    if (props.loadingKey) {
 | 
					    props.abortFn && props.abortFn();
 | 
				
			||||||
        Api.cancelReq(props.loadingKey);
 | 
					    endLoading();
 | 
				
			||||||
        endLoading();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -196,16 +196,7 @@ export class DbInst {
 | 
				
			|||||||
     * @param sql sql
 | 
					     * @param sql sql
 | 
				
			||||||
     * @param remark 执行备注
 | 
					     * @param remark 执行备注
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    async runSql(dbName: string, sql: string, remark: string = '', key: string = '') {
 | 
					    async runSql(dbName: string, sql: string, remark: string = '') {
 | 
				
			||||||
        if (key) {
 | 
					 | 
				
			||||||
            return await dbApi.sqlExec.allowCancelReq(key, {
 | 
					 | 
				
			||||||
                id: this.id,
 | 
					 | 
				
			||||||
                db: dbName,
 | 
					 | 
				
			||||||
                sql: sql.trim(),
 | 
					 | 
				
			||||||
                remark,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return await dbApi.sqlExec.request({
 | 
					        return await dbApi.sqlExec.request({
 | 
				
			||||||
            id: this.id,
 | 
					            id: this.id,
 | 
				
			||||||
            db: dbName,
 | 
					            db: dbName,
 | 
				
			||||||
@@ -214,6 +205,22 @@ export class DbInst {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 执行sql(可取消的)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param sql sql
 | 
				
			||||||
 | 
					     * @param remark 执行备注
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    execSql(dbName: string, sql: string, remark: string = '') {
 | 
				
			||||||
 | 
					        let dbId = this.id;
 | 
				
			||||||
 | 
					        return dbApi.sqlExec.useApi({
 | 
				
			||||||
 | 
					            id: dbId,
 | 
				
			||||||
 | 
					            db: dbName,
 | 
				
			||||||
 | 
					            sql: sql.trim(),
 | 
				
			||||||
 | 
					            remark,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 获取count sql
 | 
					     * 获取count sql
 | 
				
			||||||
     * @param table 表名
 | 
					     * @param table 表名
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,6 +118,9 @@ let postgresDialect = new PostgresqlDialect();
 | 
				
			|||||||
let dmDialect = new DMDialect();
 | 
					let dmDialect = new DMDialect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getDbDialect = (dbType: string | undefined): DbDialect => {
 | 
					export const getDbDialect = (dbType: string | undefined): DbDialect => {
 | 
				
			||||||
 | 
					    if (!dbType) {
 | 
				
			||||||
 | 
					        return mysqlDialect;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (dbType === DbType.mysql) {
 | 
					    if (dbType === DbType.mysql) {
 | 
				
			||||||
        return mysqlDialect;
 | 
					        return mysqlDialect;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@
 | 
				
			|||||||
                <div>
 | 
					                <div>
 | 
				
			||||||
                    <el-button @click="testConn" :loading="testConnBtnLoading" type="success">测试连接</el-button>
 | 
					                    <el-button @click="testConn" :loading="testConnBtnLoading" type="success">测试连接</el-button>
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -164,12 +164,14 @@ const state = reactive({
 | 
				
			|||||||
        sshTunnelMachineId: null as any,
 | 
					        sshTunnelMachineId: null as any,
 | 
				
			||||||
        enableRecorder: -1,
 | 
					        enableRecorder: -1,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    submitForm: {},
 | 
				
			||||||
    pwd: '',
 | 
					    pwd: '',
 | 
				
			||||||
    testConnBtnLoading: false,
 | 
					 | 
				
			||||||
    btnLoading: false,
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, tabActiveName, form, testConnBtnLoading, btnLoading } = toRefs(state);
 | 
					const { dialogVisible, tabActiveName, form, submitForm } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: testConnBtnLoading, execute: testConnExec } = machineApi.testConn.useApi(submitForm);
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveMachineExec } = machineApi.saveMachine.useApi(submitForm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, async (newValue: any) => {
 | 
					watch(props, async (newValue: any) => {
 | 
				
			||||||
    state.dialogVisible = newValue.visible;
 | 
					    state.dialogVisible = newValue.visible;
 | 
				
			||||||
@@ -205,45 +207,29 @@ const changeAuthMethod = (val: any) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const testConn = async () => {
 | 
					const testConn = async () => {
 | 
				
			||||||
    machineForm.value.validate(async (valid: boolean) => {
 | 
					    machineForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            const form = getReqForm();
 | 
					 | 
				
			||||||
            if (!form) {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            state.testConnBtnLoading = true;
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                await machineApi.testConn.request(form);
 | 
					 | 
				
			||||||
                ElMessage.success('连接成功');
 | 
					 | 
				
			||||||
            } finally {
 | 
					 | 
				
			||||||
                state.testConnBtnLoading = false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state.submitForm = getReqForm();
 | 
				
			||||||
 | 
					        await testConnExec();
 | 
				
			||||||
 | 
					        ElMessage.success('连接成功');
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const btnOk = async () => {
 | 
					const btnOk = async () => {
 | 
				
			||||||
    machineForm.value.validate(async (valid: boolean) => {
 | 
					    machineForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            const form = getReqForm();
 | 
					 | 
				
			||||||
            if (!form) {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            state.btnLoading = true;
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                await machineApi.saveMachine.request(form);
 | 
					 | 
				
			||||||
                ElMessage.success('保存成功');
 | 
					 | 
				
			||||||
                emit('val-change', form);
 | 
					 | 
				
			||||||
                cancel();
 | 
					 | 
				
			||||||
            } finally {
 | 
					 | 
				
			||||||
                state.btnLoading = false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state.submitForm = getReqForm();
 | 
				
			||||||
 | 
					        await saveMachineExec();
 | 
				
			||||||
 | 
					        ElMessage.success('保存成功');
 | 
				
			||||||
 | 
					        emit('val-change', submitForm);
 | 
				
			||||||
 | 
					        cancel();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,16 +2,12 @@
 | 
				
			|||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
            ref="pageTableRef"
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="machineApi.list"
 | 
				
			||||||
            :query="queryConfig"
 | 
					            :query="queryConfig"
 | 
				
			||||||
            v-model:query-form="params"
 | 
					            v-model:query-form="params"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="state.selectionData"
 | 
					            v-model:selection-data="state.selectionData"
 | 
				
			||||||
            :data="data.list"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					            :columns="columns"
 | 
				
			||||||
            :total="data.total"
 | 
					 | 
				
			||||||
            v-model:page-size="params.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="params.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #tagPathSelect>
 | 
					            <template #tagPathSelect>
 | 
				
			||||||
                <el-select @focus="getTags" v-model="params.tagPath" placeholder="请选择标签" @clear="search" filterable clearable style="width: 200px">
 | 
					                <el-select @focus="getTags" v-model="params.tagPath" placeholder="请选择标签" @clear="search" filterable clearable style="width: 200px">
 | 
				
			||||||
@@ -186,7 +182,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted, defineAsyncComponent } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, defineAsyncComponent, Ref } from 'vue';
 | 
				
			||||||
import { useRouter, useRoute } from 'vue-router';
 | 
					import { useRouter, useRoute } from 'vue-router';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import { machineApi, getMachineTerminalSocketUrl } from './api';
 | 
					import { machineApi, getMachineTerminalSocketUrl } from './api';
 | 
				
			||||||
@@ -210,8 +206,8 @@ const ProcessList = defineAsyncComponent(() => import('./ProcessList.vue'));
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const router = useRouter();
 | 
					const router = useRouter();
 | 
				
			||||||
const route = useRoute();
 | 
					const route = useRoute();
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					 | 
				
			||||||
const terminalDialogRef: any = ref(null);
 | 
					const terminalDialogRef: any = ref(null);
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const perms = {
 | 
					const perms = {
 | 
				
			||||||
    addMachine: 'machine:add',
 | 
					    addMachine: 'machine:add',
 | 
				
			||||||
@@ -247,11 +243,6 @@ const state = reactive({
 | 
				
			|||||||
        name: null,
 | 
					        name: null,
 | 
				
			||||||
        tagPath: '',
 | 
					        tagPath: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    // 列表数据
 | 
					 | 
				
			||||||
    data: {
 | 
					 | 
				
			||||||
        list: [],
 | 
					 | 
				
			||||||
        total: 10,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    infoDialog: {
 | 
					    infoDialog: {
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
        data: null as any,
 | 
					        data: null as any,
 | 
				
			||||||
@@ -290,11 +281,13 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { tags, params, data, infoDialog, selectionData, serviceDialog, processDialog, fileDialog, machineStatsDialog, machineEditDialog, machineRecDialog } =
 | 
					const { tags, params, infoDialog, selectionData, serviceDialog, processDialog, fileDialog, machineStatsDialog, machineEditDialog, machineRecDialog } =
 | 
				
			||||||
    toRefs(state);
 | 
					    toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    search();
 | 
					    if (route.query.tagPath) {
 | 
				
			||||||
 | 
					        state.params.tagPath = route.query.tagPath as string;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const handleCommand = (commond: any) => {
 | 
					const handleCommand = (commond: any) => {
 | 
				
			||||||
@@ -421,6 +414,10 @@ const showMachineStats = async (machine: any) => {
 | 
				
			|||||||
    state.machineStatsDialog.visible = true;
 | 
					    state.machineStatsDialog.visible = true;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const search = async () => {
 | 
				
			||||||
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const submitSuccess = () => {
 | 
					const submitSuccess = () => {
 | 
				
			||||||
    search();
 | 
					    search();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -431,19 +428,6 @@ const showFileManage = (selectionData: any) => {
 | 
				
			|||||||
    state.fileDialog.title = `${selectionData.name} => ${selectionData.ip}`;
 | 
					    state.fileDialog.title = `${selectionData.name} => ${selectionData.ip}`;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
        if (route.query.tagPath) {
 | 
					 | 
				
			||||||
            state.params.tagPath = route.query.tagPath as string;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const res = await machineApi.list.request(state.params);
 | 
					 | 
				
			||||||
        state.data = res;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const getStatsFontClass = (availavle: number, total: number) => {
 | 
					const getStatsFontClass = (availavle: number, total: number) => {
 | 
				
			||||||
    const p = availavle / total;
 | 
					    const p = availavle / total;
 | 
				
			||||||
    if (p < 0.1) {
 | 
					    if (p < 0.1) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,14 +11,11 @@
 | 
				
			|||||||
        >
 | 
					        >
 | 
				
			||||||
            <page-table
 | 
					            <page-table
 | 
				
			||||||
                ref="pageTableRef"
 | 
					                ref="pageTableRef"
 | 
				
			||||||
 | 
					                :page-api="machineApi.scripts"
 | 
				
			||||||
 | 
					                :lazy="true"
 | 
				
			||||||
                :query="queryConfig"
 | 
					                :query="queryConfig"
 | 
				
			||||||
                v-model:query-form="query"
 | 
					                v-model:query-form="query"
 | 
				
			||||||
                :data="scriptTable"
 | 
					 | 
				
			||||||
                :columns="columns"
 | 
					                :columns="columns"
 | 
				
			||||||
                :total="total"
 | 
					 | 
				
			||||||
                v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
                v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
                @pageChange="getScripts()"
 | 
					 | 
				
			||||||
                :show-selection="true"
 | 
					                :show-selection="true"
 | 
				
			||||||
                v-model:selection-data="selectionData"
 | 
					                v-model:selection-data="selectionData"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
@@ -88,7 +85,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, watch } from 'vue';
 | 
					import { ref, toRefs, reactive, watch, Ref } from 'vue';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import TerminalBody from '@/components/terminal/TerminalBody.vue';
 | 
					import TerminalBody from '@/components/terminal/TerminalBody.vue';
 | 
				
			||||||
import { getMachineTerminalSocketUrl, machineApi } from './api';
 | 
					import { getMachineTerminalSocketUrl, machineApi } from './api';
 | 
				
			||||||
@@ -107,7 +104,7 @@ const props = defineProps({
 | 
				
			|||||||
const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
 | 
					const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const paramsForm: any = ref(null);
 | 
					const paramsForm: any = ref(null);
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    dialogVisible: false,
 | 
					    dialogVisible: false,
 | 
				
			||||||
@@ -150,24 +147,15 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, queryConfig, columns, selectionData, query, editDialog, total, scriptTable, scriptParamsDialog, resultDialog, terminalDialog } =
 | 
					const { dialogVisible, queryConfig, columns, selectionData, query, editDialog, scriptParamsDialog, resultDialog, terminalDialog } = toRefs(state);
 | 
				
			||||||
    toRefs(state);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, async (newValue) => {
 | 
					watch(props, async (newValue) => {
 | 
				
			||||||
    state.dialogVisible = newValue.visible;
 | 
					    state.dialogVisible = newValue.visible;
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getScripts = async () => {
 | 
					const getScripts = async () => {
 | 
				
			||||||
    try {
 | 
					    state.query.machineId = state.query.type == ScriptTypeEnum.Private.value ? props.machineId : 9999999;
 | 
				
			||||||
        // 通过open事件才开获取到pageTableRef值
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
        state.query.machineId = state.query.type == ScriptTypeEnum.Private.value ? props.machineId : 9999999;
 | 
					 | 
				
			||||||
        const res = await machineApi.scripts.request(state.query);
 | 
					 | 
				
			||||||
        state.scriptTable = res.list;
 | 
					 | 
				
			||||||
        state.total = res.total;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const runScript = async (script: any) => {
 | 
					const runScript = async (script: any) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,13 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="authCertApi.list"
 | 
				
			||||||
            :query="state.queryConfig"
 | 
					            :query="state.queryConfig"
 | 
				
			||||||
            v-model:query-form="query"
 | 
					            v-model:query-form="query"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="selectionData"
 | 
					            v-model:selection-data="selectionData"
 | 
				
			||||||
            :data="authcerts"
 | 
					 | 
				
			||||||
            :columns="state.columns"
 | 
					            :columns="state.columns"
 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #queryRight>
 | 
					            <template #queryRight>
 | 
				
			||||||
                <el-button type="primary" icon="plus" @click="edit(false)">添加</el-button>
 | 
					                <el-button type="primary" icon="plus" @click="edit(false)">添加</el-button>
 | 
				
			||||||
@@ -27,7 +24,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { toRefs, reactive, onMounted } from 'vue';
 | 
					import { toRefs, reactive, onMounted, ref, Ref } from 'vue';
 | 
				
			||||||
import AuthCertEdit from './AuthCertEdit.vue';
 | 
					import AuthCertEdit from './AuthCertEdit.vue';
 | 
				
			||||||
import { authCertApi } from '../api';
 | 
					import { authCertApi } from '../api';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
@@ -35,6 +32,7 @@ import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			|||||||
import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
					import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
				
			||||||
import { AuthMethodEnum } from '../enums';
 | 
					import { AuthMethodEnum } from '../enums';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
@@ -68,16 +66,12 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { query, total, authcerts, selectionData, editor } = toRefs(state);
 | 
					const { query, selectionData, editor } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {});
 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    let res = await authCertApi.list.request(state.query);
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
    state.authcerts = res.list;
 | 
					 | 
				
			||||||
    state.total = res.total;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const editChange = () => {
 | 
					const editChange = () => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <el-dialog
 | 
					        <el-dialog
 | 
				
			||||||
 | 
					            @open="search()"
 | 
				
			||||||
            :title="title"
 | 
					            :title="title"
 | 
				
			||||||
            v-model="dialogVisible"
 | 
					            v-model="dialogVisible"
 | 
				
			||||||
            :close-on-click-modal="false"
 | 
					            :close-on-click-modal="false"
 | 
				
			||||||
@@ -11,14 +12,13 @@
 | 
				
			|||||||
        >
 | 
					        >
 | 
				
			||||||
            <page-table
 | 
					            <page-table
 | 
				
			||||||
                ref="pageTableRef"
 | 
					                ref="pageTableRef"
 | 
				
			||||||
 | 
					                :page-api="cronJobApi.execList"
 | 
				
			||||||
 | 
					                :lazy="true"
 | 
				
			||||||
 | 
					                :data-handler-fn="parseData"
 | 
				
			||||||
                :query="queryConfig"
 | 
					                :query="queryConfig"
 | 
				
			||||||
                v-model:query-form="params"
 | 
					                v-model:query-form="params"
 | 
				
			||||||
                :data="state.data.list"
 | 
					                :data="state.data.list"
 | 
				
			||||||
                :columns="columns"
 | 
					                :columns="columns"
 | 
				
			||||||
                :total="state.data.total"
 | 
					 | 
				
			||||||
                v-model:page-size="params.pageSize"
 | 
					 | 
				
			||||||
                v-model:page-num="params.pageNum"
 | 
					 | 
				
			||||||
                @pageChange="search()"
 | 
					 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
                <template #machineSelect>
 | 
					                <template #machineSelect>
 | 
				
			||||||
                    <el-select v-model="params.machineId" filterable placeholder="选择机器查询" style="width: 200px" clearable>
 | 
					                    <el-select v-model="params.machineId" filterable placeholder="选择机器查询" style="width: 200px" clearable>
 | 
				
			||||||
@@ -35,7 +35,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { watch, ref, toRefs, reactive } from 'vue';
 | 
					import { watch, ref, toRefs, reactive, Ref } from 'vue';
 | 
				
			||||||
import { cronJobApi, machineApi } from '../api';
 | 
					import { cronJobApi, machineApi } from '../api';
 | 
				
			||||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
					import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			||||||
import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
					import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
				
			||||||
@@ -68,6 +68,8 @@ const columns = ref([
 | 
				
			|||||||
    TableColumn.new('execTime', '执行时间').isTime().setMinWidth(150),
 | 
					    TableColumn.new('execTime', '执行时间').isTime().setMinWidth(150),
 | 
				
			||||||
]);
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    dialogVisible: false,
 | 
					    dialogVisible: false,
 | 
				
			||||||
    tags: [] as any,
 | 
					    tags: [] as any,
 | 
				
			||||||
@@ -108,17 +110,15 @@ watch(props, async (newValue: any) => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state.params.cronJobId = props.data?.id;
 | 
					    state.params.cronJobId = props.data?.id;
 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    const res = await cronJobApi.execList.request(state.params);
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
    if (!res.list) {
 | 
					};
 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const parseData = async (dataList: any) => {
 | 
				
			||||||
    // 填充机器信息
 | 
					    // 填充机器信息
 | 
				
			||||||
    for (let x of res.list) {
 | 
					    for (let x of dataList) {
 | 
				
			||||||
        const machineId = x.machineId;
 | 
					        const machineId = x.machineId;
 | 
				
			||||||
        let machine = machineMap.get(machineId);
 | 
					        let machine = machineMap.get(machineId);
 | 
				
			||||||
        // 如果未找到,则可能被移除,则调接口查询机器信息
 | 
					        // 如果未找到,则可能被移除,则调接口查询机器信息
 | 
				
			||||||
@@ -139,8 +139,7 @@ const search = async () => {
 | 
				
			|||||||
        x.machineIp = machine?.ip;
 | 
					        x.machineIp = machine?.ip;
 | 
				
			||||||
        x.machineName = machine?.name;
 | 
					        x.machineName = machine?.name;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return dataList;
 | 
				
			||||||
    state.data = res;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const cancel = () => {
 | 
					const cancel = () => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,16 +2,12 @@
 | 
				
			|||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
            ref="pageTableRef"
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="cronJobApi.list"
 | 
				
			||||||
            :query="queryConfig"
 | 
					            :query="queryConfig"
 | 
				
			||||||
            v-model:query-form="params"
 | 
					            v-model:query-form="params"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="state.selectionData"
 | 
					            v-model:selection-data="state.selectionData"
 | 
				
			||||||
            :data="data.list"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					            :columns="columns"
 | 
				
			||||||
            :total="data.total"
 | 
					 | 
				
			||||||
            v-model:page-size="params.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="params.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #queryRight>
 | 
					            <template #queryRight>
 | 
				
			||||||
                <el-button v-auth="perms.saveCronJob" type="primary" icon="plus" @click="openFormDialog(false)" plain>添加 </el-button>
 | 
					                <el-button v-auth="perms.saveCronJob" type="primary" icon="plus" @click="openFormDialog(false)" plain>添加 </el-button>
 | 
				
			||||||
@@ -38,7 +34,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted, defineAsyncComponent } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, defineAsyncComponent, Ref } from 'vue';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import { cronJobApi } from '../api';
 | 
					import { cronJobApi } from '../api';
 | 
				
			||||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
					import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			||||||
@@ -48,8 +44,6 @@ import { CronJobStatusEnum, CronJobSaveExecResTypeEnum } from '../enums';
 | 
				
			|||||||
const CronJobEdit = defineAsyncComponent(() => import('./CronJobEdit.vue'));
 | 
					const CronJobEdit = defineAsyncComponent(() => import('./CronJobEdit.vue'));
 | 
				
			||||||
const CronJobExecList = defineAsyncComponent(() => import('./CronJobExecList.vue'));
 | 
					const CronJobExecList = defineAsyncComponent(() => import('./CronJobExecList.vue'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const perms = {
 | 
					const perms = {
 | 
				
			||||||
    saveCronJob: 'machine:cronjob:save',
 | 
					    saveCronJob: 'machine:cronjob:save',
 | 
				
			||||||
    delCronJob: 'machine:cronjob:del',
 | 
					    delCronJob: 'machine:cronjob:del',
 | 
				
			||||||
@@ -69,6 +63,8 @@ const columns = ref([
 | 
				
			|||||||
    TableColumn.new('action', '操作').isSlot().setMinWidth(180).fixedRight().alignCenter(),
 | 
					    TableColumn.new('action', '操作').isSlot().setMinWidth(180).fixedRight().alignCenter(),
 | 
				
			||||||
]);
 | 
					]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    params: {
 | 
					    params: {
 | 
				
			||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
@@ -76,11 +72,6 @@ const state = reactive({
 | 
				
			|||||||
        ip: null,
 | 
					        ip: null,
 | 
				
			||||||
        name: null,
 | 
					        name: null,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    // 列表数据
 | 
					 | 
				
			||||||
    data: {
 | 
					 | 
				
			||||||
        list: [],
 | 
					 | 
				
			||||||
        total: 10,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    selectionData: [],
 | 
					    selectionData: [],
 | 
				
			||||||
    execDialog: {
 | 
					    execDialog: {
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
@@ -94,11 +85,9 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { selectionData, params, data, execDialog, cronJobEdit } = toRefs(state);
 | 
					const { selectionData, params, execDialog, cronJobEdit } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {});
 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const openFormDialog = async (data: any) => {
 | 
					const openFormDialog = async (data: any) => {
 | 
				
			||||||
    let dialogTitle;
 | 
					    let dialogTitle;
 | 
				
			||||||
@@ -143,13 +132,7 @@ const showExec = async (data: any) => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    try {
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
        const res = await cronJobApi.list.request(state.params);
 | 
					 | 
				
			||||||
        state.data = res;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -639,7 +639,7 @@ function uploadFolder(e: any) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // 上传操作
 | 
					        // 上传操作
 | 
				
			||||||
        machineApi.uploadFile
 | 
					        machineApi.uploadFile
 | 
				
			||||||
            .request(form, {
 | 
					            .xhrReq(form, {
 | 
				
			||||||
                url: `${config.baseApiUrl}/machines/${props.machineId}/files/${props.fileId}/upload-folder?${joinClientParams()}`,
 | 
					                url: `${config.baseApiUrl}/machines/${props.machineId}/files/${props.fileId}/upload-folder?${joinClientParams()}`,
 | 
				
			||||||
                headers: { 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryF1uyUD0tWdqmJqpl' },
 | 
					                headers: { 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryF1uyUD0tWdqmJqpl' },
 | 
				
			||||||
                onUploadProgress: onUploadProgress,
 | 
					                onUploadProgress: onUploadProgress,
 | 
				
			||||||
@@ -680,7 +680,7 @@ const uploadFile = (content: any) => {
 | 
				
			|||||||
    params.append('fileId', props.fileId as any);
 | 
					    params.append('fileId', props.fileId as any);
 | 
				
			||||||
    params.append('token', token);
 | 
					    params.append('token', token);
 | 
				
			||||||
    machineApi.uploadFile
 | 
					    machineApi.uploadFile
 | 
				
			||||||
        .request(params, {
 | 
					        .xhrReq(params, {
 | 
				
			||||||
            url: `${config.baseApiUrl}/machines/${props.machineId}/files/${props.fileId}/upload?${joinClientParams()}`,
 | 
					            url: `${config.baseApiUrl}/machines/${props.machineId}/files/${props.fileId}/upload?${joinClientParams()}`,
 | 
				
			||||||
            headers: { 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryF1uyUD0tWdqmJqpl' },
 | 
					            headers: { 'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryF1uyUD0tWdqmJqpl' },
 | 
				
			||||||
            onUploadProgress: onUploadProgress,
 | 
					            onUploadProgress: onUploadProgress,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,6 +110,9 @@ const getFileType = (path: string) => {
 | 
				
			|||||||
    if (path.endsWith('xml') || path.endsWith('html')) {
 | 
					    if (path.endsWith('xml') || path.endsWith('html')) {
 | 
				
			||||||
        return 'html';
 | 
					        return 'html';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (path.endsWith('py')) {
 | 
				
			||||||
 | 
					        return 'python';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return 'text';
 | 
					    return 'text';
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,9 +43,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div class="dialog-footer">
 | 
					                <div class="dialog-footer">
 | 
				
			||||||
                    <el-button @click="testConn" :loading="state.testConnBtnLoading" type="success">测试连接</el-button>
 | 
					                    <el-button @click="testConn" :loading="testConnBtnLoading" type="success">测试连接</el-button>
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -113,11 +113,13 @@ const state = reactive({
 | 
				
			|||||||
        sshTunnelMachineId: null as any,
 | 
					        sshTunnelMachineId: null as any,
 | 
				
			||||||
        tagId: [],
 | 
					        tagId: [],
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    btnLoading: false,
 | 
					    submitForm: {},
 | 
				
			||||||
    testConnBtnLoading: false,
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, tabActiveName, form, btnLoading } = toRefs(state);
 | 
					const { dialogVisible, tabActiveName, form, submitForm } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: testConnBtnLoading, execute: testConnExec } = mongoApi.testConn.useApi(submitForm);
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveMongoExec } = mongoApi.saveMongo.useApi(submitForm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, async (newValue: any) => {
 | 
					watch(props, async (newValue: any) => {
 | 
				
			||||||
    state.dialogVisible = newValue.visible;
 | 
					    state.dialogVisible = newValue.visible;
 | 
				
			||||||
@@ -142,38 +144,28 @@ const getReqForm = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const testConn = async () => {
 | 
					const testConn = async () => {
 | 
				
			||||||
    mongoForm.value.validate(async (valid: boolean) => {
 | 
					    mongoForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            state.testConnBtnLoading = true;
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                await mongoApi.testConn.request(getReqForm());
 | 
					 | 
				
			||||||
                ElMessage.success('连接成功');
 | 
					 | 
				
			||||||
            } finally {
 | 
					 | 
				
			||||||
                state.testConnBtnLoading = false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state.submitForm = getReqForm();
 | 
				
			||||||
 | 
					        await testConnExec();
 | 
				
			||||||
 | 
					        ElMessage.success('连接成功');
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const btnOk = async () => {
 | 
					const btnOk = async () => {
 | 
				
			||||||
    mongoForm.value.validate(async (valid: boolean) => {
 | 
					    mongoForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            mongoApi.saveMongo.request(getReqForm()).then(() => {
 | 
					 | 
				
			||||||
                ElMessage.success('保存成功');
 | 
					 | 
				
			||||||
                emit('val-change', state.form);
 | 
					 | 
				
			||||||
                state.btnLoading = true;
 | 
					 | 
				
			||||||
                setTimeout(() => {
 | 
					 | 
				
			||||||
                    state.btnLoading = false;
 | 
					 | 
				
			||||||
                }, 1000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                cancel();
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        state.submitForm = getReqForm();
 | 
				
			||||||
 | 
					        await saveMongoExec();
 | 
				
			||||||
 | 
					        ElMessage.success('保存成功');
 | 
				
			||||||
 | 
					        emit('val-change', state.form);
 | 
				
			||||||
 | 
					        cancel();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,16 +2,12 @@
 | 
				
			|||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
            ref="pageTableRef"
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="mongoApi.mongoList"
 | 
				
			||||||
            :query="queryConfig"
 | 
					            :query="queryConfig"
 | 
				
			||||||
            v-model:query-form="query"
 | 
					            v-model:query-form="query"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="selectionData"
 | 
					            v-model:selection-data="selectionData"
 | 
				
			||||||
            :data="list"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					            :columns="columns"
 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #tagPathSelect>
 | 
					            <template #tagPathSelect>
 | 
				
			||||||
                <el-select @focus="getTags" v-model="query.tagPath" placeholder="请选择标签" @clear="search" filterable clearable style="width: 200px">
 | 
					                <el-select @focus="getTags" v-model="query.tagPath" placeholder="请选择标签" @clear="search" filterable clearable style="width: 200px">
 | 
				
			||||||
@@ -42,7 +38,7 @@
 | 
				
			|||||||
        <mongo-run-command v-model:visible="usersVisible" :id="state.dbOps.dbId" />
 | 
					        <mongo-run-command v-model:visible="usersVisible" :id="state.dbOps.dbId" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <mongo-edit
 | 
					        <mongo-edit
 | 
				
			||||||
            @val-change="valChange"
 | 
					            @val-change="search"
 | 
				
			||||||
            :title="mongoEditDialog.title"
 | 
					            :title="mongoEditDialog.title"
 | 
				
			||||||
            v-model:visible="mongoEditDialog.visible"
 | 
					            v-model:visible="mongoEditDialog.visible"
 | 
				
			||||||
            v-model:mongo="mongoEditDialog.data"
 | 
					            v-model:mongo="mongoEditDialog.data"
 | 
				
			||||||
@@ -52,7 +48,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { mongoApi } from './api';
 | 
					import { mongoApi } from './api';
 | 
				
			||||||
import { defineAsyncComponent, ref, toRefs, reactive, onMounted } from 'vue';
 | 
					import { defineAsyncComponent, ref, toRefs, reactive, onMounted, Ref } from 'vue';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import ResourceTag from '../component/ResourceTag.vue';
 | 
					import ResourceTag from '../component/ResourceTag.vue';
 | 
				
			||||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
					import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			||||||
@@ -65,8 +61,8 @@ const MongoEdit = defineAsyncComponent(() => import('./MongoEdit.vue'));
 | 
				
			|||||||
const MongoDbs = defineAsyncComponent(() => import('./MongoDbs.vue'));
 | 
					const MongoDbs = defineAsyncComponent(() => import('./MongoDbs.vue'));
 | 
				
			||||||
const MongoRunCommand = defineAsyncComponent(() => import('./MongoRunCommand.vue'));
 | 
					const MongoRunCommand = defineAsyncComponent(() => import('./MongoRunCommand.vue'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					 | 
				
			||||||
const route = useRoute();
 | 
					const route = useRoute();
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const queryConfig = [TableQuery.slot('tagPath', '标签', 'tagPathSelect')];
 | 
					const queryConfig = [TableQuery.slot('tagPath', '标签', 'tagPathSelect')];
 | 
				
			||||||
const columns = ref([
 | 
					const columns = ref([
 | 
				
			||||||
@@ -84,8 +80,6 @@ const state = reactive({
 | 
				
			|||||||
        dbId: 0,
 | 
					        dbId: 0,
 | 
				
			||||||
        db: '',
 | 
					        db: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    list: [],
 | 
					 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    selectionData: [],
 | 
					    selectionData: [],
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
@@ -101,10 +95,12 @@ const state = reactive({
 | 
				
			|||||||
    usersVisible: false,
 | 
					    usersVisible: false,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { tags, list, total, selectionData, query, mongoEditDialog, dbsVisible, usersVisible } = toRefs(state);
 | 
					const { tags, selectionData, query, mongoEditDialog, dbsVisible, usersVisible } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    search();
 | 
					    if (route.query.tagPath) {
 | 
				
			||||||
 | 
					        state.query.tagPath = route.query.tagPath as string;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showDatabases = async (id: number) => {
 | 
					const showDatabases = async (id: number) => {
 | 
				
			||||||
@@ -133,19 +129,7 @@ const deleteMongo = async () => {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    try {
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (route.query.tagPath) {
 | 
					 | 
				
			||||||
            state.query.tagPath = route.query.tagPath as string;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const res = await mongoApi.mongoList.request(state.query);
 | 
					 | 
				
			||||||
        state.list = res.list;
 | 
					 | 
				
			||||||
        state.total = res.total;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getTags = async () => {
 | 
					const getTags = async () => {
 | 
				
			||||||
@@ -162,10 +146,6 @@ const editMongo = async (data: any) => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    state.mongoEditDialog.visible = true;
 | 
					    state.mongoEditDialog.visible = true;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
const valChange = () => {
 | 
					 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style></style>
 | 
					<style></style>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,9 +84,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div class="dialog-footer">
 | 
					                <div class="dialog-footer">
 | 
				
			||||||
                    <el-button @click="testConn" :loading="state.testConnBtnLoading" type="success">测试连接</el-button>
 | 
					                    <el-button @click="testConn" :loading="testConnBtnLoading" type="success">测试连接</el-button>
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -173,13 +173,15 @@ const state = reactive({
 | 
				
			|||||||
        remark: '',
 | 
					        remark: '',
 | 
				
			||||||
        sshTunnelMachineId: -1,
 | 
					        sshTunnelMachineId: -1,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    submitForm: {} as any,
 | 
				
			||||||
    dbList: [0],
 | 
					    dbList: [0],
 | 
				
			||||||
    pwd: '',
 | 
					    pwd: '',
 | 
				
			||||||
    btnLoading: false,
 | 
					 | 
				
			||||||
    testConnBtnLoading: false,
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, tabActiveName, form, dbList, pwd, btnLoading } = toRefs(state);
 | 
					const { dialogVisible, tabActiveName, form, submitForm, dbList, pwd } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: testConnBtnLoading, execute: testConnExec } = redisApi.testConn.useApi(submitForm);
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveRedisExec } = redisApi.saveRedis.useApi(submitForm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, async (newValue: any) => {
 | 
					watch(props, async (newValue: any) => {
 | 
				
			||||||
    state.dialogVisible = newValue.visible;
 | 
					    state.dialogVisible = newValue.visible;
 | 
				
			||||||
@@ -226,38 +228,28 @@ const getReqForm = async () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const testConn = async () => {
 | 
					const testConn = async () => {
 | 
				
			||||||
    redisForm.value.validate(async (valid: boolean) => {
 | 
					    redisForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            state.testConnBtnLoading = true;
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                await redisApi.testConn.request(await getReqForm());
 | 
					 | 
				
			||||||
                ElMessage.success('连接成功');
 | 
					 | 
				
			||||||
            } finally {
 | 
					 | 
				
			||||||
                state.testConnBtnLoading = false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        state.submitForm = await getReqForm();
 | 
				
			||||||
 | 
					        await testConnExec();
 | 
				
			||||||
 | 
					        ElMessage.success('连接成功');
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const btnOk = async () => {
 | 
					const btnOk = async () => {
 | 
				
			||||||
    redisForm.value.validate(async (valid: boolean) => {
 | 
					    redisForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            redisApi.saveRedis.request(await getReqForm()).then(() => {
 | 
					 | 
				
			||||||
                ElMessage.success('保存成功');
 | 
					 | 
				
			||||||
                emit('val-change', state.form);
 | 
					 | 
				
			||||||
                state.btnLoading = true;
 | 
					 | 
				
			||||||
                setTimeout(() => {
 | 
					 | 
				
			||||||
                    state.btnLoading = false;
 | 
					 | 
				
			||||||
                }, 1000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                cancel();
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('请正确填写信息');
 | 
					            ElMessage.error('请正确填写信息');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        state.submitForm = await getReqForm();
 | 
				
			||||||
 | 
					        await saveRedisExec();
 | 
				
			||||||
 | 
					        ElMessage.success('保存成功');
 | 
				
			||||||
 | 
					        emit('val-change', state.form);
 | 
				
			||||||
 | 
					        cancel();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,16 +2,12 @@
 | 
				
			|||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
            ref="pageTableRef"
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="redisApi.redisList"
 | 
				
			||||||
            :query="queryConfig"
 | 
					            :query="queryConfig"
 | 
				
			||||||
            v-model:query-form="query"
 | 
					            v-model:query-form="query"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="selectionData"
 | 
					            v-model:selection-data="selectionData"
 | 
				
			||||||
            :data="redisTable"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					            :columns="columns"
 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #tagPathSelect>
 | 
					            <template #tagPathSelect>
 | 
				
			||||||
                <el-select @focus="getTags" v-model="query.tagPath" placeholder="请选择标签" @clear="search" filterable clearable style="width: 200px">
 | 
					                <el-select @focus="getTags" v-model="query.tagPath" placeholder="请选择标签" @clear="search" filterable clearable style="width: 200px">
 | 
				
			||||||
@@ -148,7 +144,7 @@
 | 
				
			|||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <redis-edit
 | 
					        <redis-edit
 | 
				
			||||||
            @val-change="valChange"
 | 
					            @val-change="search"
 | 
				
			||||||
            :tags="tags"
 | 
					            :tags="tags"
 | 
				
			||||||
            :title="redisEditDialog.title"
 | 
					            :title="redisEditDialog.title"
 | 
				
			||||||
            v-model:visible="redisEditDialog.visible"
 | 
					            v-model:visible="redisEditDialog.visible"
 | 
				
			||||||
@@ -160,7 +156,7 @@
 | 
				
			|||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import Info from './Info.vue';
 | 
					import Info from './Info.vue';
 | 
				
			||||||
import { redisApi } from './api';
 | 
					import { redisApi } from './api';
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
import RedisEdit from './RedisEdit.vue';
 | 
					import RedisEdit from './RedisEdit.vue';
 | 
				
			||||||
import { dateFormat } from '@/common/utils/date';
 | 
					import { dateFormat } from '@/common/utils/date';
 | 
				
			||||||
@@ -171,8 +167,8 @@ import { tagApi } from '../tag/api';
 | 
				
			|||||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
 | 
					import { TagResourceTypeEnum } from '@/common/commonEnum';
 | 
				
			||||||
import { useRoute } from 'vue-router';
 | 
					import { useRoute } from 'vue-router';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					 | 
				
			||||||
const route = useRoute();
 | 
					const route = useRoute();
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const queryConfig = [TableQuery.slot('tagPath', '标签', 'tagPathSelect')];
 | 
					const queryConfig = [TableQuery.slot('tagPath', '标签', 'tagPathSelect')];
 | 
				
			||||||
const columns = ref([
 | 
					const columns = ref([
 | 
				
			||||||
@@ -186,8 +182,6 @@ const columns = ref([
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    tags: [],
 | 
					    tags: [],
 | 
				
			||||||
    redisTable: [],
 | 
					 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    selectionData: [],
 | 
					    selectionData: [],
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
        tagPath: '',
 | 
					        tagPath: '',
 | 
				
			||||||
@@ -222,10 +216,12 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { tags, redisTable, total, selectionData, query, detailDialog, clusterInfoDialog, infoDialog, redisEditDialog } = toRefs(state);
 | 
					const { tags, selectionData, query, detailDialog, clusterInfoDialog, infoDialog, redisEditDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(async () => {
 | 
					onMounted(async () => {
 | 
				
			||||||
    search();
 | 
					    if (route.query.tagPath) {
 | 
				
			||||||
 | 
					        state.query.tagPath = route.query.tagPath as string;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showDetail = (detail: any) => {
 | 
					const showDetail = (detail: any) => {
 | 
				
			||||||
@@ -267,20 +263,8 @@ const onShowClusterInfo = async (redis: any) => {
 | 
				
			|||||||
    state.clusterInfoDialog.visible = true;
 | 
					    state.clusterInfoDialog.visible = true;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = () => {
 | 
				
			||||||
    try {
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (route.query.tagPath) {
 | 
					 | 
				
			||||||
            state.query.tagPath = route.query.tagPath as string;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const res = await redisApi.redisList.request(state.query);
 | 
					 | 
				
			||||||
        state.redisTable = res.list;
 | 
					 | 
				
			||||||
        state.total = res.total;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getTags = async () => {
 | 
					const getTags = async () => {
 | 
				
			||||||
@@ -297,10 +281,6 @@ const editRedis = async (data: any) => {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    state.redisEditDialog.visible = true;
 | 
					    state.redisEditDialog.visible = true;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
const valChange = () => {
 | 
					 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style></style>
 | 
					<style></style>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,13 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="tagApi.getTeams"
 | 
				
			||||||
            :query="state.queryConfig"
 | 
					            :query="state.queryConfig"
 | 
				
			||||||
            v-model:query-form="query"
 | 
					            v-model:query-form="query"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="selectionData"
 | 
					            v-model:selection-data="selectionData"
 | 
				
			||||||
            :data="data"
 | 
					 | 
				
			||||||
            :columns="state.columns"
 | 
					            :columns="state.columns"
 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #queryRight>
 | 
					            <template #queryRight>
 | 
				
			||||||
                <el-button v-auth="'team:save'" type="primary" icon="plus" @click="showSaveTeamDialog(false)">添加</el-button>
 | 
					                <el-button v-auth="'team:save'" type="primary" icon="plus" @click="showSaveTeamDialog(false)">添加</el-button>
 | 
				
			||||||
@@ -89,16 +86,14 @@
 | 
				
			|||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <el-dialog width="50%" :title="showMemDialog.title" v-model="showMemDialog.visible">
 | 
					        <el-dialog @open="setMemebers" width="50%" :title="showMemDialog.title" v-model="showMemDialog.visible">
 | 
				
			||||||
            <page-table
 | 
					            <page-table
 | 
				
			||||||
 | 
					                ref="showMemPageTableRef"
 | 
				
			||||||
 | 
					                :page-api="tagApi.getTeamMem"
 | 
				
			||||||
 | 
					                :lazy="true"
 | 
				
			||||||
                :query="showMemDialog.queryConfig"
 | 
					                :query="showMemDialog.queryConfig"
 | 
				
			||||||
                v-model:query-form="showMemDialog.query"
 | 
					                v-model:query-form="showMemDialog.query"
 | 
				
			||||||
                :data="showMemDialog.members.list"
 | 
					 | 
				
			||||||
                :columns="showMemDialog.columns"
 | 
					                :columns="showMemDialog.columns"
 | 
				
			||||||
                :total="showMemDialog.members.total"
 | 
					 | 
				
			||||||
                v-model:page-size="showMemDialog.query.pageSize"
 | 
					 | 
				
			||||||
                v-model:page-num="showMemDialog.query.pageNum"
 | 
					 | 
				
			||||||
                @pageChange="setMemebers()"
 | 
					 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
                <template #queryRight>
 | 
					                <template #queryRight>
 | 
				
			||||||
                    <el-button v-auth="'team:member:save'" @click="showAddMemberDialog()" type="primary" icon="plus">添加</el-button>
 | 
					                    <el-button v-auth="'team:member:save'" @click="showAddMemberDialog()" type="primary" icon="plus">添加</el-button>
 | 
				
			||||||
@@ -138,7 +133,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
 | 
				
			||||||
import { tagApi } from './api';
 | 
					import { tagApi } from './api';
 | 
				
			||||||
import { accountApi } from '../../system/api';
 | 
					import { accountApi } from '../../system/api';
 | 
				
			||||||
import { ElMessage, ElMessageBox } from 'element-plus';
 | 
					import { ElMessage, ElMessageBox } from 'element-plus';
 | 
				
			||||||
@@ -148,6 +143,9 @@ import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const teamForm: any = ref(null);
 | 
					const teamForm: any = ref(null);
 | 
				
			||||||
const tagTreeRef: any = ref(null);
 | 
					const tagTreeRef: any = ref(null);
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					const showMemPageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    currentEditPermissions: false,
 | 
					    currentEditPermissions: false,
 | 
				
			||||||
    addTeamDialog: {
 | 
					    addTeamDialog: {
 | 
				
			||||||
@@ -168,8 +166,6 @@ const state = reactive({
 | 
				
			|||||||
        TableColumn.new('creator', '创建人'),
 | 
					        TableColumn.new('creator', '创建人'),
 | 
				
			||||||
        TableColumn.new('action', '操作').isSlot().setMinWidth(120).fixedRight().alignCenter(),
 | 
					        TableColumn.new('action', '操作').isSlot().setMinWidth(120).fixedRight().alignCenter(),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    data: [],
 | 
					 | 
				
			||||||
    selectionData: [],
 | 
					    selectionData: [],
 | 
				
			||||||
    showMemDialog: {
 | 
					    showMemDialog: {
 | 
				
			||||||
        queryConfig: [TableQuery.text('username', '用户名')],
 | 
					        queryConfig: [TableQuery.text('username', '用户名')],
 | 
				
			||||||
@@ -213,16 +209,12 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { query, addTeamDialog, total, data, selectionData, showMemDialog, showTagDialog } = toRefs(state);
 | 
					const { query, addTeamDialog, selectionData, showMemDialog, showTagDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {});
 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    let res = await tagApi.getTeams.request(state.query);
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
    state.data = res.list;
 | 
					 | 
				
			||||||
    state.total = res.total;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showSaveTeamDialog = (data: any) => {
 | 
					const showSaveTeamDialog = (data: any) => {
 | 
				
			||||||
@@ -270,7 +262,6 @@ const deleteTeam = () => {
 | 
				
			|||||||
const showMembers = async (team: any) => {
 | 
					const showMembers = async (team: any) => {
 | 
				
			||||||
    state.showMemDialog.query.teamId = team.id;
 | 
					    state.showMemDialog.query.teamId = team.id;
 | 
				
			||||||
    state.showMemDialog.visible = true;
 | 
					    state.showMemDialog.visible = true;
 | 
				
			||||||
    await setMemebers();
 | 
					 | 
				
			||||||
    state.showMemDialog.title = `[${team.name}] 成员信息`;
 | 
					    state.showMemDialog.title = `[${team.name}] 成员信息`;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -293,9 +284,7 @@ const deleteMember = async (data: any) => {
 | 
				
			|||||||
 * 设置成员列表信息
 | 
					 * 设置成员列表信息
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const setMemebers = async () => {
 | 
					const setMemebers = async () => {
 | 
				
			||||||
    const res = await tagApi.getTeamMem.request(state.showMemDialog.query);
 | 
					    showMemPageTableRef.value.search();
 | 
				
			||||||
    state.showMemDialog.members.list = res.list;
 | 
					 | 
				
			||||||
    state.showMemDialog.members.total = res.total;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showAddMemberDialog = () => {
 | 
					const showAddMemberDialog = () => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@
 | 
				
			|||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div class="dialog-footer">
 | 
					                <div class="dialog-footer">
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -84,10 +84,11 @@ const state = reactive({
 | 
				
			|||||||
        password: null,
 | 
					        password: null,
 | 
				
			||||||
        repassword: null,
 | 
					        repassword: null,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    btnLoading: false,
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, edit, form, btnLoading } = toRefs(state);
 | 
					const { dialogVisible, edit, form } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveAccountExec } = accountApi.save.useApi(form);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, (newValue: any) => {
 | 
					watch(props, (newValue: any) => {
 | 
				
			||||||
    if (newValue.account) {
 | 
					    if (newValue.account) {
 | 
				
			||||||
@@ -101,23 +102,18 @@ watch(props, (newValue: any) => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const btnOk = async () => {
 | 
					const btnOk = async () => {
 | 
				
			||||||
    accountForm.value.validate((valid: boolean) => {
 | 
					    accountForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (!valid) {
 | 
				
			||||||
            accountApi.save.request(state.form).then(() => {
 | 
					 | 
				
			||||||
                ElMessage.success('操作成功');
 | 
					 | 
				
			||||||
                emit('val-change', state.form);
 | 
					 | 
				
			||||||
                state.btnLoading = true;
 | 
					 | 
				
			||||||
                setTimeout(() => {
 | 
					 | 
				
			||||||
                    state.btnLoading = false;
 | 
					 | 
				
			||||||
                }, 1000);
 | 
					 | 
				
			||||||
                //重置表单域
 | 
					 | 
				
			||||||
                accountForm.value.resetFields();
 | 
					 | 
				
			||||||
                state.form = {} as any;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            ElMessage.error('表单填写有误');
 | 
					            ElMessage.error('表单填写有误');
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await saveAccountExec();
 | 
				
			||||||
 | 
					        ElMessage.success('操作成功');
 | 
				
			||||||
 | 
					        emit('val-change', state.form);
 | 
				
			||||||
 | 
					        //重置表单域
 | 
				
			||||||
 | 
					        accountForm.value.resetFields();
 | 
				
			||||||
 | 
					        state.form = {} as any;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,16 +2,12 @@
 | 
				
			|||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
            ref="pageTableRef"
 | 
					            ref="pageTableRef"
 | 
				
			||||||
 | 
					            :page-api="accountApi.list"
 | 
				
			||||||
            :query="queryConfig"
 | 
					            :query="queryConfig"
 | 
				
			||||||
            v-model:query-form="query"
 | 
					            v-model:query-form="query"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="selectionData"
 | 
					            v-model:selection-data="selectionData"
 | 
				
			||||||
            :data="datas"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					            :columns="columns"
 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #queryRight>
 | 
					            <template #queryRight>
 | 
				
			||||||
                <el-button v-auth="perms.addAccount" type="primary" icon="plus" @click="editAccount(false)">添加</el-button>
 | 
					                <el-button v-auth="perms.addAccount" type="primary" icon="plus" @click="editAccount(false)">添加</el-button>
 | 
				
			||||||
@@ -81,7 +77,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
 | 
				
			||||||
import RoleEdit from './RoleEdit.vue';
 | 
					import RoleEdit from './RoleEdit.vue';
 | 
				
			||||||
import AccountEdit from './AccountEdit.vue';
 | 
					import AccountEdit from './AccountEdit.vue';
 | 
				
			||||||
import { AccountStatusEnum, ResourceTypeEnum } from '../enums';
 | 
					import { AccountStatusEnum, ResourceTypeEnum } from '../enums';
 | 
				
			||||||
@@ -92,8 +88,6 @@ import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			|||||||
import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
					import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
				
			||||||
import { hasPerms } from '@/components/auth/auth';
 | 
					import { hasPerms } from '@/components/auth/auth';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const perms = {
 | 
					const perms = {
 | 
				
			||||||
    addAccount: 'account:add',
 | 
					    addAccount: 'account:add',
 | 
				
			||||||
    delAccount: 'account:del',
 | 
					    delAccount: 'account:del',
 | 
				
			||||||
@@ -118,6 +112,7 @@ const columns = ref([
 | 
				
			|||||||
const actionBtns = hasPerms([perms.addAccount, perms.saveAccountRole, perms.changeAccountStatus]);
 | 
					const actionBtns = hasPerms([perms.addAccount, perms.saveAccountRole, perms.changeAccountStatus]);
 | 
				
			||||||
const actionColumn = TableColumn.new('action', '操作').isSlot().fixedRight().setMinWidth(260).noShowOverflowTooltip().alignCenter();
 | 
					const actionColumn = TableColumn.new('action', '操作').isSlot().fixedRight().setMinWidth(260).noShowOverflowTooltip().alignCenter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 选中的数据
 | 
					     * 选中的数据
 | 
				
			||||||
@@ -131,8 +126,6 @@ const state = reactive({
 | 
				
			|||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
        pageSize: 0,
 | 
					        pageSize: 0,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    datas: [],
 | 
					 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    showRoleDialog: {
 | 
					    showRoleDialog: {
 | 
				
			||||||
        title: '',
 | 
					        title: '',
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
@@ -158,24 +151,16 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { selectionData, query, datas, total, showRoleDialog, showResourceDialog, roleDialog, accountDialog } = toRefs(state);
 | 
					const { selectionData, query, showRoleDialog, showResourceDialog, roleDialog, accountDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
    if (Object.keys(actionBtns).length > 0) {
 | 
					    if (Object.keys(actionBtns).length > 0) {
 | 
				
			||||||
        columns.value.push(actionColumn);
 | 
					        columns.value.push(actionColumn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    try {
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
        let res: any = await accountApi.list.request(state.query);
 | 
					 | 
				
			||||||
        state.datas = res.list;
 | 
					 | 
				
			||||||
        state.total = res.total;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showResources = async (row: any) => {
 | 
					const showResources = async (row: any) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,7 @@
 | 
				
			|||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div class="dialog-footer">
 | 
					                <div class="dialog-footer">
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -76,10 +76,11 @@ const state = reactive({
 | 
				
			|||||||
        remark: '',
 | 
					        remark: '',
 | 
				
			||||||
        permission: '',
 | 
					        permission: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    btnLoading: false,
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dvisible, params, form, btnLoading } = toRefs(state);
 | 
					const { dvisible, params, form } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveConfigExec } = configApi.save.useApi(form);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, (newValue: any) => {
 | 
					watch(props, (newValue: any) => {
 | 
				
			||||||
    state.dvisible = newValue.visible;
 | 
					    state.dvisible = newValue.visible;
 | 
				
			||||||
@@ -134,13 +135,10 @@ const btnOk = async () => {
 | 
				
			|||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                state.form.permission = 'all';
 | 
					                state.form.permission = 'all';
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            await configApi.save.request(state.form);
 | 
					
 | 
				
			||||||
 | 
					            await saveConfigExec();
 | 
				
			||||||
            emit('val-change', state.form);
 | 
					            emit('val-change', state.form);
 | 
				
			||||||
            cancel();
 | 
					            cancel();
 | 
				
			||||||
            state.btnLoading = true;
 | 
					 | 
				
			||||||
            setTimeout(() => {
 | 
					 | 
				
			||||||
                state.btnLoading = false;
 | 
					 | 
				
			||||||
            }, 1000);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,6 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table ref="pageTableRef" :page-api="configApi.list" v-model:selection-data="selectionData" :columns="columns">
 | 
				
			||||||
            :show-selection="true"
 | 
					 | 
				
			||||||
            v-model:selection-data="selectionData"
 | 
					 | 
				
			||||||
            :data="configs"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
            <template #queryRight>
 | 
					            <template #queryRight>
 | 
				
			||||||
                <el-button v-auth="perms.saveConfig" type="primary" icon="plus" @click="editConfig(false)">添加</el-button>
 | 
					                <el-button v-auth="perms.saveConfig" type="primary" icon="plus" @click="editConfig(false)">添加</el-button>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
@@ -52,7 +43,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
 | 
				
			||||||
import ConfigEdit from './ConfigEdit.vue';
 | 
					import ConfigEdit from './ConfigEdit.vue';
 | 
				
			||||||
import { configApi } from '../api';
 | 
					import { configApi } from '../api';
 | 
				
			||||||
import { ElMessage } from 'element-plus';
 | 
					import { ElMessage } from 'element-plus';
 | 
				
			||||||
@@ -75,15 +66,15 @@ const columns = ref([
 | 
				
			|||||||
const actionColumn = TableColumn.new('action', '操作').isSlot().fixedRight().setMinWidth(130).noShowOverflowTooltip().alignCenter();
 | 
					const actionColumn = TableColumn.new('action', '操作').isSlot().fixedRight().setMinWidth(130).noShowOverflowTooltip().alignCenter();
 | 
				
			||||||
const actionBtns = hasPerms([perms.saveConfig]);
 | 
					const actionBtns = hasPerms([perms.saveConfig]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
const paramsFormRef: any = ref(null);
 | 
					const paramsFormRef: any = ref(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
        pageSize: 0,
 | 
					        pageSize: 0,
 | 
				
			||||||
        name: null,
 | 
					        name: null,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    configs: [],
 | 
					 | 
				
			||||||
    selectionData: [],
 | 
					    selectionData: [],
 | 
				
			||||||
    paramsDialog: {
 | 
					    paramsDialog: {
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
@@ -98,19 +89,16 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { query, total, configs, selectionData, paramsDialog, configEdit } = toRefs(state);
 | 
					const { selectionData, paramsDialog, configEdit } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
    if (Object.keys(actionBtns).length > 0) {
 | 
					    if (Object.keys(actionBtns).length > 0) {
 | 
				
			||||||
        columns.value.push(actionColumn);
 | 
					        columns.value.push(actionColumn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = async () => {
 | 
				
			||||||
    let res = await configApi.list.request(state.query);
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
    state.configs = res.list;
 | 
					 | 
				
			||||||
    state.total = res.total;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const showSetConfigDialog = (row: any) => {
 | 
					const showSetConfigDialog = (row: any) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -132,7 +132,7 @@
 | 
				
			|||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div>
 | 
					                <div>
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -222,10 +222,12 @@ const state = reactive({
 | 
				
			|||||||
            link: '',
 | 
					            link: '',
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    btnLoading: false,
 | 
					    submitForm: {},
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dialogVisible, form, btnLoading } = toRefs(state);
 | 
					const { dialogVisible, form, submitForm } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveResouceExec } = resourceApi.save.useApi(submitForm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, (newValue: any) => {
 | 
					watch(props, (newValue: any) => {
 | 
				
			||||||
    state.dialogVisible = newValue.visible;
 | 
					    state.dialogVisible = newValue.visible;
 | 
				
			||||||
@@ -264,20 +266,15 @@ const btnOk = () => {
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        submitForm.meta = null as any;
 | 
					        submitForm.meta = null as any;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    menuForm.value.validate((valid: any) => {
 | 
					 | 
				
			||||||
        if (valid) {
 | 
					 | 
				
			||||||
            resourceApi.save.request(submitForm).then(() => {
 | 
					 | 
				
			||||||
                emit('val-change', submitForm);
 | 
					 | 
				
			||||||
                state.btnLoading = true;
 | 
					 | 
				
			||||||
                ElMessage.success('保存成功');
 | 
					 | 
				
			||||||
                setTimeout(() => {
 | 
					 | 
				
			||||||
                    state.btnLoading = false;
 | 
					 | 
				
			||||||
                }, 1000);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                cancel();
 | 
					    menuForm.value.validate(async (valid: any) => {
 | 
				
			||||||
            });
 | 
					        if (valid) {
 | 
				
			||||||
        } else {
 | 
					            state.submitForm = submitForm;
 | 
				
			||||||
            return false;
 | 
					            await saveResouceExec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            emit('val-change', submitForm);
 | 
				
			||||||
 | 
					            ElMessage.success('保存成功');
 | 
				
			||||||
 | 
					            cancel();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -223,8 +223,7 @@ const deleteMenu = (data: any) => {
 | 
				
			|||||||
            .request({
 | 
					            .request({
 | 
				
			||||||
                id: data.id,
 | 
					                id: data.id,
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .then((res) => {
 | 
					            .then(() => {
 | 
				
			||||||
                console.log(res);
 | 
					 | 
				
			||||||
                ElMessage.success('删除成功!');
 | 
					                ElMessage.success('删除成功!');
 | 
				
			||||||
                search();
 | 
					                search();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,7 @@
 | 
				
			|||||||
            <template #footer>
 | 
					            <template #footer>
 | 
				
			||||||
                <div class="dialog-footer">
 | 
					                <div class="dialog-footer">
 | 
				
			||||||
                    <el-button @click="cancel()">取 消</el-button>
 | 
					                    <el-button @click="cancel()">取 消</el-button>
 | 
				
			||||||
                    <el-button type="primary" :loading="btnLoading" @click="btnOk">确 定</el-button>
 | 
					                    <el-button type="primary" :loading="saveBtnLoading" @click="btnOk">确 定</el-button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </template>
 | 
					            </template>
 | 
				
			||||||
        </el-dialog>
 | 
					        </el-dialog>
 | 
				
			||||||
@@ -57,10 +57,11 @@ const state = reactive({
 | 
				
			|||||||
        status: 1,
 | 
					        status: 1,
 | 
				
			||||||
        remark: '',
 | 
					        remark: '',
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    btnLoading: false,
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { dvisible, form, btnLoading } = toRefs(state);
 | 
					const { dvisible, form } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { isFetching: saveBtnLoading, execute: saveRoleExec } = roleApi.save.useApi(form);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
watch(props, (newValue: any) => {
 | 
					watch(props, (newValue: any) => {
 | 
				
			||||||
    state.dvisible = newValue.visible;
 | 
					    state.dvisible = newValue.visible;
 | 
				
			||||||
@@ -81,13 +82,9 @@ const cancel = () => {
 | 
				
			|||||||
const btnOk = async () => {
 | 
					const btnOk = async () => {
 | 
				
			||||||
    roleForm.value.validate(async (valid: boolean) => {
 | 
					    roleForm.value.validate(async (valid: boolean) => {
 | 
				
			||||||
        if (valid) {
 | 
					        if (valid) {
 | 
				
			||||||
            await roleApi.save.request(state.form);
 | 
					            await saveRoleExec();
 | 
				
			||||||
            emit('val-change', state.form);
 | 
					            emit('val-change', state.form);
 | 
				
			||||||
            cancel();
 | 
					            cancel();
 | 
				
			||||||
            state.btnLoading = true;
 | 
					 | 
				
			||||||
            setTimeout(() => {
 | 
					 | 
				
			||||||
                state.btnLoading = false;
 | 
					 | 
				
			||||||
            }, 1000);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,13 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table
 | 
				
			||||||
            ref="pageTableRef"
 | 
					 | 
				
			||||||
            :query="queryConfig"
 | 
					            :query="queryConfig"
 | 
				
			||||||
            v-model:query-form="query"
 | 
					            v-model:query-form="query"
 | 
				
			||||||
            :show-selection="true"
 | 
					            :show-selection="true"
 | 
				
			||||||
            v-model:selection-data="selectionData"
 | 
					            v-model:selection-data="selectionData"
 | 
				
			||||||
            :data="roles"
 | 
					 | 
				
			||||||
            :columns="columns"
 | 
					            :columns="columns"
 | 
				
			||||||
            :total="total"
 | 
					            :page-api="roleApi.list"
 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					            ref="pageTableRef"
 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            <template #queryRight>
 | 
					            <template #queryRight>
 | 
				
			||||||
                <el-button v-auth="perms.addRole" type="primary" icon="plus" @click="editRole(false)">添加</el-button>
 | 
					                <el-button v-auth="perms.addRole" type="primary" icon="plus" @click="editRole(false)">添加</el-button>
 | 
				
			||||||
@@ -40,7 +36,7 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted } from 'vue';
 | 
					import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
 | 
				
			||||||
import RoleEdit from './RoleEdit.vue';
 | 
					import RoleEdit from './RoleEdit.vue';
 | 
				
			||||||
import ResourceEdit from './ResourceEdit.vue';
 | 
					import ResourceEdit from './ResourceEdit.vue';
 | 
				
			||||||
import ShowResource from './ShowResource.vue';
 | 
					import ShowResource from './ShowResource.vue';
 | 
				
			||||||
@@ -51,8 +47,6 @@ import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
				
			|||||||
import { hasPerms } from '@/components/auth/auth';
 | 
					import { hasPerms } from '@/components/auth/auth';
 | 
				
			||||||
import { RoleStatusEnum } from '../enums';
 | 
					import { RoleStatusEnum } from '../enums';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const perms = {
 | 
					const perms = {
 | 
				
			||||||
    addRole: 'role:add',
 | 
					    addRole: 'role:add',
 | 
				
			||||||
    delRole: 'role:del',
 | 
					    delRole: 'role:del',
 | 
				
			||||||
@@ -75,14 +69,13 @@ const columns = ref([
 | 
				
			|||||||
const actionBtns = hasPerms([perms.updateRole, perms.saveRoleResource]);
 | 
					const actionBtns = hasPerms([perms.updateRole, perms.saveRoleResource]);
 | 
				
			||||||
const actionColumn = TableColumn.new('action', '操作').isSlot().setMinWidth(260).fixedRight().alignCenter();
 | 
					const actionColumn = TableColumn.new('action', '操作').isSlot().setMinWidth(260).fixedRight().alignCenter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const pageTableRef: Ref<any> = ref(null);
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
        pageSize: 0,
 | 
					        pageSize: 0,
 | 
				
			||||||
        name: null,
 | 
					        name: null,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    roles: [],
 | 
					 | 
				
			||||||
    selectionData: [],
 | 
					    selectionData: [],
 | 
				
			||||||
    resourceDialog: {
 | 
					    resourceDialog: {
 | 
				
			||||||
        visible: false,
 | 
					        visible: false,
 | 
				
			||||||
@@ -102,24 +95,16 @@ const state = reactive({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { query, total, roles, selectionData, resourceDialog, roleEditDialog, showResourceDialog } = toRefs(state);
 | 
					const { query, selectionData, resourceDialog, roleEditDialog, showResourceDialog } = toRefs(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
onMounted(() => {
 | 
					onMounted(() => {
 | 
				
			||||||
    if (Object.keys(actionBtns).length > 0) {
 | 
					    if (Object.keys(actionBtns).length > 0) {
 | 
				
			||||||
        columns.value.push(actionColumn);
 | 
					        columns.value.push(actionColumn);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const search = async () => {
 | 
					const search = () => {
 | 
				
			||||||
    try {
 | 
					    pageTableRef.value.search();
 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
        let res = await roleApi.list.request(state.query);
 | 
					 | 
				
			||||||
        state.roles = res.list;
 | 
					 | 
				
			||||||
        state.total = res.total;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const roleEditChange = () => {
 | 
					const roleEditChange = () => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,6 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
    <div>
 | 
					    <div>
 | 
				
			||||||
        <page-table
 | 
					        <page-table :query="queryConfig" v-model:query-form="query" :columns="columns" :page-api="logApi.list">
 | 
				
			||||||
            ref="pageTableRef"
 | 
					 | 
				
			||||||
            :query="state.queryConfig"
 | 
					 | 
				
			||||||
            v-model:query-form="query"
 | 
					 | 
				
			||||||
            :data="logs"
 | 
					 | 
				
			||||||
            :columns="state.columns"
 | 
					 | 
				
			||||||
            :total="total"
 | 
					 | 
				
			||||||
            v-model:page-size="query.pageSize"
 | 
					 | 
				
			||||||
            v-model:page-num="query.pageNum"
 | 
					 | 
				
			||||||
            @pageChange="search()"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
            <template #selectAccount>
 | 
					            <template #selectAccount>
 | 
				
			||||||
                <el-select
 | 
					                <el-select
 | 
				
			||||||
                    style="width: 200px"
 | 
					                    style="width: 200px"
 | 
				
			||||||
@@ -29,13 +19,26 @@
 | 
				
			|||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { ref, toRefs, reactive, onMounted } from 'vue';
 | 
					import { toRefs, reactive } from 'vue';
 | 
				
			||||||
import { logApi, accountApi } from '../api';
 | 
					import { logApi, accountApi } from '../api';
 | 
				
			||||||
import PageTable from '@/components/pagetable/PageTable.vue';
 | 
					import PageTable from '@/components/pagetable/PageTable.vue';
 | 
				
			||||||
import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
					import { TableColumn, TableQuery } from '@/components/pagetable';
 | 
				
			||||||
import { LogTypeEnum } from '../enums';
 | 
					import { LogTypeEnum } from '../enums';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const pageTableRef: any = ref(null);
 | 
					const queryConfig = [
 | 
				
			||||||
 | 
					    TableQuery.slot('creatorId', '操作人', 'selectAccount'),
 | 
				
			||||||
 | 
					    TableQuery.select('type', '操作结果').setOptions(Object.values(LogTypeEnum)),
 | 
				
			||||||
 | 
					    TableQuery.text('description', '描述'),
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const columns = [
 | 
				
			||||||
 | 
					    TableColumn.new('creator', '操作人'),
 | 
				
			||||||
 | 
					    TableColumn.new('createTime', '操作时间').isTime(),
 | 
				
			||||||
 | 
					    TableColumn.new('type', '结果').typeTag(LogTypeEnum),
 | 
				
			||||||
 | 
					    TableColumn.new('description', '描述'),
 | 
				
			||||||
 | 
					    TableColumn.new('reqParam', '操作信息').canBeautify(),
 | 
				
			||||||
 | 
					    TableColumn.new('resp', '响应信息'),
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const state = reactive({
 | 
					const state = reactive({
 | 
				
			||||||
    query: {
 | 
					    query: {
 | 
				
			||||||
@@ -45,40 +48,10 @@ const state = reactive({
 | 
				
			|||||||
        pageNum: 1,
 | 
					        pageNum: 1,
 | 
				
			||||||
        pageSize: 0,
 | 
					        pageSize: 0,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    queryConfig: [
 | 
					 | 
				
			||||||
        TableQuery.slot('creatorId', '操作人', 'selectAccount'),
 | 
					 | 
				
			||||||
        TableQuery.select('type', '操作结果').setOptions(Object.values(LogTypeEnum)),
 | 
					 | 
				
			||||||
        TableQuery.text('description', '描述'),
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    columns: [
 | 
					 | 
				
			||||||
        TableColumn.new('creator', '操作人'),
 | 
					 | 
				
			||||||
        TableColumn.new('createTime', '操作时间').isTime(),
 | 
					 | 
				
			||||||
        TableColumn.new('type', '结果').typeTag(LogTypeEnum),
 | 
					 | 
				
			||||||
        TableColumn.new('description', '描述'),
 | 
					 | 
				
			||||||
        TableColumn.new('reqParam', '操作信息').canBeautify(),
 | 
					 | 
				
			||||||
        TableColumn.new('resp', '响应信息'),
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    total: 0,
 | 
					 | 
				
			||||||
    logs: [],
 | 
					 | 
				
			||||||
    accounts: [] as any,
 | 
					    accounts: [] as any,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { query, total, logs, accounts } = toRefs(state);
 | 
					const { query, accounts } = toRefs(state);
 | 
				
			||||||
 | 
					 | 
				
			||||||
onMounted(() => {
 | 
					 | 
				
			||||||
    search();
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const search = async () => {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(true);
 | 
					 | 
				
			||||||
        let res = await logApi.list.request(state.query);
 | 
					 | 
				
			||||||
        state.logs = res.list;
 | 
					 | 
				
			||||||
        state.total = res.total;
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        pageTableRef.value.loading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getAccount = (username: any) => {
 | 
					const getAccount = (username: any) => {
 | 
				
			||||||
    accountApi.list.request({ username }).then((res) => {
 | 
					    accountApi.list.request({ username }).then((res) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,9 +62,11 @@ func (app *instanceAppImpl) Save(ctx context.Context, instanceEntity *entity.DbI
 | 
				
			|||||||
	instanceEntity.Network = instanceEntity.GetNetwork()
 | 
						instanceEntity.Network = instanceEntity.GetNetwork()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 查找是否存在该库
 | 
						// 查找是否存在该库
 | 
				
			||||||
	oldInstance := &entity.DbInstance{Host: instanceEntity.Host, Port: instanceEntity.Port, Username: instanceEntity.Username}
 | 
						oldInstance := &entity.DbInstance{
 | 
				
			||||||
	if instanceEntity.SshTunnelMachineId > 0 {
 | 
							Host:               instanceEntity.Host,
 | 
				
			||||||
		oldInstance.SshTunnelMachineId = instanceEntity.SshTunnelMachineId
 | 
							Port:               instanceEntity.Port,
 | 
				
			||||||
 | 
							Username:           instanceEntity.Username,
 | 
				
			||||||
 | 
							SshTunnelMachineId: instanceEntity.SshTunnelMachineId,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := app.GetBy(oldInstance)
 | 
						err := app.GetBy(oldInstance)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,10 +74,13 @@ func (m *machineAppImpl) GetMachineList(condition *entity.MachineQuery, pagePara
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *machineAppImpl) Save(ctx context.Context, me *entity.Machine, tagIds ...uint64) error {
 | 
					func (m *machineAppImpl) Save(ctx context.Context, me *entity.Machine, tagIds ...uint64) error {
 | 
				
			||||||
	oldMachine := &entity.Machine{Ip: me.Ip, Port: me.Port, Username: me.Username}
 | 
						oldMachine := &entity.Machine{
 | 
				
			||||||
	if me.SshTunnelMachineId > 0 {
 | 
							Ip:                 me.Ip,
 | 
				
			||||||
		oldMachine.SshTunnelMachineId = me.SshTunnelMachineId
 | 
							Port:               me.Port,
 | 
				
			||||||
 | 
							Username:           me.Username,
 | 
				
			||||||
 | 
							SshTunnelMachineId: me.SshTunnelMachineId,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := m.GetBy(oldMachine)
 | 
						err := m.GetBy(oldMachine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	me.PwdEncrypt()
 | 
						me.PwdEncrypt()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,9 +70,9 @@ func (r *redisAppImpl) TestConn(re *entity.Redis) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (r *redisAppImpl) Save(ctx context.Context, re *entity.Redis, tagIds ...uint64) error {
 | 
					func (r *redisAppImpl) Save(ctx context.Context, re *entity.Redis, tagIds ...uint64) error {
 | 
				
			||||||
	// 查找是否存在该库
 | 
						// 查找是否存在该库
 | 
				
			||||||
	oldRedis := &entity.Redis{Host: re.Host}
 | 
						oldRedis := &entity.Redis{
 | 
				
			||||||
	if re.SshTunnelMachineId > 0 {
 | 
							Host:               re.Host,
 | 
				
			||||||
		oldRedis.SshTunnelMachineId = re.SshTunnelMachineId
 | 
							SshTunnelMachineId: re.SshTunnelMachineId,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	err := r.GetBy(oldRedis)
 | 
						err := r.GetBy(oldRedis)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -160,37 +160,35 @@ func (p *tagTreeAppImpl) RelateResource(ctx context.Context, resourceCode string
 | 
				
			|||||||
		addTagIds, delTagIds, _ = collx.ArrayCompare[uint64](tagIds, oldTagIds, func(u1, u2 uint64) bool { return u1 == u2 })
 | 
							addTagIds, delTagIds, _ = collx.ArrayCompare[uint64](tagIds, oldTagIds, func(u1, u2 uint64) bool { return u1 == u2 })
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return p.Tx(ctx, func(ctx context.Context) error {
 | 
						if len(addTagIds) > 0 {
 | 
				
			||||||
		if len(addTagIds) > 0 {
 | 
							addTagResource := make([]*entity.TagResource, 0)
 | 
				
			||||||
			addTagResource := make([]*entity.TagResource, 0)
 | 
							for _, tagId := range addTagIds {
 | 
				
			||||||
			for _, tagId := range addTagIds {
 | 
								tag, err := p.GetById(new(entity.TagTree), tagId)
 | 
				
			||||||
				tag, err := p.GetById(new(entity.TagTree), tagId)
 | 
								if err != nil {
 | 
				
			||||||
				if err != nil {
 | 
									return errorx.NewBiz("存在错误标签id")
 | 
				
			||||||
					return errorx.NewBiz("存在错误标签id")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				addTagResource = append(addTagResource, &entity.TagResource{
 | 
					 | 
				
			||||||
					ResourceCode: resourceCode,
 | 
					 | 
				
			||||||
					ResourceType: resourceType,
 | 
					 | 
				
			||||||
					TagId:        tagId,
 | 
					 | 
				
			||||||
					TagPath:      tag.CodePath,
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if err := p.tagResourceApp.BatchInsert(ctx, addTagResource); err != nil {
 | 
								addTagResource = append(addTagResource, &entity.TagResource{
 | 
				
			||||||
 | 
									ResourceCode: resourceCode,
 | 
				
			||||||
 | 
									ResourceType: resourceType,
 | 
				
			||||||
 | 
									TagId:        tagId,
 | 
				
			||||||
 | 
									TagPath:      tag.CodePath,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := p.tagResourceApp.BatchInsert(ctx, addTagResource); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(delTagIds) > 0 {
 | 
				
			||||||
 | 
							for _, tagId := range delTagIds {
 | 
				
			||||||
 | 
								cond := &entity.TagResource{ResourceCode: resourceCode, ResourceType: resourceType, TagId: tagId}
 | 
				
			||||||
 | 
								if err := p.tagResourceApp.DeleteByCond(ctx, cond); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if len(delTagIds) > 0 {
 | 
						return nil
 | 
				
			||||||
			for _, tagId := range delTagIds {
 | 
					 | 
				
			||||||
				cond := &entity.TagResource{ResourceCode: resourceCode, ResourceType: resourceType, TagId: tagId}
 | 
					 | 
				
			||||||
				if err := p.tagResourceApp.DeleteByCond(ctx, cond); err != nil {
 | 
					 | 
				
			||||||
					return err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (p *tagTreeAppImpl) ListTagPathByResource(resourceType int8, resourceCode string) []string {
 | 
					func (p *tagTreeAppImpl) ListTagPathByResource(resourceType int8, resourceCode string) []string {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user