mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-03 07:50: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