mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 15:30:25 +08:00
otp: 样式优化
This commit is contained in:
@@ -63,7 +63,7 @@
|
||||
"sass": "^1.87.0",
|
||||
"tailwindcss": "^4.1.4",
|
||||
"typescript": "^5.8.2",
|
||||
"vite": "^6.3.2",
|
||||
"vite": "^6.3.3",
|
||||
"vite-plugin-progress": "0.0.7",
|
||||
"vue-eslint-parser": "^10.1.3"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="monaco-editor-custom h-full" style="border: 1px solid var(--el-border-color-light, #ebeef5)">
|
||||
<div class="monaco-editor-custom relative h-full" style="border: 1px solid var(--el-border-color-light, #ebeef5)">
|
||||
<div class="monaco-editor-content" ref="monacoTextareaRef" :style="{ height: height }"></div>
|
||||
<el-select v-if="canChangeMode" class="code-mode-select" v-model="languageMode" @change="changeLanguage" filterable>
|
||||
<el-option v-for="mode in languageArr" :key="mode.value" :label="mode.label" :value="mode.value"> </el-option>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</SearchForm>
|
||||
</transition>
|
||||
|
||||
<el-card class="h-full" body-class="h-full">
|
||||
<el-card class="h-full" body-class="h-full flex flex-col">
|
||||
<!-- 表格头部 操作按钮 -->
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
@@ -79,8 +79,9 @@
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="h-[calc(100%-90px)]">
|
||||
<div class="flex-1 overflow-auto">
|
||||
<el-table
|
||||
v-show="showTable"
|
||||
ref="tableRef"
|
||||
v-bind="$attrs"
|
||||
height="100%"
|
||||
@@ -152,7 +153,6 @@
|
||||
:small="props.size == 'small'"
|
||||
@current-change="pageNumChange"
|
||||
@size-change="pageSizeChange"
|
||||
style="text-align: right"
|
||||
layout="prev, pager, next, total, sizes"
|
||||
:total="total"
|
||||
v-model:current-page="queryForm.pageNum"
|
||||
@@ -165,7 +165,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRefs, watch, reactive, onMounted, Ref, ref, useSlots, toValue } from 'vue';
|
||||
import { toRefs, watch, reactive, onMounted, Ref, ref, useSlots, toValue, h } from 'vue';
|
||||
import { TableColumn } from './index';
|
||||
import EnumTag from '@/components/enumtag/EnumTag.vue';
|
||||
import { useThemeConfig } from '@/store/themeConfig';
|
||||
@@ -176,7 +176,7 @@ import { SearchItem } from '../SearchForm/index';
|
||||
import SearchFormItem from '../SearchForm/components/SearchFormItem.vue';
|
||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||
import { usePageTable } from '@/hooks/usePageTable';
|
||||
import { ElTable } from 'element-plus';
|
||||
import { ElInput, ElTable } from 'element-plus';
|
||||
|
||||
const emit = defineEmits(['update:selectionData', 'pageSizeChange', 'pageNumChange']);
|
||||
|
||||
@@ -240,6 +240,10 @@ const showToolButton = (key: 'setting' | 'search') => {
|
||||
|
||||
const nowSearchItem: Ref<SearchItem> = ref(null) as any;
|
||||
|
||||
// 是否已经计算列宽度
|
||||
const isCalculatedWidth: Ref<boolean> = ref(false);
|
||||
const showTable: Ref<boolean> = ref(false);
|
||||
|
||||
/**
|
||||
* 改变当前的搜索项
|
||||
* @param searchItem 当前点击的搜索项
|
||||
@@ -276,15 +280,31 @@ const state = reactive({
|
||||
const { pageSizes, formatVal } = toRefs(state);
|
||||
|
||||
watch(tableData, (newValue: any) => {
|
||||
if (newValue && newValue.length > 0) {
|
||||
props.columns.forEach((item) => {
|
||||
if (item.autoWidth && item.show) {
|
||||
item.autoCalculateMinWidth(tableData.value);
|
||||
}
|
||||
});
|
||||
calculateTableColumnMinWidth();
|
||||
// 需要计算完才能显示表格,否则会有表格闪烁的问题
|
||||
if (!showTable.value) {
|
||||
showTable.value = true;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 计算表格列宽
|
||||
*/
|
||||
const calculateTableColumnMinWidth = () => {
|
||||
if (isCalculatedWidth.value || !tableData.value || tableData.value.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算表格列宽
|
||||
props.columns.forEach((item) => {
|
||||
if (item.autoWidth && item.show) {
|
||||
item.autoCalculateMinWidth(tableData.value);
|
||||
}
|
||||
});
|
||||
|
||||
isCalculatedWidth.value = true;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(newValue: any) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="terminal-body" :style="{ height }">
|
||||
<div ref="terminalRef" class="terminal" />
|
||||
<div class="h-full w-full flex">
|
||||
<div ref="terminalRef" class="h-full w-full" :style="{ background: getTerminalTheme().background }" />
|
||||
|
||||
<TerminalSearch ref="terminalSearchRef" :search-addon="state.addon.search" @close="focus" />
|
||||
</div>
|
||||
@@ -18,7 +18,7 @@ import { useThemeConfig } from '@/store/themeConfig';
|
||||
import { ref, nextTick, reactive, onMounted, onBeforeUnmount, watch } from 'vue';
|
||||
import TerminalSearch from './TerminalSearch.vue';
|
||||
import { TerminalStatus } from './common';
|
||||
import { useDebounceFn, useEventListener } from '@vueuse/core';
|
||||
import { useDebounceFn, useEventListener, useIntervalFn } from '@vueuse/core';
|
||||
import themes from './themes';
|
||||
import { TrzszFilter } from 'trzsz';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
@@ -41,13 +41,6 @@ const props = defineProps({
|
||||
socketUrl: {
|
||||
type: String,
|
||||
},
|
||||
/**
|
||||
* 高度
|
||||
*/
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['statusChange']);
|
||||
@@ -60,7 +53,6 @@ const { themeConfig } = storeToRefs(useThemeConfig());
|
||||
// 终端实例
|
||||
let term: Terminal;
|
||||
let socket: WebSocket;
|
||||
let pingInterval: any;
|
||||
|
||||
const state = reactive({
|
||||
// 插件
|
||||
@@ -89,7 +81,9 @@ watch(
|
||||
watch(
|
||||
() => themeConfig.value.terminalTheme,
|
||||
() => {
|
||||
term.options.theme = getTerminalTheme();
|
||||
if (term) {
|
||||
term.options.theme = getTerminalTheme();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -154,7 +148,8 @@ function initSocket() {
|
||||
// 监听socket连接
|
||||
socket.onopen = () => {
|
||||
// 注册心跳
|
||||
pingInterval = setInterval(sendPing, 15000);
|
||||
useIntervalFn(sendPing, 15000);
|
||||
|
||||
state.status = TerminalStatus.Connected;
|
||||
|
||||
focus();
|
||||
@@ -289,8 +284,6 @@ function sendCmd(key: any) {
|
||||
function closeSocket() {
|
||||
// 关闭 websocket
|
||||
socket && socket.readyState === 1 && socket.close();
|
||||
// 清除 ping
|
||||
pingInterval && clearInterval(pingInterval);
|
||||
}
|
||||
|
||||
function close() {
|
||||
@@ -310,17 +303,4 @@ const getStatus = (): TerminalStatus => {
|
||||
|
||||
defineExpose({ init, fitTerminal, focus, clear, close, getStatus, sendResize, write2Term, writeln2Term });
|
||||
</script>
|
||||
<style lang="scss">
|
||||
#terminal-body {
|
||||
width: 100%;
|
||||
|
||||
.terminal {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
// .xterm .xterm-viewport {
|
||||
// overflow-y: hidden;
|
||||
// }
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss"></style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-drawer v-model="visible" :before-close="cancel" size="50%">
|
||||
<el-drawer v-model="visible" :before-close="cancel" size="50%" body-class="flex flex-col">
|
||||
<template #header>
|
||||
<DrawerHeader :header="props.title" :back="cancel">
|
||||
<template #extra>
|
||||
@@ -13,7 +13,7 @@
|
||||
<el-descriptions-item v-for="(value, key) in extra" :key="key" :span="1" :label="key">{{ value }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<TerminalBody class="mb-2" ref="terminalRef" height="calc(100vh - 220px)" />
|
||||
<TerminalBody class="mb-2 flex-1" ref="terminalRef" />
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -22,7 +22,7 @@ export const usePageTable = (
|
||||
) => {
|
||||
const state = reactive({
|
||||
// 表格数据
|
||||
tableData: [],
|
||||
tableData: [{}],
|
||||
// 总数量
|
||||
total: 0,
|
||||
// 查询参数,包含分页参数
|
||||
|
||||
@@ -2,11 +2,11 @@ import router from '@/router';
|
||||
import { clearUser, getClientId, getRefreshToken, getToken, saveRefreshToken, saveToken } from '@/common/utils/storage';
|
||||
import { templateResolve } from '@/common/utils/string';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { createFetch } from '@vueuse/core';
|
||||
import { createFetch, UseFetchReturn } from '@vueuse/core';
|
||||
import Api from '@/common/Api';
|
||||
import { Result, ResultEnum } from '@/common/request';
|
||||
import config from '@/common/config';
|
||||
import { unref } from 'vue';
|
||||
import { ref, unref } from 'vue';
|
||||
import { URL_401 } from '@/router/staticRouter';
|
||||
import openApi from '@/common/openApi';
|
||||
import { useThemeConfig } from '@/store/themeConfig';
|
||||
@@ -92,12 +92,15 @@ export function useApiFetch<T>(api: Api, params: any = null, reqOptions: Request
|
||||
},
|
||||
});
|
||||
|
||||
// 统一处理后的返回结果,如果直接使用uaf.data,则数据会出现由{code: x, data: {}} -> data 的变化导致某些结果绑定报错
|
||||
const data = ref<T | null>(null);
|
||||
return {
|
||||
execute: async function () {
|
||||
return execCustomFetch(uaf);
|
||||
await execCustomFetch(uaf);
|
||||
data.value = uaf.data.value;
|
||||
},
|
||||
isFetching: uaf.isFetching,
|
||||
data: uaf.data,
|
||||
data: data,
|
||||
abort: uaf.abort,
|
||||
};
|
||||
}
|
||||
@@ -105,7 +108,7 @@ export function useApiFetch<T>(api: Api, params: any = null, reqOptions: Request
|
||||
let refreshingToken = false;
|
||||
let queue: any[] = [];
|
||||
|
||||
async function execCustomFetch(uaf: any) {
|
||||
async function execCustomFetch(uaf: UseFetchReturn<any>) {
|
||||
try {
|
||||
await uaf.execute(true);
|
||||
} catch (e: any) {
|
||||
@@ -118,22 +121,22 @@ async function execCustomFetch(uaf: any) {
|
||||
|
||||
const respStatus = uaf.response.value?.status;
|
||||
if (respStatus == 404) {
|
||||
ElMessage.error('请求接口不存在');
|
||||
ElMessage.error('url not found');
|
||||
return rejectPromise;
|
||||
}
|
||||
if (respStatus == 500) {
|
||||
ElMessage.error('服务器响应异常');
|
||||
ElMessage.error('server error');
|
||||
return rejectPromise;
|
||||
}
|
||||
|
||||
console.error(e);
|
||||
ElMessage.error('网络请求错误');
|
||||
ElMessage.error('network error');
|
||||
return rejectPromise;
|
||||
}
|
||||
|
||||
const result: Result = uaf.data.value as any;
|
||||
if (!result) {
|
||||
ElMessage.error('网络请求失败');
|
||||
ElMessage.error('network request failed');
|
||||
return Promise.reject(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-container class="layout-container flex-center">
|
||||
<Header />
|
||||
<el-container class="h-[calc(100vh-50px)]">
|
||||
<el-container class="flex-1 overflow-auto">
|
||||
<Aside />
|
||||
<div class="flex-center layout-backtop">
|
||||
<TagsView v-if="themeConfig.isTagsview" />
|
||||
|
||||
@@ -34,8 +34,6 @@ body,
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background-color: var(--bg-main-color);
|
||||
font-size: 14px;
|
||||
// overflow: hidden;
|
||||
// position: relative;
|
||||
}
|
||||
|
||||
/* 主布局样式
|
||||
|
||||
@@ -22,14 +22,21 @@
|
||||
|
||||
<el-table-column prop="res" :label="$t('flow.runResult')" :min-width="30" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-popover placement="top" :width="400" trigger="hover">
|
||||
<el-popover placement="top" width="50%" trigger="hover">
|
||||
<template #reference>
|
||||
<el-link icon="view" :type="scope.row.errorMsg ? 'danger' : 'success'" :underline="false"> </el-link>
|
||||
</template>
|
||||
|
||||
<el-text v-if="scope.row.errorMsg">{{ scope.row.errorMsg }}</el-text>
|
||||
<el-table v-else :data="scope.row.res" size="small">
|
||||
<el-table-column v-for="col in scope.row.columns" :key="col.name" :label="col.name" :prop="col.name" />
|
||||
<el-table max-height="600px" v-else :data="scope.row.res" size="small">
|
||||
<el-table-column
|
||||
:width="DbInst.flexColumnWidth(col.name, scope.row.res)"
|
||||
v-for="col in scope.row.columns"
|
||||
:key="col.name"
|
||||
:label="col.name"
|
||||
:prop="col.name"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</el-table>
|
||||
</el-popover>
|
||||
</template>
|
||||
@@ -50,6 +57,7 @@ import { tagApi } from '@/views/ops/tag/api';
|
||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||
import TagCodePath from '@/views/ops/component/TagCodePath.vue';
|
||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||
import { DbInst } from '@/views/ops/db/db';
|
||||
|
||||
const props = defineProps({
|
||||
procinst: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-card class="h-full flex" body-class="!p-1 flex flex-col flex-1 overflow-auto">
|
||||
<el-card class="h-full flex" body-class="!p-1 flex flex-col w-full">
|
||||
<el-input v-model="filterText" :placeholder="$t('tag.tagFilterPlaceholder')" clearable size="small" class="!mb-1 w-full" />
|
||||
<el-scrollbar>
|
||||
<el-tree
|
||||
@@ -22,7 +22,7 @@
|
||||
<span
|
||||
:id="node.key"
|
||||
@dblclick="treeNodeDblclick(data, node)"
|
||||
class="node-container flex items-center w-full cursor-pointer select-none"
|
||||
class="node-container flex items-center cursor-pointer select-none"
|
||||
:class="data.type.nodeDblclickFunc ? 'select-none' : ''"
|
||||
>
|
||||
<span v-if="data.type.value == TagTreeNode.TagPath">
|
||||
|
||||
@@ -65,10 +65,8 @@
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="cancel()">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="btnOk">{{ $t('common.confirm') }}</el-button>
|
||||
</div>
|
||||
<el-button @click="cancel()">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="btnOk">{{ $t('common.confirm') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -90,9 +88,6 @@ import { useI18nFormValidate } from '@/hooks/useI18n';
|
||||
import { Rules } from '@/common/rule';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
instance: {
|
||||
type: [Boolean, Object],
|
||||
},
|
||||
@@ -104,8 +99,10 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change', 'confirm']);
|
||||
const emit = defineEmits(['cancel', 'val-change', 'confirm']);
|
||||
|
||||
const rules = {
|
||||
instanceId: [Rules.requiredSelect('db.dbInst')],
|
||||
@@ -121,7 +118,6 @@ const dbForm: any = ref(null);
|
||||
// const tagSelectRef: any = ref(null);
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
allDatabases: [] as any,
|
||||
dbNamesSelected: [] as any,
|
||||
dbNamesFiltered: [] as any,
|
||||
@@ -142,28 +138,24 @@ const state = reactive({
|
||||
loadingDbNames: false,
|
||||
});
|
||||
|
||||
const { dialogVisible, allDatabases, form, dbNamesSelected } = toRefs(state);
|
||||
const { allDatabases, form, dbNamesSelected } = toRefs(state);
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
() => {
|
||||
state.dialogVisible = props.visible;
|
||||
if (!state.dialogVisible) {
|
||||
return;
|
||||
}
|
||||
const db: any = props.db;
|
||||
if (db.code) {
|
||||
state.form = { ...db };
|
||||
if (db.getDatabaseMode == DbGetDbNamesMode.Assign.value) {
|
||||
// 将数据库名使用空格切割,获取所有数据库列表
|
||||
state.dbNamesSelected = db.database.split(' ');
|
||||
}
|
||||
} else {
|
||||
state.form = { getDatabaseMode: DbGetDbNamesMode.Auto.value } as any;
|
||||
state.dbNamesSelected = [];
|
||||
}
|
||||
watch(dialogVisible, () => {
|
||||
if (!dialogVisible.value) {
|
||||
return;
|
||||
}
|
||||
);
|
||||
const db: any = props.db;
|
||||
if (db.code) {
|
||||
state.form = { ...db };
|
||||
if (db.getDatabaseMode == DbGetDbNamesMode.Assign.value) {
|
||||
// 将数据库名使用空格切割,获取所有数据库列表
|
||||
state.dbNamesSelected = db.database.split(' ');
|
||||
}
|
||||
} else {
|
||||
state.form = { getDatabaseMode: DbGetDbNamesMode.Auto.value } as any;
|
||||
state.dbNamesSelected = [];
|
||||
}
|
||||
});
|
||||
|
||||
const onChangeGetDatabaseMode = (val: any) => {
|
||||
if (val == DbGetDbNamesMode.Auto.value) {
|
||||
@@ -218,7 +210,7 @@ const resetInputDb = () => {
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
emit('update:visible', false);
|
||||
dialogVisible.value = false;
|
||||
emit('cancel');
|
||||
setTimeout(() => {
|
||||
resetInputDb();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<DrawerHeader :header="title" :back="cancel" />
|
||||
</template>
|
||||
|
||||
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
|
||||
<el-form :model="form" ref="dbFormRef" :rules="rules" label-width="auto">
|
||||
<el-divider content-position="left">{{ $t('common.basic') }}</el-divider>
|
||||
|
||||
<el-form-item ref="tagSelectRef" prop="tagCodePaths" :label="$t('tag.relateTag')">
|
||||
@@ -72,7 +72,7 @@
|
||||
<el-option label="SID" :value="2" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col style="text-align: center" :span="1">:</el-col>
|
||||
<el-col class="text-center" :span="1">:</el-col>
|
||||
<el-col :span="18">
|
||||
<el-input v-if="state.extra.stype == 1" v-model="state.extra.serviceName" placeholder="Service Name"> </el-input>
|
||||
<el-input v-else v-model="state.extra.sid" placeholder="SID"> </el-input>
|
||||
@@ -114,7 +114,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, toRefs, watchEffect } from 'vue';
|
||||
import { computed, reactive, ref, toRefs, watchEffect } from 'vue';
|
||||
import { dbApi } from './api';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import SshTunnelSelect from '../component/SshTunnelSelect.vue';
|
||||
@@ -133,9 +133,6 @@ import { Rules } from '@/common/rule';
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
data: {
|
||||
type: [Boolean, Object],
|
||||
},
|
||||
@@ -144,8 +141,10 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
|
||||
const emit = defineEmits(['cancel', 'val-change']);
|
||||
|
||||
const rules = {
|
||||
tagCodePaths: [Rules.requiredSelect('tag.relateTag')],
|
||||
@@ -154,7 +153,7 @@ const rules = {
|
||||
host: [Rules.requiredInput('Host:Port')],
|
||||
};
|
||||
|
||||
const dbForm: any = ref(null);
|
||||
const dbFormRef: any = ref(null);
|
||||
const tagSelectRef: any = ref(null);
|
||||
|
||||
const DefaultForm = {
|
||||
@@ -173,20 +172,30 @@ const DefaultForm = {
|
||||
};
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
extra: {} as any, // 连接需要的额外参数(json)
|
||||
form: DefaultForm,
|
||||
submitForm: {} as any,
|
||||
});
|
||||
|
||||
const { dialogVisible, form, submitForm } = toRefs(state);
|
||||
const { form } = toRefs(state);
|
||||
|
||||
const submitForm = computed(() => {
|
||||
const reqForm: any = { ...state.form };
|
||||
reqForm.selectAuthCert = null;
|
||||
reqForm.tags = null;
|
||||
if (!state.form.sshTunnelMachineId) {
|
||||
reqForm.sshTunnelMachineId = -1;
|
||||
}
|
||||
if (Object.keys(state.extra).length > 0) {
|
||||
reqForm.extra = state.extra;
|
||||
}
|
||||
return reqForm;
|
||||
});
|
||||
|
||||
const { isFetching: saveBtnLoading, execute: saveInstanceExec, data: saveInstanceRes } = dbApi.saveInstance.useApi(submitForm);
|
||||
const { isFetching: testConnBtnLoading, execute: testConnExec } = dbApi.testConn.useApi(submitForm);
|
||||
|
||||
watchEffect(() => {
|
||||
state.dialogVisible = props.visible;
|
||||
if (!state.dialogVisible) {
|
||||
if (!dialogVisible.value) {
|
||||
return;
|
||||
}
|
||||
const dbInst: any = props.data;
|
||||
@@ -200,31 +209,16 @@ watchEffect(() => {
|
||||
}
|
||||
});
|
||||
|
||||
const getReqForm = async () => {
|
||||
const reqForm: any = { ...state.form };
|
||||
reqForm.selectAuthCert = null;
|
||||
reqForm.tags = null;
|
||||
if (!state.form.sshTunnelMachineId) {
|
||||
reqForm.sshTunnelMachineId = -1;
|
||||
}
|
||||
if (Object.keys(state.extra).length > 0) {
|
||||
reqForm.extra = state.extra;
|
||||
}
|
||||
return reqForm;
|
||||
};
|
||||
|
||||
const testConn = async (authCert: any) => {
|
||||
await useI18nFormValidate(dbForm);
|
||||
state.submitForm = await getReqForm();
|
||||
state.submitForm.authCerts = [authCert];
|
||||
await useI18nFormValidate(dbFormRef);
|
||||
submitForm.value.authCerts = [authCert];
|
||||
await testConnExec();
|
||||
ElMessage.success(t('db.connSuccess'));
|
||||
};
|
||||
|
||||
const btnOk = async () => {
|
||||
await useI18nFormValidate(dbForm);
|
||||
state.submitForm = await getReqForm();
|
||||
notBlankI18n(state.submitForm.authCerts, 'db.acName');
|
||||
await useI18nFormValidate(dbFormRef);
|
||||
notBlankI18n(submitForm.value.authCerts, 'db.acName');
|
||||
await saveInstanceExec();
|
||||
useI18nSaveSuccessMsg();
|
||||
state.form.id = saveInstanceRes as any;
|
||||
@@ -233,7 +227,7 @@ const btnOk = async () => {
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
emit('update:visible', false);
|
||||
dialogVisible.value = false;
|
||||
emit('cancel');
|
||||
state.extra = {};
|
||||
};
|
||||
|
||||
@@ -4,23 +4,23 @@
|
||||
<DrawerHeader :header="title" :back="cancel" />
|
||||
</template>
|
||||
|
||||
<el-form label-position="left" ref="formRef" :model="tableData" label-width="80px">
|
||||
<el-row>
|
||||
<el-form label-position="left" ref="formRef" :model="tableData" label-width="auto">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="tableName" :label="$t('db.tableName')">
|
||||
<el-input style="width: 80%" v-model="tableData.tableName" size="small"></el-input>
|
||||
<el-input v-model="tableData.tableName" size="small"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="tableComment" :label="$t('db.comment')">
|
||||
<el-input style="width: 80%" v-model="tableData.tableComment" size="small"></el-input>
|
||||
<el-input v-model="tableData.tableComment" size="small"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="$t('db.column')" name="1">
|
||||
<el-table ref="tableRef" :data="tableData.fields.res" :max-height="tableData.height">
|
||||
<el-table ref="tableRef" :data="tableData.fields.res" :height="tableHeight">
|
||||
<el-table-column
|
||||
:prop="item.prop"
|
||||
:label="$t(item.label)"
|
||||
@@ -72,13 +72,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-row style="margin-top: 20px">
|
||||
<el-row class="mt-4">
|
||||
<el-button @click="addDefaultRows()" link type="warning" icon="plus">{{ $t('db.addDefaultColumn') }}</el-button>
|
||||
<el-button @click="addRow()" link type="primary" icon="plus">{{ $t('db.addColumn') }}</el-button>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('db.index')" name="2">
|
||||
<el-table :data="tableData.indexs.res" :max-height="tableData.height">
|
||||
<el-table :data="tableData.indexs.res" :height="tableHeight">
|
||||
<el-table-column :prop="item.prop" :label="$t(item.label)" v-for="item in tableData.indexs.colNames" :key="item.prop">
|
||||
<template #default="scope">
|
||||
<el-input v-if="item.prop === 'indexName'" size="small" disabled v-model="scope.row.indexName"></el-input>
|
||||
@@ -90,8 +90,8 @@
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
filterable
|
||||
size="small"
|
||||
@change="indexChanges(scope.row)"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option v-for="cl in tableData.indexs.columns" :key="cl.name" :label="cl.name" :value="cl.name">
|
||||
{{ cl.name + ' - ' + (cl.remark || '') }}
|
||||
@@ -114,7 +114,7 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-row style="margin-top: 20px">
|
||||
<el-row class="mt-4">
|
||||
<el-button @click="addIndex()" link type="primary" icon="plus">{{ $t('db.addIndex') }}</el-button>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
@@ -173,6 +173,8 @@ type ColName = {
|
||||
width?: number;
|
||||
};
|
||||
|
||||
const tableHeight = 'calc(100vh - 320px)';
|
||||
|
||||
const formRef: any = ref();
|
||||
const tableRef: any = useTemplateRef('tableRef');
|
||||
|
||||
@@ -272,7 +274,6 @@ const state = reactive({
|
||||
tableComment: '',
|
||||
oldTableName: '',
|
||||
oldTableComment: '',
|
||||
height: 'calc(100vh - 310px)',
|
||||
db: '',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div class="flex-all-center h-full">
|
||||
<div class="h-full">
|
||||
<ResourceOpPanel @resized="onResizeTagTree">
|
||||
<template #left>
|
||||
<tag-tree
|
||||
class="machine-terminal-tree"
|
||||
ref="tagTreeRef"
|
||||
:resource-type="TagResourceTypePath.MachineAuthCert"
|
||||
:tag-path-node-type="NodeTypeTagPath"
|
||||
@@ -34,7 +33,7 @@
|
||||
<template #right>
|
||||
<el-card class="h-full" body-class="machine-terminal-tabs h-full !p-1 flex flex-col flex-1">
|
||||
<el-tabs v-if="state.tabs.size > 0" type="card" @tab-remove="onRemoveTab" v-model="state.activeTermName" class="!h-full w-full">
|
||||
<el-tab-pane class="!h-full" closable v-for="dt in state.tabs.values()" :label="dt.label" :name="dt.key" :key="dt.key">
|
||||
<el-tab-pane class="!h-full flex flex-col" closable v-for="dt in state.tabs.values()" :label="dt.label" :name="dt.key" :key="dt.key">
|
||||
<template #label>
|
||||
<el-popconfirm @confirm="handleReconnect(dt, true)" :title="$t('machine.reConnTips')">
|
||||
<template #reference>
|
||||
@@ -63,7 +62,7 @@
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<div :ref="(el: any) => setTerminalWrapperRef(el, dt.key)" class="terminal-wrapper" style="height: calc(100vh - 155px)">
|
||||
<div :ref="(el: any) => setTerminalWrapperRef(el, dt.key)" class="terminal-wrapper flex-1 h-[calc(100vh-155px)]">
|
||||
<TerminalBody
|
||||
v-if="dt.params.protocol == MachineProtocolEnum.Ssh.value"
|
||||
:mount-init="false"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="mock-data-dialog">
|
||||
<div>
|
||||
<el-dialog
|
||||
:title="title"
|
||||
v-model="dialogVisible"
|
||||
@@ -35,8 +35,8 @@
|
||||
<dynamic-form-edit v-model="params" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item required prop="script" class="100w">
|
||||
<div style="width: 100%">
|
||||
<el-form-item required prop="script">
|
||||
<div class="w-full">
|
||||
<monaco-editor v-model="form.script" language="shell" height="300px" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
@@ -66,9 +66,6 @@ import { useI18nFormValidate, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
|
||||
import { Rules } from '@/common/rule';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
},
|
||||
@@ -83,7 +80,9 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'submitSuccess']);
|
||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
const emit = defineEmits(['cancel', 'submitSuccess']);
|
||||
|
||||
const rules = {
|
||||
name: [Rules.requiredInput('common.name')],
|
||||
@@ -96,7 +95,6 @@ const { isCommon, machineId } = toRefs(props);
|
||||
const scriptForm: any = ref(null);
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
params: [] as any,
|
||||
form: {
|
||||
id: null,
|
||||
@@ -110,11 +108,10 @@ const state = reactive({
|
||||
btnLoading: false,
|
||||
});
|
||||
|
||||
const { dialogVisible, params, form, btnLoading } = toRefs(state);
|
||||
const { params, form, btnLoading } = toRefs(state);
|
||||
|
||||
watch(props, (newValue: any) => {
|
||||
state.dialogVisible = newValue.visible;
|
||||
if (!newValue.visible) {
|
||||
if (!dialogVisible.value) {
|
||||
return;
|
||||
}
|
||||
if (newValue.data) {
|
||||
@@ -142,7 +139,7 @@ const btnOk = async () => {
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
emit('update:visible', false);
|
||||
dialogVisible.value = false;
|
||||
emit('cancel');
|
||||
state.params = [];
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="file-manage">
|
||||
<div>
|
||||
<el-dialog
|
||||
@open="getScripts()"
|
||||
:title="title"
|
||||
@@ -68,10 +68,11 @@
|
||||
:close-on-click-modal="false"
|
||||
:modal="false"
|
||||
@close="closeTermnial"
|
||||
body-class="h-[560px]"
|
||||
draggable
|
||||
append-to-body
|
||||
>
|
||||
<TerminalBody ref="terminal" :cmd="terminalDialog.cmd" :socket-url="getMachineTerminalSocketUrl(props.authCertName)" height="560px" />
|
||||
<TerminalBody ref="terminal" :cmd="terminalDialog.cmd" :socket-url="getMachineTerminalSocketUrl(props.authCertName)" />
|
||||
</el-dialog>
|
||||
|
||||
<script-edit
|
||||
@@ -86,7 +87,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, toRefs, reactive, watch, Ref } from 'vue';
|
||||
import { ref, toRefs, reactive, Ref } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import TerminalBody from '@/components/terminal/TerminalBody.vue';
|
||||
import { getMachineTerminalSocketUrl, machineApi } from './api';
|
||||
@@ -102,19 +103,19 @@ import { useI18nCreateTitle, useI18nDeleteConfirm, useI18nDeleteSuccessMsg, useI
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean },
|
||||
machineId: { type: Number },
|
||||
authCertName: { type: String },
|
||||
title: { type: String },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
|
||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
const emit = defineEmits(['cancel', 'update:machineId']);
|
||||
|
||||
const paramsForm: any = ref(null);
|
||||
const pageTableRef: Ref<any> = ref(null);
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
selectionData: [],
|
||||
searchItems: [SearchItem.select('type', 'common.type').withEnum(ScriptTypeEnum)],
|
||||
columns: [
|
||||
@@ -151,11 +152,7 @@ const state = reactive({
|
||||
},
|
||||
});
|
||||
|
||||
const { dialogVisible, columns, selectionData, query, editDialog, scriptParamsDialog, resultDialog, terminalDialog } = toRefs(state);
|
||||
|
||||
watch(props, async (newValue) => {
|
||||
state.dialogVisible = newValue.visible;
|
||||
});
|
||||
const { columns, selectionData, query, editDialog, scriptParamsDialog, resultDialog, terminalDialog } = toRefs(state);
|
||||
|
||||
const getScripts = async () => {
|
||||
pageTableRef.value.search();
|
||||
@@ -271,7 +268,7 @@ const deleteRow = async (rows: any) => {
|
||||
* 关闭取消按钮触发的事件
|
||||
*/
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
dialogVisible.value = false;
|
||||
emit('update:machineId', null);
|
||||
emit('cancel');
|
||||
state.query.type = ScriptTypeEnum.Private.value;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="file-manage">
|
||||
<div>
|
||||
<el-dialog v-if="dialogVisible" :title="title" v-model="dialogVisible" :show-close="true" :before-close="handleClose" width="50%">
|
||||
<el-table :data="fileTable" stripe style="width: 100%" v-loading="loading">
|
||||
<el-table :data="fileTable" stripe v-loading="loading">
|
||||
<el-table-column prop="name" :label="$t('common.name')" min-width="100px">
|
||||
<template #header>
|
||||
<el-button class="ml0" type="primary" circle size="small" icon="Plus" @click="add()"> </el-button>
|
||||
@@ -29,9 +29,8 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-row style="margin-top: 10px" type="flex" justify="end">
|
||||
<el-row class="mt-2" type="flex" justify="end">
|
||||
<el-pagination
|
||||
style="text-align: center"
|
||||
:total="total"
|
||||
layout="prev, pager, next, total, jumper"
|
||||
v-model:current-page="query.pageNum"
|
||||
@@ -41,7 +40,7 @@
|
||||
</el-pagination>
|
||||
</el-row>
|
||||
|
||||
<el-dialog destroy-on-close :title="fileDialog.title" v-model="fileDialog.visible" :close-on-click-modal="false" width="70%">
|
||||
<el-drawer destroy-on-close :title="fileDialog.title" v-model="fileDialog.visible" :close-on-click-modal="false" size="70%" header-class="!mb-0">
|
||||
<machine-file
|
||||
:title="fileDialog.title"
|
||||
:machine-id="machineId"
|
||||
@@ -50,7 +49,7 @@
|
||||
:path="fileDialog.path"
|
||||
:protocol="protocol"
|
||||
/>
|
||||
</el-dialog>
|
||||
</el-drawer>
|
||||
|
||||
<machine-file-content
|
||||
:title="fileContent.title"
|
||||
@@ -66,33 +65,29 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, toRefs, watch } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { machineApi } from '../api';
|
||||
import { FileTypeEnum } from '../enums';
|
||||
import MachineFile from './MachineFile.vue';
|
||||
import MachineFileContent from './MachineFileContent.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import EnumSelect from '@/components/enumselect/EnumSelect.vue';
|
||||
import { useI18nDeleteConfirm, useI18nSaveSuccessMsg } from '@/hooks/useI18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean },
|
||||
protocol: { type: Number, default: 1 },
|
||||
machineId: { type: Number },
|
||||
authCertName: { type: String },
|
||||
title: { type: String },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
|
||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
const emit = defineEmits(['cancel', 'update:machineId']);
|
||||
|
||||
const addFile = machineApi.addConf;
|
||||
const delFile = machineApi.delConf;
|
||||
const files = machineApi.files;
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
query: {
|
||||
id: 0,
|
||||
pageNum: 1,
|
||||
@@ -122,11 +117,10 @@ const state = reactive({
|
||||
},
|
||||
});
|
||||
|
||||
const { dialogVisible, loading, query, total, fileTable, fileDialog, fileContent } = toRefs(state);
|
||||
const { loading, query, total, fileTable, fileDialog, fileContent } = toRefs(state);
|
||||
|
||||
watch(props, async (newValue) => {
|
||||
state.dialogVisible = newValue.visible;
|
||||
if (newValue.machineId && newValue.visible) {
|
||||
if (newValue.machineId && dialogVisible.value) {
|
||||
await getFiles();
|
||||
}
|
||||
});
|
||||
@@ -198,28 +192,10 @@ const showFileContent = async (fileId: number, path: string) => {
|
||||
* 关闭取消按钮触发的事件
|
||||
*/
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
dialogVisible.value = false;
|
||||
emit('update:machineId', null);
|
||||
emit('cancel');
|
||||
state.fileTable = [];
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.machine-file-upload-exec {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
}
|
||||
.inline-block {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.margin-change {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss"></style>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<template>
|
||||
<div class="machine-file">
|
||||
<div>
|
||||
<el-progress v-if="uploadProgressShow" style="width: 90%; margin-left: 20px" :text-inside="true" :stroke-width="20" :percentage="progressNum" />
|
||||
<div class="machine-file h-full">
|
||||
<div class="h-full flex flex-col">
|
||||
<!-- 文件上传进度条 -->
|
||||
<el-progress v-if="uploadProgressShow" class="ml-4 w-[90%]" :text-inside="true" :stroke-width="20" :percentage="progressNum" />
|
||||
|
||||
<el-row class="mb-2">
|
||||
<!-- 文件路径 -->
|
||||
<el-row class="mb-2 ml-4">
|
||||
<el-breadcrumb separator-icon="ArrowRight">
|
||||
<el-breadcrumb-item v-for="path in filePathNav" :key="path">
|
||||
<el-link @click="setFiles(path.path)" style="font-weight: bold">{{ path.name }}</el-link>
|
||||
@@ -11,251 +13,259 @@
|
||||
</el-breadcrumb>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
ref="fileTableRef"
|
||||
@cell-dblclick="cellDbclick"
|
||||
@selection-change="handleSelectionChange"
|
||||
height="65vh"
|
||||
:data="filterFiles"
|
||||
highlight-current-row
|
||||
v-loading="loading"
|
||||
>
|
||||
<el-table-column type="selection" width="30" />
|
||||
<!-- 文件列表 -->
|
||||
<div class="flex-1 overflow-auto">
|
||||
<el-table
|
||||
ref="fileTableRef"
|
||||
@cell-dblclick="cellDbclick"
|
||||
@selection-change="handleSelectionChange"
|
||||
height="100%"
|
||||
:data="filterFiles"
|
||||
highlight-current-row
|
||||
v-loading="loading"
|
||||
>
|
||||
<el-table-column type="selection" width="30" />
|
||||
|
||||
<el-table-column prop="name" :label="$t('common.name')" min-width="380">
|
||||
<template #header>
|
||||
<div class="machine-file-table-header">
|
||||
<div>
|
||||
<el-button :disabled="nowPath == basePath" type="primary" circle size="small" icon="Back" @click="back()"> </el-button>
|
||||
<el-button class="!ml-1" type="primary" circle size="small" icon="Refresh" @click="refresh()"> </el-button>
|
||||
<!-- 文件名 -->
|
||||
<el-table-column prop="name" :label="$t('common.name')" min-width="380">
|
||||
<template #header>
|
||||
<div class="machine-file-table-header">
|
||||
<div>
|
||||
<el-button :disabled="nowPath == basePath" type="primary" circle size="small" icon="Back" @click="back()"> </el-button>
|
||||
<el-button class="!ml-1" type="primary" circle size="small" icon="Refresh" @click="refresh()"> </el-button>
|
||||
|
||||
<!-- 文件&文件夹上传 -->
|
||||
<el-dropdown class="machine-file-upload-exec" trigger="click" size="small">
|
||||
<span>
|
||||
<el-button
|
||||
v-auth="'machine:file:upload'"
|
||||
class="!ml-1"
|
||||
type="primary"
|
||||
circle
|
||||
size="small"
|
||||
icon="Upload"
|
||||
:title="$t('machine.upload')"
|
||||
></el-button>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>
|
||||
<el-upload
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="uploadSuccess"
|
||||
action=""
|
||||
:http-request="uploadFile"
|
||||
:headers="{ token }"
|
||||
:show-file-list="false"
|
||||
name="file"
|
||||
class="machine-file-upload-exec"
|
||||
>
|
||||
<el-link>{{ $t('machine.file') }}</el-link>
|
||||
</el-upload>
|
||||
</el-dropdown-item>
|
||||
<!-- 文件&文件夹上传 -->
|
||||
<el-dropdown class="machine-file-upload-exec" trigger="click" size="small">
|
||||
<span>
|
||||
<el-button
|
||||
v-auth="'machine:file:upload'"
|
||||
class="!ml-1"
|
||||
type="primary"
|
||||
circle
|
||||
size="small"
|
||||
icon="Upload"
|
||||
:title="$t('machine.upload')"
|
||||
></el-button>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>
|
||||
<el-upload
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="uploadSuccess"
|
||||
action=""
|
||||
:http-request="uploadFile"
|
||||
:headers="{ token }"
|
||||
:show-file-list="false"
|
||||
name="file"
|
||||
class="machine-file-upload-exec"
|
||||
>
|
||||
<el-link>{{ $t('machine.file') }}</el-link>
|
||||
</el-upload>
|
||||
</el-dropdown-item>
|
||||
|
||||
<el-dropdown-item>
|
||||
<div>
|
||||
<el-link @click="addFinderToList">{{ $t('machine.folder') }}</el-link>
|
||||
<input
|
||||
type="file"
|
||||
id="folderUploadInput"
|
||||
ref="folderUploadRef"
|
||||
webkitdirectory
|
||||
directory
|
||||
@change="uploadFolder"
|
||||
style="display: none"
|
||||
/>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
||||
<el-button
|
||||
:disabled="state.selectionFiles.length == 0"
|
||||
v-auth="'machine:file:rm'"
|
||||
@click="copyFile(state.selectionFiles)"
|
||||
class="!ml-1"
|
||||
type="primary"
|
||||
circle
|
||||
size="small"
|
||||
icon="CopyDocument"
|
||||
:title="$t('machine.copy')"
|
||||
>
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
:disabled="state.selectionFiles.length == 0"
|
||||
v-auth="'machine:file:rm'"
|
||||
@click="mvFile(state.selectionFiles)"
|
||||
class="!ml-1"
|
||||
type="primary"
|
||||
circle
|
||||
size="small"
|
||||
icon="Rank"
|
||||
:title="$t('machine.move')"
|
||||
>
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
v-auth="'machine:file:write'"
|
||||
@click="showCreateFileDialog()"
|
||||
class="!ml-1"
|
||||
type="primary"
|
||||
circle
|
||||
size="small"
|
||||
icon="FolderAdd"
|
||||
:title="$t('common.create')"
|
||||
>
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
:disabled="state.selectionFiles.length == 0"
|
||||
v-auth="'machine:file:rm'"
|
||||
@click="deleteFile(state.selectionFiles)"
|
||||
class="!ml-1"
|
||||
type="danger"
|
||||
circle
|
||||
size="small"
|
||||
icon="delete"
|
||||
:title="$t('common.delete')"
|
||||
>
|
||||
</el-button>
|
||||
|
||||
<el-button-group v-if="state.copyOrMvFile.paths.length > 0" size="small" class="!ml-1">
|
||||
<el-tooltip effect="customized" raw-content placement="top">
|
||||
<template #content>
|
||||
<div v-for="path in state.copyOrMvFile.paths" v-bind:key="path">{{ path }}</div>
|
||||
<el-dropdown-item>
|
||||
<div>
|
||||
<el-link @click="addFinderToList">{{ $t('machine.folder') }}</el-link>
|
||||
<input
|
||||
type="file"
|
||||
id="folderUploadInput"
|
||||
ref="folderUploadRef"
|
||||
webkitdirectory
|
||||
directory
|
||||
@change="uploadFolder"
|
||||
style="display: none"
|
||||
/>
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
||||
<el-button @click="pasteFile" type="primary">
|
||||
{{ isCpFile() ? $t('machine.copy') : $t('machine.move') }}
|
||||
{{ $t('machine.paste') }}{{ state.copyOrMvFile.paths.length }}</el-button
|
||||
>
|
||||
</el-tooltip>
|
||||
<el-button
|
||||
:disabled="state.selectionFiles.length == 0"
|
||||
v-auth="'machine:file:rm'"
|
||||
@click="copyFile(state.selectionFiles)"
|
||||
class="!ml-1"
|
||||
type="primary"
|
||||
circle
|
||||
size="small"
|
||||
icon="CopyDocument"
|
||||
:title="$t('machine.copy')"
|
||||
>
|
||||
</el-button>
|
||||
|
||||
<el-button icon="CloseBold" @click="cancelCopy" />
|
||||
</el-button-group>
|
||||
<el-button
|
||||
:disabled="state.selectionFiles.length == 0"
|
||||
v-auth="'machine:file:rm'"
|
||||
@click="mvFile(state.selectionFiles)"
|
||||
class="!ml-1"
|
||||
type="primary"
|
||||
circle
|
||||
size="small"
|
||||
icon="Rank"
|
||||
:title="$t('machine.move')"
|
||||
>
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
v-auth="'machine:file:write'"
|
||||
@click="showCreateFileDialog()"
|
||||
class="!ml-1"
|
||||
type="primary"
|
||||
circle
|
||||
size="small"
|
||||
icon="FolderAdd"
|
||||
:title="$t('common.create')"
|
||||
>
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
:disabled="state.selectionFiles.length == 0"
|
||||
v-auth="'machine:file:rm'"
|
||||
@click="deleteFile(state.selectionFiles)"
|
||||
class="!ml-1"
|
||||
type="danger"
|
||||
circle
|
||||
size="small"
|
||||
icon="delete"
|
||||
:title="$t('common.delete')"
|
||||
>
|
||||
</el-button>
|
||||
|
||||
<el-button-group v-if="state.copyOrMvFile.paths.length > 0" size="small" class="!ml-1">
|
||||
<el-tooltip effect="customized" raw-content placement="top">
|
||||
<template #content>
|
||||
<div v-for="path in state.copyOrMvFile.paths" v-bind:key="path">{{ path }}</div>
|
||||
</template>
|
||||
|
||||
<el-button @click="pasteFile" type="primary">
|
||||
{{ isCpFile() ? $t('machine.copy') : $t('machine.move') }}
|
||||
{{ $t('machine.paste') }}{{ state.copyOrMvFile.paths.length }}</el-button
|
||||
>
|
||||
</el-tooltip>
|
||||
|
||||
<el-button icon="CloseBold" @click="cancelCopy" />
|
||||
</el-button-group>
|
||||
</div>
|
||||
|
||||
<div class="w-[150px]">
|
||||
<el-input v-model="fileNameFilter" size="small" :placeholder="$t('machine.fileNameFilterPlaceholder')" clearable />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div style="width: 150px">
|
||||
<el-input v-model="fileNameFilter" size="small" :placeholder="$t('machine.fileNameFilterPlaceholder')" clearable />
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.isFolder">
|
||||
<SvgIcon :size="15" name="folder" color="#007AFF" />
|
||||
</span>
|
||||
<span v-else>
|
||||
<SvgIcon :size="15" :name="scope.row.icon" />
|
||||
</span>
|
||||
|
||||
<span class="!ml-1 inline-block w-[90%]">
|
||||
<div v-if="scope.row.nameEdit">
|
||||
<el-input
|
||||
@keyup.enter="fileRename(scope.row)"
|
||||
:ref="(el: any) => el?.focus()"
|
||||
@blur="filenameBlur(scope.row)"
|
||||
v-model="scope.row.name"
|
||||
/>
|
||||
</div>
|
||||
<el-link v-else @click="getFile(scope.row)" style="font-weight: bold" :underline="false">{{ scope.row.name }}</el-link>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="size" label="Size" min-width="90" sortable>
|
||||
<template #default="scope">
|
||||
<span style="color: #67c23a; font-weight: bold" v-if="scope.row.type == '-'"> {{ formatByteSize(scope.row.size) }} </span>
|
||||
<span style="color: #67c23a; font-weight: bold" v-if="scope.row.type == 'd' && scope.row.dirSize"> {{ scope.row.dirSize }} </span>
|
||||
<span style="color: #67c23a; font-weight: bold" v-if="scope.row.type == 'd' && !scope.row.dirSize">
|
||||
<el-button @click="getDirSize(scope.row)" type="primary" link :loading="scope.row.loadingDirSize">
|
||||
{{ $t('machine.calculate') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="mode" :label="$t('machine.attribute')" width="110"> </el-table-column>
|
||||
|
||||
<el-table-column v-if="$props.protocol == MachineProtocolEnum.Ssh.value" :label="$t('machine.user')" min-width="70" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ userMap.get(scope.row.uid)?.uname || scope.row.uid }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column v-if="$props.protocol == MachineProtocolEnum.Ssh.value" :label="$t('machine.group')" min-width="70" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ groupMap.get(scope.row.gid)?.gname || scope.row.gid }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="modTime" :label="$t('machine.modificationTime')" width="160" sortable> </el-table-column>
|
||||
|
||||
<el-table-column :width="100">
|
||||
<template #header>
|
||||
<el-popover placement="top" :width="270" trigger="hover">
|
||||
<template #reference>
|
||||
<SvgIcon name="QuestionFilled" :size="18" class="pointer-icon mr-2" />
|
||||
</template>
|
||||
<div>{{ $t('machine.renameTips') }}</div>
|
||||
</el-popover>
|
||||
{{ $t('common.operation') }}
|
||||
</template>
|
||||
|
||||
<template #default="scope">
|
||||
<div class="flex gap-1.5">
|
||||
<!-- 基础信息 -->
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
:title="`${scope.row.path} - ${$t('machine.fileDetail')}`"
|
||||
:width="520"
|
||||
trigger="click"
|
||||
@show="showFileStat(scope.row)"
|
||||
>
|
||||
<template #reference>
|
||||
<span style="color: #67c23a; font-weight: bold">
|
||||
<el-link
|
||||
@click="showFileStat(scope.row)"
|
||||
icon="InfoFilled"
|
||||
:underline="false"
|
||||
link
|
||||
:loading="scope.row.loadingStat"
|
||||
></el-link>
|
||||
</span>
|
||||
</template>
|
||||
<el-input disabled autosize v-model="scope.row.stat" type="textarea" />
|
||||
</el-popover>
|
||||
|
||||
<!-- 下载文件 -->
|
||||
<el-link
|
||||
@click="downloadFile(scope.row)"
|
||||
v-if="scope.row.type == '-'"
|
||||
v-auth="'machine:file:write'"
|
||||
type="primary"
|
||||
icon="download"
|
||||
:underline="false"
|
||||
:title="$t('machine.download')"
|
||||
></el-link>
|
||||
|
||||
<!-- 删除文件 -->
|
||||
<el-link
|
||||
@click="deleteFile([scope.row])"
|
||||
v-if="!dontOperate(scope.row)"
|
||||
v-auth="'machine:file:rm'"
|
||||
type="danger"
|
||||
icon="delete"
|
||||
:underline="false"
|
||||
:title="$t('common.delete')"
|
||||
></el-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.isFolder">
|
||||
<SvgIcon :size="15" name="folder" color="#007AFF" />
|
||||
</span>
|
||||
<span v-else>
|
||||
<SvgIcon :size="15" :name="scope.row.icon" />
|
||||
</span>
|
||||
|
||||
<span class="!ml-1" style="display: inline-block; width: 90%">
|
||||
<div v-if="scope.row.nameEdit">
|
||||
<el-input
|
||||
@keyup.enter="fileRename(scope.row)"
|
||||
:ref="(el: any) => el?.focus()"
|
||||
@blur="filenameBlur(scope.row)"
|
||||
v-model="scope.row.name"
|
||||
/>
|
||||
</div>
|
||||
<el-link v-else @click="getFile(scope.row)" style="font-weight: bold" :underline="false">{{ scope.row.name }}</el-link>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="size" label="Size" min-width="90" sortable>
|
||||
<template #default="scope">
|
||||
<span style="color: #67c23a; font-weight: bold" v-if="scope.row.type == '-'"> {{ formatByteSize(scope.row.size) }} </span>
|
||||
<span style="color: #67c23a; font-weight: bold" v-if="scope.row.type == 'd' && scope.row.dirSize"> {{ scope.row.dirSize }} </span>
|
||||
<span style="color: #67c23a; font-weight: bold" v-if="scope.row.type == 'd' && !scope.row.dirSize">
|
||||
<el-button @click="getDirSize(scope.row)" type="primary" link :loading="scope.row.loadingDirSize">
|
||||
{{ $t('machine.calculate') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="mode" :label="$t('machine.attribute')" width="110"> </el-table-column>
|
||||
|
||||
<el-table-column v-if="$props.protocol == MachineProtocolEnum.Ssh.value" :label="$t('machine.user')" min-width="70" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ userMap.get(scope.row.uid)?.uname || scope.row.uid }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column v-if="$props.protocol == MachineProtocolEnum.Ssh.value" :label="$t('machine.group')" min-width="70" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ groupMap.get(scope.row.gid)?.gname || scope.row.gid }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="modTime" :label="$t('machine.modificationTime')" width="160" sortable> </el-table-column>
|
||||
|
||||
<el-table-column :width="130">
|
||||
<template #header>
|
||||
<el-popover placement="top" :width="270" trigger="hover">
|
||||
<template #reference>
|
||||
<SvgIcon name="QuestionFilled" :size="18" class="pointer-icon mr-2" />
|
||||
</template>
|
||||
<div>{{ $t('machine.renameTips') }}</div>
|
||||
</el-popover>
|
||||
{{ $t('common.operation') }}
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-link
|
||||
@click="deleteFile([scope.row])"
|
||||
v-if="!dontOperate(scope.row)"
|
||||
v-auth="'machine:file:rm'"
|
||||
type="danger"
|
||||
icon="delete"
|
||||
:underline="false"
|
||||
:title="$t('common.delete')"
|
||||
></el-link>
|
||||
|
||||
<el-link
|
||||
@click="downloadFile(scope.row)"
|
||||
v-if="scope.row.type == '-'"
|
||||
v-auth="'machine:file:write'"
|
||||
type="primary"
|
||||
icon="download"
|
||||
:underline="false"
|
||||
class="ml-2"
|
||||
:title="$t('machine.download')"
|
||||
></el-link>
|
||||
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
:title="`${scope.row.path} - ${$t('machine.fileDetail')}`"
|
||||
:width="520"
|
||||
trigger="click"
|
||||
@show="showFileStat(scope.row)"
|
||||
>
|
||||
<template #reference>
|
||||
<span style="color: #67c23a; font-weight: bold">
|
||||
<el-link
|
||||
@click="showFileStat(scope.row)"
|
||||
icon="InfoFilled"
|
||||
:underline="false"
|
||||
link
|
||||
class="ml-2"
|
||||
:loading="scope.row.loadingStat"
|
||||
></el-link>
|
||||
</span>
|
||||
</template>
|
||||
<el-input disabled autosize v-model="scope.row.stat" type="textarea" />
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="machine-file-content">
|
||||
<div>
|
||||
<el-dialog
|
||||
destroy-on-close
|
||||
:before-close="handleClose"
|
||||
@@ -9,28 +9,25 @@
|
||||
top="5vh"
|
||||
width="65%"
|
||||
>
|
||||
<div>
|
||||
<monaco-editor :can-change-mode="true" v-model="content" :language="fileType" />
|
||||
<div v-loading="loadingContent">
|
||||
<monaco-editor :can-change-mode="true" v-model="fileContent" :language="fileType" />
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button v-auth="'machine:file:write'" type="primary" @click="updateContent">{{ $t('common.save') }}</el-button>
|
||||
</div>
|
||||
<el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button v-auth="'machine:file:write'" type="primary" @click="updateContent">{{ $t('common.save') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, toRefs, watch } from 'vue';
|
||||
import { computed, reactive, toRefs, watch } from 'vue';
|
||||
import { machineApi } from '../api';
|
||||
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
||||
import { useI18nSaveSuccessMsg } from '@/hooks/useI18n';
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
protocol: { type: Number, default: 1 },
|
||||
title: { type: String, default: '' },
|
||||
machineId: { type: Number },
|
||||
@@ -39,41 +36,50 @@ const props = defineProps({
|
||||
path: { type: String, default: '' },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
|
||||
const dialogVisible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
const emit = defineEmits(['cancel', 'update:machineId']);
|
||||
|
||||
const updateFileContent = machineApi.updateFileContent;
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
loadingContent: false,
|
||||
content: '',
|
||||
fileType: '',
|
||||
});
|
||||
|
||||
const { dialogVisible, content, fileType } = toRefs(state);
|
||||
const { fileType } = toRefs(state);
|
||||
|
||||
const {
|
||||
isFetching: loadingContent,
|
||||
execute: getFileContentExec,
|
||||
data: fileContent,
|
||||
} = machineApi.fileContent.useApi(
|
||||
computed(() => {
|
||||
return {
|
||||
fileId: props.fileId,
|
||||
path: props.path,
|
||||
machineId: props.machineId,
|
||||
authCertName: props.authCertName,
|
||||
protocol: props.protocol,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
watch(props, async (newValue) => {
|
||||
if (newValue.visible) {
|
||||
if (dialogVisible.value) {
|
||||
await getFileContent();
|
||||
}
|
||||
state.dialogVisible = newValue.visible;
|
||||
});
|
||||
|
||||
const getFileContent = async () => {
|
||||
const path = props.path;
|
||||
const res = await machineApi.fileContent.request({
|
||||
fileId: props.fileId,
|
||||
path,
|
||||
machineId: props.machineId,
|
||||
authCertName: props.authCertName,
|
||||
protocol: props.protocol,
|
||||
});
|
||||
state.fileType = getFileType(path);
|
||||
state.content = res;
|
||||
fileContent.value = '';
|
||||
state.fileType = getFileType(props.path);
|
||||
await getFileContentExec();
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
state.dialogVisible = false;
|
||||
emit('update:visible', false);
|
||||
dialogVisible.value = false;
|
||||
};
|
||||
|
||||
const updateContent = async () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="redis-data-op flex-all-center h-full">
|
||||
<div class="redis-data-op h-full">
|
||||
<ResourceOpPanel>
|
||||
<template #left>
|
||||
<tag-tree
|
||||
@@ -144,9 +144,9 @@
|
||||
</Pane>
|
||||
|
||||
<Pane>
|
||||
<div class="h-full card !p-1">
|
||||
<el-tabs @tab-remove="removeDataTab" v-model="state.activeName">
|
||||
<el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key">
|
||||
<div class="h-full card !p-1 key-deatil">
|
||||
<el-tabs class="h-full" @tab-remove="removeDataTab" v-model="state.activeName">
|
||||
<el-tab-pane class="h-full" closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key">
|
||||
<key-detail :redis="redisInst" :key-info="dt.keyInfo" @change-key="searchKey()" @del-key="delKey" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@@ -614,6 +614,18 @@ const delKey = async (key: string) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.key-deatil {
|
||||
.el-tabs__header {
|
||||
background-color: var(--el-color-white);
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
}
|
||||
|
||||
::v-deep(.el-tabs__item) {
|
||||
padding: 0 10px;
|
||||
height: 29px;
|
||||
}
|
||||
}
|
||||
|
||||
.redis-data-op {
|
||||
.key-list-vtree .folder-label {
|
||||
font-weight: bold;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="format-viewer-container">
|
||||
<div class="mb-1 float-right">
|
||||
<div class="mb-1 flex justify-end">
|
||||
<el-select v-model="selectedView" class="format-selector" size="small" placeholder="Text">
|
||||
<template #prefix>
|
||||
<SvgIcon name="view" />
|
||||
|
||||
@@ -1,21 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-container direction="vertical" class="key-tab-container">
|
||||
<!-- key info -->
|
||||
<key-header
|
||||
ref="keyHeader"
|
||||
:redis="props.redis"
|
||||
:key-info="state.keyInfo"
|
||||
@refresh-content="refreshContent"
|
||||
@del-key="delKey"
|
||||
@change-key="changeKey"
|
||||
class="key-header-info"
|
||||
>
|
||||
</key-header>
|
||||
<div class="flex flex-col h-full">
|
||||
<!-- key info -->
|
||||
<key-header :redis="props.redis" :key-info="state.keyInfo" @refresh-content="refreshContent" @del-key="delKey" @change-key="changeKey"> </key-header>
|
||||
|
||||
<!-- key content -->
|
||||
<component ref="keyValueRef" :is="components[componentName]" :redis="props.redis" :key-info="keyInfo"> </component>
|
||||
</el-container>
|
||||
<!-- key content , 暂不懂为啥要用h-0或者其他随便设个高度?,h-full就是不行会导致loadMore按钮不显示 -->
|
||||
<component class="h-0 flex-1" ref="keyValueRef" :is="components[componentName]" :redis="props.redis" :key-info="keyInfo"> </component>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@@ -106,24 +95,10 @@ onMounted(() => {
|
||||
});
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.key-tab-container {
|
||||
/*padding-left: 5px;*/
|
||||
}
|
||||
|
||||
.key-header-info {
|
||||
// margin-top: 15px;
|
||||
}
|
||||
|
||||
.key-content-container {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
// .key-detail-filter-value {
|
||||
// width: 90%;
|
||||
// height: 24px;
|
||||
// padding: 0 5px;
|
||||
// }
|
||||
|
||||
/*tooltip in table width limit*/
|
||||
.el-tooltip__popper {
|
||||
max-width: 50%;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex">
|
||||
<!-- key name -->
|
||||
<div class="key-header-item key-name-input">
|
||||
<el-input ref="keyNameInput" v-model="ki.key" :title="$t('redis.renameTips')" placeholder="KeyName">
|
||||
@@ -180,12 +180,6 @@ const ttlConveter = (ttl: any) => {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.key-header-item {
|
||||
/*padding-right: 15px;*/
|
||||
/*margin-bottom: 10px;*/
|
||||
float: left;
|
||||
}
|
||||
|
||||
.key-header-item.key-name-input {
|
||||
width: calc(100% - 322px);
|
||||
min-width: 230px;
|
||||
|
||||
@@ -1,37 +1,47 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
|
||||
<el-table size="small" border :data="hashValues" height="500" min-height="300" stripe>
|
||||
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="field" label="field" show-overflow-tooltip min-width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
|
||||
<el-table-column :label="$t('common.operation')">
|
||||
<template #header>
|
||||
<el-input
|
||||
class="key-detail-filter-value"
|
||||
v-model="state.filterValue"
|
||||
@keyup.enter="hscan(true, true)"
|
||||
:placeholder="$t('redis.filterPlaceholder')"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-link @click="showEditDialog(scope.row)" :underline="false" type="primary" icon="edit" plain></el-link>
|
||||
<el-popconfirm :title="$t('redis.deleteConfirm')" @confirm="hdel(scope.row.field, scope.$index)">
|
||||
<template #reference>
|
||||
<el-link v-auth="'redis:data:del'" :underline="false" type="danger" icon="delete" size="small" plain class="ml-1"></el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-auto">
|
||||
<el-table size="small" border :data="hashValues" height="100%" stripe>
|
||||
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="field" label="field" show-overflow-tooltip min-width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
|
||||
<el-table-column :label="$t('common.operation')">
|
||||
<template #header>
|
||||
<el-input
|
||||
v-model="state.filterValue"
|
||||
@keyup.enter="hscan(true, true)"
|
||||
:placeholder="$t('redis.filterPlaceholder')"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-link @click="showEditDialog(scope.row)" :underline="false" type="primary" icon="edit" plain></el-link>
|
||||
<el-popconfirm :title="$t('redis.deleteConfirm')" @confirm="hdel(scope.row.field, scope.$index)">
|
||||
<template #reference>
|
||||
<el-link v-auth="'redis:data:del'" :underline="false" type="danger" icon="delete" size="small" plain class="ml-1"></el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- load more content -->
|
||||
<div class="content-more-container">
|
||||
<el-button size="small" @click="hscan()" :disabled="loadMoreDisable" class="content-more-btn"> {{ $t('redis.loadMore') }} </el-button>
|
||||
</div>
|
||||
|
||||
<el-dialog :title="$t('redis.addNewLine')" v-model="editDialog.visible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-dialog
|
||||
:title="$t('redis.addNewLine')"
|
||||
v-model="editDialog.visible"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
:close-on-click-modal="false"
|
||||
body-class="p-1"
|
||||
>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<el-input v-model="editDialog.field" placeholder="field" />
|
||||
@@ -42,7 +52,7 @@
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<div>
|
||||
<el-button @click="editDialog.visible = false">{{ $t('common.cancel') }}</el-button>
|
||||
<el-button v-auth="'redis:data:save'" type="primary" @click="confirmEditData">{{ $t('common.confirm') }}</el-button>
|
||||
</div>
|
||||
@@ -168,18 +178,4 @@ const confirmEditData = async () => {
|
||||
|
||||
defineExpose({ initData });
|
||||
</script>
|
||||
<style lang="scss">
|
||||
#string-value-text {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.text-type-select {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
max-width: 70px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss"></style>
|
||||
|
||||
@@ -1,26 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button @click="showEditDialog(null, -1)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
|
||||
<el-table size="small" border :data="values" height="450" min-height="300" stripe>
|
||||
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
|
||||
<el-table-column :label="$t('common.operation')">
|
||||
<template #default="scope">
|
||||
<el-link @click="showEditDialog(scope.row, scope.$index)" :underline="false" type="primary" icon="edit" plain></el-link>
|
||||
<el-popconfirm :title="$t('redis.deleteConfirm')" @confirm="lrem(scope.row, scope.$index)">
|
||||
<template #reference>
|
||||
<el-link v-auth="'redis:data:del'" :underline="false" type="danger" icon="delete" size="small" plain class="ml-1"></el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<el-button @click="showEditDialog(null, -1)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-auto">
|
||||
<el-table size="small" border :data="values" height="100%" stripe>
|
||||
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
|
||||
<el-table-column :label="$t('common.operation')">
|
||||
<template #default="scope">
|
||||
<el-link @click="showEditDialog(scope.row, scope.$index)" :underline="false" type="primary" icon="edit" plain></el-link>
|
||||
<el-popconfirm :title="$t('redis.deleteConfirm')" @confirm="lrem(scope.row, scope.$index)">
|
||||
<template #reference>
|
||||
<el-link v-auth="'redis:data:del'" :underline="false" type="danger" icon="delete" size="small" plain class="ml-1"></el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- load more content -->
|
||||
<div class="content-more-container">
|
||||
<el-button size="small" @click="getListValue(false)" :disabled="loadMoreDisable" class="content-more-btn"> {{ $t('redis.loadMore') }} </el-button>
|
||||
</div>
|
||||
|
||||
<el-dialog :title="$t('redis.addNewLine')" v-model="editDialog.visible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-dialog
|
||||
:title="$t('redis.addNewLine')"
|
||||
v-model="editDialog.visible"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
:close-on-click-modal="false"
|
||||
body-class="p-1"
|
||||
>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<format-viewer class="!w-full" ref="formatViewerRef" :content="editDialog.content"></format-viewer>
|
||||
|
||||
@@ -1,36 +1,46 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
|
||||
<el-table size="small" border :data="setDatas" height="450" min-height="300" stripe>
|
||||
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
|
||||
<el-table-column :label="$t('common.operation')">
|
||||
<template #header>
|
||||
<el-input
|
||||
class="key-detail-filter-value"
|
||||
v-model="state.filterValue"
|
||||
@keyup.enter="sscanData(true, true)"
|
||||
:placeholder="$t('redis.filterPlaceholder')"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-link @click="showEditDialog(scope.row)" :underline="false" type="primary" icon="edit" plain></el-link>
|
||||
<el-popconfirm :title="$t('redis.deleteConfirm')" @confirm="srem(scope.row, scope.$index)">
|
||||
<template #reference>
|
||||
<el-link v-auth="'redis:data:del'" :underline="false" type="danger" icon="delete" size="small" plain class="ml-1"></el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-auto">
|
||||
<el-table size="small" border :data="setDatas" height="100%" stripe>
|
||||
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
|
||||
<el-table-column :label="$t('common.operation')">
|
||||
<template #header>
|
||||
<el-input
|
||||
v-model="state.filterValue"
|
||||
@keyup.enter="sscanData(true, true)"
|
||||
:placeholder="$t('redis.filterPlaceholder')"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-link @click="showEditDialog(scope.row)" :underline="false" type="primary" icon="edit" plain></el-link>
|
||||
<el-popconfirm :title="$t('redis.deleteConfirm')" @confirm="srem(scope.row, scope.$index)">
|
||||
<template #reference>
|
||||
<el-link v-auth="'redis:data:del'" :underline="false" type="danger" icon="delete" size="small" plain class="ml-1"></el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- load more content -->
|
||||
<div class="content-more-container">
|
||||
<el-button size="small" @click="sscanData(false)" :disabled="loadMoreDisable" class="content-more-btn"> {{ $t('redis.loadMore') }} </el-button>
|
||||
</div>
|
||||
|
||||
<el-dialog :title="$t('redis.addNewLine')" v-model="editDialog.visible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-dialog
|
||||
:title="$t('redis.addNewLine')"
|
||||
v-model="editDialog.visible"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
:close-on-click-modal="false"
|
||||
body-class="p-1"
|
||||
>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<format-viewer class="!w-full" ref="formatViewerRef" :content="editDialog.content"></format-viewer>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form class="key-content-string" label-width="auto">
|
||||
<div>
|
||||
<format-viewer ref="formatViewerRef" height="250px" :content="string.value"></format-viewer>
|
||||
</div>
|
||||
<div class="flex flex-col h-full">
|
||||
<el-form label-width="auto">
|
||||
<format-viewer ref="formatViewerRef" height="280px" :content="string.value"></format-viewer>
|
||||
</el-form>
|
||||
<div class="!mt-2 float-right">
|
||||
<div class="mt-2 flex justify-end">
|
||||
<el-button @click="saveValue" type="primary" v-auth="'redis:data:save'">{{ $t('common.save') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -89,19 +87,4 @@ const saveValue = async () => {
|
||||
|
||||
defineExpose({ initData });
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// .key-content-string .format-viewer-container {
|
||||
// min-height: calc(100vh - 253px);
|
||||
// }
|
||||
|
||||
// /*text viewer box*/
|
||||
// .key-content-string .el-textarea textarea {
|
||||
// font-size: 14px;
|
||||
// height: calc(100vh - 436px);
|
||||
// }
|
||||
|
||||
// /*json in monaco editor*/
|
||||
// .key-content-string .monaco-editor-content {
|
||||
// height: calc(100vh - 450px) !important;
|
||||
// }
|
||||
</style>
|
||||
<style lang="scss"></style>
|
||||
|
||||
@@ -1,37 +1,48 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
|
||||
<el-table size="small" border :data="values" height="450" min-height="300" stripe>
|
||||
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="score" label="score" show-overflow-tooltip min-width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
|
||||
<el-table-column :label="$t('common.operation')">
|
||||
<template #header>
|
||||
<el-input
|
||||
class="key-detail-filter-value"
|
||||
v-model="state.filterValue"
|
||||
@keyup.enter="zscanData(true)"
|
||||
:placeholder="$t('redis.filterPlaceholder')"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-link @click="showEditDialog(scope.row)" :underline="false" type="primary" icon="edit" plain></el-link>
|
||||
<el-popconfirm :title="$t('redis.deleteConfirm')" @confirm="zrem(scope.row, scope.$index)">
|
||||
<template #reference>
|
||||
<el-link v-auth="'redis:data:del'" :underline="false" type="danger" icon="delete" size="small" plain class="ml-1"></el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<el-button @click="showEditDialog(null)" icon="plus" size="small" plain type="primary" class="mb-2">{{ $t('redis.addNewLine') }}</el-button>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 overflow-auto">
|
||||
<el-table size="small" border :data="values" height="100%" stripe>
|
||||
<el-table-column type="index" :label="'ID (Total: ' + total + ')'" sortable width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="score" label="score" show-overflow-tooltip min-width="100"> </el-table-column>
|
||||
<el-table-column resizable sortable prop="value" label="value" show-overflow-tooltip min-width="200"> </el-table-column>
|
||||
<el-table-column :label="$t('common.operation')">
|
||||
<template #header>
|
||||
<el-input
|
||||
v-model="state.filterValue"
|
||||
@keyup.enter="zscanData(true)"
|
||||
:placeholder="$t('redis.filterPlaceholder')"
|
||||
clearable
|
||||
size="small"
|
||||
/>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-link @click="showEditDialog(scope.row)" :underline="false" type="primary" icon="edit" plain></el-link>
|
||||
<el-popconfirm :title="$t('redis.deleteConfirm')" @confirm="zrem(scope.row, scope.$index)">
|
||||
<template #reference>
|
||||
<el-link v-auth="'redis:data:del'" :underline="false" type="danger" icon="delete" size="small" plain class="ml-1"></el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<!-- load more content -->
|
||||
<div class="content-more-container">
|
||||
<el-button size="small" @click="loadDatas()" :disabled="loadMoreDisable" class="content-more-btn"> {{ $t('redis.loadMore') }} </el-button>
|
||||
</div>
|
||||
|
||||
<el-dialog :title="$t('redis.addNewLine')" v-model="editDialog.visible" width="600px" :destroy-on-close="true" :close-on-click-modal="false">
|
||||
<el-dialog
|
||||
:title="$t('redis.addNewLine')"
|
||||
v-model="editDialog.visible"
|
||||
width="600px"
|
||||
:destroy-on-close="true"
|
||||
:close-on-click-modal="false"
|
||||
body-class="p-1"
|
||||
>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<el-input type="number" v-model.number="editDialog.score" placeholder="score" />
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
</div>
|
||||
<el-scrollbar class="tag-tree-data">
|
||||
<el-tree
|
||||
class="min-w-full inline-block"
|
||||
ref="tagTreeRef"
|
||||
node-key="id"
|
||||
highlight-current
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="account-dialog">
|
||||
<div>
|
||||
<el-dialog :title="title" v-model="visible" :before-close="cancel" :show-close="false" width="600px" :destroy-on-close="true">
|
||||
<el-form :model="form" ref="accountForm" :rules="rules" label-width="auto">
|
||||
<el-form-item prop="name" :label="$t('system.account.name')">
|
||||
@@ -73,7 +73,7 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
|
||||
const emit = defineEmits(['cancel', 'val-change']);
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-drawer :title="title" v-model="dvisible" :show-close="false" :before-close="cancel" size="1000px" :destroy-on-close="true">
|
||||
<el-drawer :title="title" v-model="visible" :show-close="false" :before-close="cancel" size="1000px" :destroy-on-close="true">
|
||||
<template #header>
|
||||
<DrawerHeader :header="title" :back="cancel" />
|
||||
</template>
|
||||
@@ -14,7 +14,6 @@
|
||||
</el-form-item>
|
||||
<el-form-item prop="permission" :label="$t('system.sysconf.permission')">
|
||||
<el-select
|
||||
style="width: 100%"
|
||||
remote
|
||||
:remote-method="getAccount"
|
||||
v-model="state.permissionAccount"
|
||||
@@ -58,9 +57,6 @@ const rules = {
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
data: {
|
||||
type: [Boolean, Object],
|
||||
},
|
||||
@@ -69,13 +65,14 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
|
||||
const emit = defineEmits(['cancel', 'val-change']);
|
||||
|
||||
const configForm: any = ref(null);
|
||||
|
||||
const state = reactive({
|
||||
dvisible: false,
|
||||
params: [] as any,
|
||||
accounts: [] as any,
|
||||
permissionAccount: [] as any,
|
||||
@@ -90,42 +87,37 @@ const state = reactive({
|
||||
},
|
||||
});
|
||||
|
||||
const { dvisible, params, form } = toRefs(state);
|
||||
const { params, form } = toRefs(state);
|
||||
|
||||
const { isFetching: saveBtnLoading, execute: saveConfigExec } = configApi.save.useApi(form);
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
() => {
|
||||
state.dvisible = props.visible;
|
||||
if (!state.dvisible) {
|
||||
return;
|
||||
}
|
||||
watch(visible, () => {
|
||||
if (!visible.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.data) {
|
||||
state.form = { ...(props.data as any) };
|
||||
if (state.form.params) {
|
||||
state.params = JSON.parse(state.form.params);
|
||||
} else {
|
||||
state.params = [];
|
||||
}
|
||||
if (props.data) {
|
||||
state.form = { ...(props.data as any) };
|
||||
if (state.form.params) {
|
||||
state.params = JSON.parse(state.form.params);
|
||||
} else {
|
||||
state.form = { permission: 'all' } as any;
|
||||
state.params = [];
|
||||
}
|
||||
|
||||
if (state.form.permission != 'all') {
|
||||
const accounts = state.form.permission.split(',');
|
||||
state.permissionAccount = accounts.slice(0, accounts.length - 1);
|
||||
} else {
|
||||
state.permissionAccount = [];
|
||||
}
|
||||
} else {
|
||||
state.form = { permission: 'all' } as any;
|
||||
state.params = [];
|
||||
}
|
||||
);
|
||||
|
||||
if (state.form.permission != 'all') {
|
||||
const accounts = state.form.permission.split(',');
|
||||
state.permissionAccount = accounts.slice(0, accounts.length - 1);
|
||||
} else {
|
||||
state.permissionAccount = [];
|
||||
}
|
||||
});
|
||||
|
||||
const cancel = () => {
|
||||
// 更新父组件visible prop对应的值为false
|
||||
emit('update:visible', false);
|
||||
visible.value = false;
|
||||
// 若父组件有取消事件,则调用
|
||||
emit('cancel');
|
||||
state.permissionAccount = [];
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
|
||||
import ConfigEdit from './ConfigEdit.vue';
|
||||
import { configApi } from '../api';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import PageTable from '@/components/pagetable/PageTable.vue';
|
||||
import { TableColumn } from '@/components/pagetable';
|
||||
import { hasPerms } from '@/components/auth/auth';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="system-menu-dialog-container layout-pd">
|
||||
<el-dialog :title="title" :destroy-on-close="true" v-model="dialogVisible" width="800px">
|
||||
<div>
|
||||
<el-dialog :title="title" :destroy-on-close="true" v-model="visible" width="800px">
|
||||
<el-form :model="form" :inline="true" ref="menuForm" :rules="rules" label-width="auto">
|
||||
<el-row :gutter="35">
|
||||
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
|
||||
@@ -111,9 +111,6 @@ import { Rules } from '@/common/rule';
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
data: {
|
||||
type: [Boolean, Object],
|
||||
},
|
||||
@@ -125,8 +122,10 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
|
||||
const emit = defineEmits(['cancel', 'val-change']);
|
||||
|
||||
const menuForm: any = ref(null);
|
||||
|
||||
@@ -161,7 +160,6 @@ const trueFalseOption = [
|
||||
];
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
form: {
|
||||
id: null,
|
||||
name: null,
|
||||
@@ -183,12 +181,14 @@ const state = reactive({
|
||||
submitForm: {},
|
||||
});
|
||||
|
||||
const { dialogVisible, form, submitForm } = toRefs(state);
|
||||
const { form, submitForm } = toRefs(state);
|
||||
|
||||
const { isFetching: saveBtnLoading, execute: saveResouceExec } = resourceApi.save.useApi(submitForm);
|
||||
|
||||
watchEffect(() => {
|
||||
state.dialogVisible = props.visible;
|
||||
if (!visible.value) {
|
||||
return;
|
||||
}
|
||||
if (props.data) {
|
||||
state.form = { ...(props.data as any) };
|
||||
} else {
|
||||
@@ -271,7 +271,7 @@ const parseMenuMeta = (meta: any) => {
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
emit('update:visible', false);
|
||||
visible.value = false;
|
||||
emit('cancel');
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
</div>
|
||||
<el-scrollbar>
|
||||
<el-tree
|
||||
class="inline-block min-w-full"
|
||||
ref="resourceTreeRef"
|
||||
:indent="24"
|
||||
node-key="id"
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
import { ref, toRefs, reactive, onMounted, Ref } from 'vue';
|
||||
import { AccountStatusEnum } from '../enums';
|
||||
import { accountApi, roleApi } from '../api';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import PageTable from '@/components/pagetable/PageTable.vue';
|
||||
import { TableColumn } from '@/components/pagetable';
|
||||
import { hasPerms } from '@/components/auth/auth';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<el-dialog
|
||||
:title="$t('system.role.allocateMenuTitle', { roleName: roleInfo?.name })"
|
||||
v-model="dialogVisible"
|
||||
v-model="visible"
|
||||
:before-close="cancel"
|
||||
:show-close="false"
|
||||
width="400px"
|
||||
@@ -46,9 +46,6 @@ import { getMenuIcon } from '../resource';
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
@@ -65,8 +62,10 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
|
||||
const emit = defineEmits(['cancel', 'val-change']);
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
@@ -76,17 +75,15 @@ const defaultProps = {
|
||||
const menuTree: any = ref(null);
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
roleInfo: null as any,
|
||||
submiting: false,
|
||||
});
|
||||
|
||||
const { dialogVisible, roleInfo } = toRefs(state);
|
||||
const { roleInfo } = toRefs(state);
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
() => visible,
|
||||
(newValue) => {
|
||||
state.dialogVisible = newValue;
|
||||
state.roleInfo = props.role;
|
||||
}
|
||||
);
|
||||
@@ -109,8 +106,7 @@ const btnOk = async () => {
|
||||
};
|
||||
|
||||
const cancel = () => {
|
||||
// 更新父组件visible prop对应的值为false
|
||||
emit('update:visible', false);
|
||||
visible.value = false;
|
||||
emit('cancel');
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="role-dialog">
|
||||
<el-dialog :title="title" v-model="dvisible" :show-close="false" :before-close="cancel" width="600px" :destroy-on-close="true">
|
||||
<div>
|
||||
<el-dialog :title="title" v-model="visible" :show-close="false" :before-close="cancel" width="600px" :destroy-on-close="true">
|
||||
<el-form ref="roleForm" :model="form" :rules="rules" label-width="auto">
|
||||
<el-form-item prop="name" :label="$t('system.role.roleName')" required>
|
||||
<el-input v-model="form.name" auto-complete="off"></el-input>
|
||||
@@ -45,9 +45,6 @@ const rules = {
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
data: {
|
||||
type: [Boolean, Object],
|
||||
},
|
||||
@@ -56,12 +53,13 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'val-change']);
|
||||
const emit = defineEmits(['cancel', 'val-change']);
|
||||
|
||||
const roleForm: any = ref(null);
|
||||
const state = reactive({
|
||||
dvisible: false,
|
||||
form: {
|
||||
id: null,
|
||||
name: '',
|
||||
@@ -71,12 +69,14 @@ const state = reactive({
|
||||
},
|
||||
});
|
||||
|
||||
const { dvisible, form } = toRefs(state);
|
||||
const { form } = toRefs(state);
|
||||
|
||||
const { isFetching: saveBtnLoading, execute: saveRoleExec } = roleApi.save.useApi(form);
|
||||
|
||||
watchEffect(() => {
|
||||
state.dvisible = props.visible;
|
||||
if (!visible.value) {
|
||||
return;
|
||||
}
|
||||
if (props.data) {
|
||||
state.form = { ...(props.data as any) };
|
||||
} else {
|
||||
@@ -85,8 +85,7 @@ watchEffect(() => {
|
||||
});
|
||||
|
||||
const cancel = () => {
|
||||
// 更新父组件visible prop对应的值为false
|
||||
emit('update:visible', false);
|
||||
visible.value = false;
|
||||
// 若父组件有取消事件,则调用
|
||||
emit('cancel');
|
||||
};
|
||||
|
||||
@@ -54,7 +54,6 @@ import RoleEdit from './RoleEdit.vue';
|
||||
import ResourceEdit from './ResourceEdit.vue';
|
||||
import ShowResource from './ShowResource.vue';
|
||||
import { roleApi, resourceApi } from '../api';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import PageTable from '@/components/pagetable/PageTable.vue';
|
||||
import { TableColumn } from '@/components/pagetable';
|
||||
import { hasPerms } from '@/components/auth/auth';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog @close="closeDialog" :title="title" :before-close="closeDialog" v-model="dialogVisible" width="400px">
|
||||
<el-tree style="height: 50vh; overflow: auto" :data="resources" node-key="id" :props="defaultProps">
|
||||
<el-dialog @close="closeDialog" :title="props.title" :before-close="closeDialog" v-model="visible" width="400px">
|
||||
<el-tree style="height: 50vh; overflow: auto" :data="props.resources" node-key="id" :props="defaultProps">
|
||||
<template #default="{ node, data }">
|
||||
<span class="custom-tree-node">
|
||||
<SvgIcon :name="getMenuIcon(data)" class="mb-0.5 mr-0.5" />
|
||||
@@ -35,15 +35,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRefs, reactive, watch } from 'vue';
|
||||
import { ResourceTypeEnum } from '../enums';
|
||||
import { formatDate } from '@/common/utils/format';
|
||||
import { getMenuIcon } from '../resource/index';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
},
|
||||
resources: {
|
||||
type: Array,
|
||||
},
|
||||
@@ -52,29 +48,15 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
//定义事件
|
||||
const emit = defineEmits(['update:visible', 'update:resources']);
|
||||
const visible = defineModel<boolean>('visible', { default: false });
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
};
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
});
|
||||
const { dialogVisible } = toRefs(state);
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(newValue) => {
|
||||
state.dialogVisible = newValue;
|
||||
}
|
||||
);
|
||||
|
||||
const closeDialog = () => {
|
||||
emit('update:visible', false);
|
||||
emit('update:resources', []);
|
||||
visible.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ func (p *procinstAppImpl) CancelProc(ctx context.Context, procinstId uint64) err
|
||||
if la == nil {
|
||||
return errorx.NewBiz("no login")
|
||||
}
|
||||
if procinst.CreatorId != consts.AdminId && procinst.CreatorId != la.Id {
|
||||
if la.Id != consts.AdminId && procinst.CreatorId != la.Id {
|
||||
return errorx.NewBizI(ctx, imsg.ErrProcinstCancelSelf)
|
||||
}
|
||||
procinst.Status = entity.ProcinstStatusCancelled
|
||||
|
||||
Reference in New Issue
Block a user