mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-09 23:17:21 +08:00
feat: 统一日志组件 (#5727)
This commit is contained in:
parent
d91ce3da65
commit
f3fac23a84
9 changed files with 146 additions and 257 deletions
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div style="display: flex; flex-wrap: wrap">
|
<div class="flex flex-wrap">
|
||||||
<el-select @change="searchLogs" v-model="logSearch.mode" class="selectWidth">
|
<el-select @change="searchLogs" v-model="logSearch.mode" class="selectWidth">
|
||||||
<template #prefix>{{ $t('container.fetch') }}</template>
|
<template #prefix>{{ $t('container.fetch') }}</template>
|
||||||
<el-option v-for="item in timeOptions" :key="item.label" :value="item.value" :label="item.label" />
|
<el-option v-for="item in timeOptions" :key="item.label" :value="item.value" :label="item.label" />
|
||||||
|
@ -25,17 +25,7 @@
|
||||||
{{ $t('commons.button.clean') }}
|
{{ $t('commons.button.clean') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<LogPro v-model="logInfo" :heightDiff="400"></LogPro>
|
||||||
<div :style="{ height: `calc(100vh - ${loadHeight()})`, 'margin-top': '10px', 'min-height': '400px' }">
|
|
||||||
<highlightjs
|
|
||||||
v-if="showLog"
|
|
||||||
ref="editorRef"
|
|
||||||
class="editor-main"
|
|
||||||
language="JavaScript"
|
|
||||||
:autodetect="false"
|
|
||||||
:code="logInfo"
|
|
||||||
></highlightjs>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -45,18 +35,10 @@ import i18n from '@/lang';
|
||||||
import { dateFormatForName, downloadWithContent } from '@/utils/util';
|
import { dateFormatForName, downloadWithContent } from '@/utils/util';
|
||||||
import { onBeforeUnmount, reactive, ref } from 'vue';
|
import { onBeforeUnmount, reactive, ref } from 'vue';
|
||||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||||
import { GlobalStore } from '@/store';
|
import LogPro from '@/components/log-pro/index.vue';
|
||||||
const globalStore = GlobalStore();
|
|
||||||
|
|
||||||
const logInfo = ref();
|
const logInfo = ref();
|
||||||
const terminalSocket = ref<WebSocket>();
|
const terminalSocket = ref<WebSocket>();
|
||||||
const editorRef = ref();
|
|
||||||
const scrollerElement = ref<HTMLElement | null>(null);
|
|
||||||
const showLog = ref(false);
|
|
||||||
|
|
||||||
const loadHeight = () => {
|
|
||||||
return globalStore.openMenuTabs ? '405px' : '375px';
|
|
||||||
};
|
|
||||||
|
|
||||||
const logSearch = reactive({
|
const logSearch = reactive({
|
||||||
isWatch: false,
|
isWatch: false,
|
||||||
|
@ -102,9 +84,6 @@ const searchLogs = async () => {
|
||||||
);
|
);
|
||||||
terminalSocket.value.onmessage = (event) => {
|
terminalSocket.value.onmessage = (event) => {
|
||||||
logInfo.value += event.data;
|
logInfo.value += event.data;
|
||||||
nextTick(() => {
|
|
||||||
scrollerElement.value.scrollTop = scrollerElement.value.scrollHeight;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,17 +131,6 @@ onBeforeUnmount(() => {
|
||||||
terminalSocket.value?.send('close conn');
|
terminalSocket.value?.send('close conn');
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await nextTick(() => {
|
|
||||||
showLog.value = true;
|
|
||||||
});
|
|
||||||
if (editorRef.value) {
|
|
||||||
scrollerElement.value = editorRef.value.$el as HTMLElement;
|
|
||||||
let hljsDom = scrollerElement.value.querySelector('.hljs') as HTMLElement;
|
|
||||||
hljsDom.style['min-height'] = '500px';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
acceptParams,
|
acceptParams,
|
||||||
});
|
});
|
||||||
|
|
61
frontend/src/components/log-pro/index.vue
Normal file
61
frontend/src/components/log-pro/index.vue
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<template>
|
||||||
|
<highlightjs
|
||||||
|
ref="editorRef"
|
||||||
|
language="JavaScript"
|
||||||
|
:style="customStyle"
|
||||||
|
:autodetect="false"
|
||||||
|
:code="content"
|
||||||
|
></highlightjs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { CSSProperties } from 'vue';
|
||||||
|
|
||||||
|
const editorRef = ref();
|
||||||
|
const scrollerElement = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
heightDiff: {
|
||||||
|
type: Number,
|
||||||
|
default: 280,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = ref('');
|
||||||
|
|
||||||
|
const customStyle = computed<CSSProperties>(() => ({
|
||||||
|
width: '100%',
|
||||||
|
overflow: 'auto',
|
||||||
|
}));
|
||||||
|
|
||||||
|
const initLog = async () => {
|
||||||
|
await nextTick();
|
||||||
|
if (editorRef.value && scrollerElement.value == undefined) {
|
||||||
|
const parentElement = editorRef.value.$el as HTMLElement;
|
||||||
|
scrollerElement.value = parentElement.querySelector('.hljs') as HTMLElement;
|
||||||
|
scrollerElement.value.style['min-height'] = '500px';
|
||||||
|
scrollerElement.value.style['max-height'] = 'calc(100vh - ' + props.heightDiff + 'px)';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
async (newValue) => {
|
||||||
|
if (editorRef.value && scrollerElement.value != undefined && newValue != content.value) {
|
||||||
|
content.value = newValue;
|
||||||
|
scrollerElement.value.scrollTop = scrollerElement.value.scrollHeight;
|
||||||
|
} else {
|
||||||
|
initLog();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initLog();
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -31,7 +31,7 @@
|
||||||
<el-option :value="500" :label="500" />
|
<el-option :value="500" :label="500" />
|
||||||
<el-option :value="1000" :label="1000" />
|
<el-option :value="1000" :label="1000" />
|
||||||
</el-select>
|
</el-select>
|
||||||
<div class="margin-button" style="float: left">
|
<div class="margin-button float-left">
|
||||||
<el-checkbox border @change="searchLogs" v-model="logSearch.isWatch">
|
<el-checkbox border @change="searchLogs" v-model="logSearch.isWatch">
|
||||||
{{ $t('commons.button.watch') }}
|
{{ $t('commons.button.watch') }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
|
@ -43,14 +43,7 @@
|
||||||
{{ $t('commons.button.clean') }}
|
{{ $t('commons.button.clean') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<LogPro v-model="logInfo"></LogPro>
|
||||||
<highlightjs
|
|
||||||
class="mt-10 editor-main"
|
|
||||||
ref="editorRef"
|
|
||||||
language="JavaScript"
|
|
||||||
:autodetect="false"
|
|
||||||
:code="logInfo"
|
|
||||||
></highlightjs>
|
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
|
@ -70,6 +63,7 @@ import { ElMessageBox } from 'element-plus';
|
||||||
import { MsgError, MsgSuccess } from '@/utils/message';
|
import { MsgError, MsgSuccess } from '@/utils/message';
|
||||||
import screenfull from 'screenfull';
|
import screenfull from 'screenfull';
|
||||||
import { GlobalStore } from '@/store';
|
import { GlobalStore } from '@/store';
|
||||||
|
import LogPro from '@/components/log-pro/index.vue';
|
||||||
|
|
||||||
const logVisible = ref(false);
|
const logVisible = ref(false);
|
||||||
const mobile = computed(() => {
|
const mobile = computed(() => {
|
||||||
|
@ -79,8 +73,6 @@ const mobile = computed(() => {
|
||||||
const logInfo = ref<string>('');
|
const logInfo = ref<string>('');
|
||||||
const globalStore = GlobalStore();
|
const globalStore = GlobalStore();
|
||||||
const terminalSocket = ref<WebSocket>();
|
const terminalSocket = ref<WebSocket>();
|
||||||
const editorRef = ref();
|
|
||||||
const scrollerElement = ref<HTMLElement | null>(null);
|
|
||||||
|
|
||||||
const logSearch = reactive({
|
const logSearch = reactive({
|
||||||
isWatch: true,
|
isWatch: true,
|
||||||
|
@ -142,10 +134,6 @@ const searchLogs = async () => {
|
||||||
);
|
);
|
||||||
terminalSocket.value.onmessage = (event) => {
|
terminalSocket.value.onmessage = (event) => {
|
||||||
logInfo.value += event.data.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '');
|
logInfo.value += event.data.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, '');
|
||||||
nextTick(() => {
|
|
||||||
initLog();
|
|
||||||
scrollerElement.value.scrollTop = scrollerElement.value.scrollHeight;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,13 +203,6 @@ const acceptParams = (props: DialogProps): void => {
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
handleClose();
|
handleClose();
|
||||||
});
|
});
|
||||||
const initLog = () => {
|
|
||||||
if (editorRef.value && scrollerElement.value == undefined) {
|
|
||||||
scrollerElement.value = editorRef.value.$el as HTMLElement;
|
|
||||||
let hljsDom = scrollerElement.value.querySelector('.hljs') as HTMLElement;
|
|
||||||
hljsDom.style['min-height'] = '500px';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
acceptParams,
|
acceptParams,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
type="primary"
|
type="primary"
|
||||||
:disabled="mysqlStatus !== 'Running'"
|
:disabled="mysqlStatus !== 'Running'"
|
||||||
:plain="activeName !== 'status'"
|
:plain="activeName !== 'status'"
|
||||||
@click="activeName = 'status'"
|
@click="changeTab('status')"
|
||||||
>
|
>
|
||||||
{{ $t('database.currentStatus') }}
|
{{ $t('database.currentStatus') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
type="primary"
|
type="primary"
|
||||||
:disabled="mysqlStatus !== 'Running'"
|
:disabled="mysqlStatus !== 'Running'"
|
||||||
:plain="activeName !== 'tuning'"
|
:plain="activeName !== 'tuning'"
|
||||||
@click="activeName = 'tuning'"
|
@click="changeTab('tuning')"
|
||||||
>
|
>
|
||||||
{{ $t('database.performanceTuning') }}
|
{{ $t('database.performanceTuning') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -28,14 +28,14 @@
|
||||||
type="primary"
|
type="primary"
|
||||||
:disabled="mysqlStatus !== 'Running'"
|
:disabled="mysqlStatus !== 'Running'"
|
||||||
:plain="activeName !== 'log'"
|
:plain="activeName !== 'log'"
|
||||||
@click="activeName = 'log'"
|
@click="changeTab('log')"
|
||||||
>
|
>
|
||||||
{{ $t('database.log') }}
|
{{ $t('database.log') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
:disabled="mysqlStatus !== 'Running'"
|
:disabled="mysqlStatus !== 'Running'"
|
||||||
@click="jumpToSlowlog"
|
@click="changeTab('slowLog')"
|
||||||
:plain="activeName !== 'slowLog'"
|
:plain="activeName !== 'slowLog'"
|
||||||
>
|
>
|
||||||
{{ $t('database.slowLog') }}
|
{{ $t('database.slowLog') }}
|
||||||
|
@ -48,19 +48,7 @@
|
||||||
|
|
||||||
<template #main>
|
<template #main>
|
||||||
<div v-if="activeName === 'conf'">
|
<div v-if="activeName === 'conf'">
|
||||||
<codemirror
|
<CodemirrorPro v-model="mysqlConf" :heightDiff="400"></CodemirrorPro>
|
||||||
:autofocus="true"
|
|
||||||
:placeholder="$t('commons.msg.noneData')"
|
|
||||||
:indent-with-tab="true"
|
|
||||||
:tabSize="4"
|
|
||||||
:style="{ height: `calc(100vh - ${loadHeight()})`, 'margin-top': '10px' }"
|
|
||||||
:lineWrapping="true"
|
|
||||||
:matchBrackets="true"
|
|
||||||
theme="cobalt"
|
|
||||||
:styleActiveLine="true"
|
|
||||||
:extensions="extensions"
|
|
||||||
v-model="mysqlConf"
|
|
||||||
/>
|
|
||||||
<el-button class="mt-2.5" @click="getDefaultConfig()">
|
<el-button class="mt-2.5" @click="getDefaultConfig()">
|
||||||
{{ $t('app.defaultConfig') }}
|
{{ $t('app.defaultConfig') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -79,9 +67,9 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<Status v-show="activeName === 'status'" ref="statusRef" />
|
<Status v-if="activeName === 'status'" ref="statusRef" />
|
||||||
<Variables @loading="changeLoading" v-show="activeName === 'tuning'" ref="variablesRef" />
|
<Variables @loading="changeLoading" v-if="activeName === 'tuning'" ref="variablesRef" />
|
||||||
<div v-show="activeName === 'port'">
|
<div v-if="activeName === 'port'">
|
||||||
<el-form :model="baseInfo" ref="panelFormRef" label-position="top">
|
<el-form :model="baseInfo" ref="panelFormRef" label-position="top">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="1"><br /></el-col>
|
<el-col :span="1"><br /></el-col>
|
||||||
|
@ -98,11 +86,11 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<ContainerLog v-show="activeName === 'log'" ref="dialogContainerLogRef" />
|
<ContainerLog v-if="activeName === 'log'" ref="dialogContainerLogRef" />
|
||||||
<SlowLog
|
<SlowLog
|
||||||
@loading="changeLoading"
|
@loading="changeLoading"
|
||||||
@refresh="loadBaseInfo"
|
@refresh="loadBaseInfo"
|
||||||
v-show="activeName === 'slowLog'"
|
v-if="activeName === 'slowLog'"
|
||||||
ref="slowLogRef"
|
ref="slowLogRef"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
@ -140,21 +128,16 @@ import Variables from '@/views/database/mysql/setting/variables/index.vue';
|
||||||
import SlowLog from '@/views/database/mysql/setting/slow-log/index.vue';
|
import SlowLog from '@/views/database/mysql/setting/slow-log/index.vue';
|
||||||
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
import { Codemirror } from 'vue-codemirror';
|
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
|
||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
|
||||||
import { loadDBFile, loadDBBaseInfo, loadMysqlVariables, updateDBFile } from '@/api/modules/database';
|
import { loadDBFile, loadDBBaseInfo, loadMysqlVariables, updateDBFile } from '@/api/modules/database';
|
||||||
import { ChangePort, CheckAppInstalled, GetAppDefaultConfig } from '@/api/modules/app';
|
import { ChangePort, CheckAppInstalled, GetAppDefaultConfig } from '@/api/modules/app';
|
||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import router from '@/routers';
|
import router from '@/routers';
|
||||||
import { GlobalStore } from '@/store';
|
import CodemirrorPro from '@/components/codemirror-pro/index.vue';
|
||||||
const globalStore = GlobalStore();
|
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const extensions = [javascript(), oneDark];
|
|
||||||
const activeName = ref('conf');
|
const activeName = ref('conf');
|
||||||
|
|
||||||
const baseInfo = reactive({
|
const baseInfo = reactive({
|
||||||
|
@ -194,13 +177,29 @@ const jumpToConf = async () => {
|
||||||
loadMysqlConf();
|
loadMysqlConf();
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadHeight = () => {
|
const changeTab = (tab: string) => {
|
||||||
return globalStore.openMenuTabs ? '405px' : '375px';
|
activeName.value = tab;
|
||||||
};
|
|
||||||
|
|
||||||
const jumpToSlowlog = async () => {
|
switch (tab) {
|
||||||
activeName.value = 'slowLog';
|
case 'log':
|
||||||
loadSlowLogs();
|
nextTick(() => {
|
||||||
|
loadContainerLog(baseInfo.containerID);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'slowLog':
|
||||||
|
nextTick(() => {
|
||||||
|
loadSlowLogs();
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'status':
|
||||||
|
nextTick(() => {
|
||||||
|
statusRef.value!.acceptParams({ type: props.type, database: props.database });
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'tuning':
|
||||||
|
loadVariables();
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmitChangePort = async () => {
|
const onSubmitChangePort = async () => {
|
||||||
|
@ -292,7 +291,6 @@ const loadBaseInfo = async () => {
|
||||||
baseInfo.port = res.data?.port;
|
baseInfo.port = res.data?.port;
|
||||||
baseInfo.containerID = res.data?.containerName;
|
baseInfo.containerID = res.data?.containerName;
|
||||||
loadMysqlConf();
|
loadMysqlConf();
|
||||||
loadContainerLog(baseInfo.containerID);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeLoading = (status: boolean) => {
|
const changeLoading = (status: boolean) => {
|
||||||
|
@ -345,11 +343,6 @@ const onLoadInfo = async () => {
|
||||||
mysqlStatus.value = res.data.status;
|
mysqlStatus.value = res.data.status;
|
||||||
mysqlVersion.value = res.data.version;
|
mysqlVersion.value = res.data.version;
|
||||||
loadBaseInfo();
|
loadBaseInfo();
|
||||||
if (mysqlStatus.value === 'Running') {
|
|
||||||
loadVariables();
|
|
||||||
loadSlowLogs();
|
|
||||||
statusRef.value!.acceptParams({ type: props.type, database: props.database });
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,61 +10,37 @@
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('database.longQueryTime')" v-if="detailShow">
|
<el-form-item :label="$t('database.longQueryTime')" v-if="detailShow">
|
||||||
<div style="float: left">
|
<div class="float-left">
|
||||||
<el-input type="number" v-model.number="variables.long_query_time" />
|
<el-input type="number" v-model.number="variables.long_query_time" />
|
||||||
</div>
|
</div>
|
||||||
<el-button style="float: left; margin-left: 10px" @click="changeSlowLogs">
|
<el-button class="float-left ml-5" @click="changeSlowLogs">
|
||||||
{{ $t('commons.button.save') }}
|
{{ $t('commons.button.save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<div style="float: left; margin-left: 20px">
|
<div class="float-left ml-10">
|
||||||
<el-checkbox style="margin-top: 2px" :disabled="!currentStatus" border v-model="isWatch">
|
<el-checkbox :disabled="!currentStatus" border v-model="isWatch">
|
||||||
{{ $t('commons.button.watch') }}
|
{{ $t('commons.button.watch') }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<el-button :disabled="!currentStatus" style="margin-left: 20px" @click="onDownload" icon="Download">
|
<el-button :disabled="!currentStatus" class="ml-20" @click="onDownload" icon="Download">
|
||||||
{{ $t('file.download') }}
|
{{ $t('file.download') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<codemirror
|
<LogPro v-model="slowLogs"></LogPro>
|
||||||
:autofocus="true"
|
|
||||||
:placeholder="$t('database.noData')"
|
|
||||||
:indent-with-tab="true"
|
|
||||||
:tabSize="4"
|
|
||||||
:style="{ height: getDynamicHeight(), width: '100%' }"
|
|
||||||
:lineWrapping="true"
|
|
||||||
:matchBrackets="true"
|
|
||||||
theme="cobalt"
|
|
||||||
:styleActiveLine="true"
|
|
||||||
:extensions="extensions"
|
|
||||||
@ready="handleReady"
|
|
||||||
v-model="slowLogs"
|
|
||||||
:disabled="true"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ConfirmDialog @cancel="onCancel" ref="confirmDialogRef" @confirm="onSave"></ConfirmDialog>
|
<ConfirmDialog @cancel="onCancel" ref="confirmDialogRef" @confirm="onSave"></ConfirmDialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Codemirror } from 'vue-codemirror';
|
import { onBeforeUnmount, reactive, ref } from 'vue';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
|
||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
|
||||||
import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue';
|
|
||||||
import { Database } from '@/api/interface/database';
|
import { Database } from '@/api/interface/database';
|
||||||
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
|
||||||
import { loadDBFile, updateMysqlVariables } from '@/api/modules/database';
|
import { loadDBFile, updateMysqlVariables } from '@/api/modules/database';
|
||||||
import { dateFormatForName, downloadWithContent } from '@/utils/util';
|
import { dateFormatForName, downloadWithContent } from '@/utils/util';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgError, MsgInfo, MsgSuccess } from '@/utils/message';
|
import { MsgError, MsgInfo, MsgSuccess } from '@/utils/message';
|
||||||
import { GlobalStore } from '@/store';
|
import LogPro from '@/components/log-pro/index.vue';
|
||||||
const globalStore = GlobalStore();
|
|
||||||
|
|
||||||
const extensions = [javascript(), oneDark];
|
|
||||||
const slowLogs = ref();
|
const slowLogs = ref();
|
||||||
const view = shallowRef();
|
|
||||||
const handleReady = (payload) => {
|
|
||||||
view.value = payload.view;
|
|
||||||
};
|
|
||||||
const detailShow = ref();
|
const detailShow = ref();
|
||||||
const currentStatus = ref();
|
const currentStatus = ref();
|
||||||
|
|
||||||
|
@ -121,20 +97,20 @@ const handleSlowLogs = async () => {
|
||||||
confirmDialogRef.value!.acceptParams(params);
|
confirmDialogRef.value!.acceptParams(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDynamicHeight = () => {
|
// const getDynamicHeight = () => {
|
||||||
if (variables.slow_query_log === 'ON') {
|
// if (variables.slow_query_log === 'ON') {
|
||||||
if (globalStore.openMenuTabs) {
|
// if (globalStore.openMenuTabs) {
|
||||||
return `calc(100vh - 467px)`;
|
// return `calc(100vh - 467px)`;
|
||||||
} else {
|
// } else {
|
||||||
return `calc(100vh - 437px)`;
|
// return `calc(100vh - 437px)`;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (globalStore.openMenuTabs) {
|
// if (globalStore.openMenuTabs) {
|
||||||
return `calc(100vh - 413px)`;
|
// return `calc(100vh - 413px)`;
|
||||||
} else {
|
// } else {
|
||||||
return `calc(100vh - 383px)`;
|
// return `calc(100vh - 383px)`;
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
const changeSlowLogs = () => {
|
const changeSlowLogs = () => {
|
||||||
if (!(variables.long_query_time > 0 && variables.long_query_time <= 600)) {
|
if (!(variables.long_query_time > 0 && variables.long_query_time <= 600)) {
|
||||||
|
@ -190,13 +166,13 @@ const onDownload = async () => {
|
||||||
const loadMysqlSlowlogs = async () => {
|
const loadMysqlSlowlogs = async () => {
|
||||||
const res = await loadDBFile(currentDB.type + '-slow-logs', currentDB.database);
|
const res = await loadDBFile(currentDB.type + '-slow-logs', currentDB.database);
|
||||||
slowLogs.value = res.data || '';
|
slowLogs.value = res.data || '';
|
||||||
nextTick(() => {
|
// nextTick(() => {
|
||||||
const state = view.value.state;
|
// const state = view.value.state;
|
||||||
view.value.dispatch({
|
// view.value.dispatch({
|
||||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
// selection: { anchor: state.doc.length, head: state.doc.length },
|
||||||
scrollIntoView: true,
|
// scrollIntoView: true,
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
};
|
};
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
|
|
||||||
<LayoutContent>
|
<LayoutContent>
|
||||||
<template #main>
|
<template #main>
|
||||||
<MainDiv :heightDiff="300">
|
<MainDiv :heightDiff="3200">
|
||||||
<el-radio-group v-model="confShowType" @change="changeMode">
|
<el-radio-group v-model="confShowType" @change="changeMode">
|
||||||
<el-radio-button value="base">{{ $t('database.baseConf') }}</el-radio-button>
|
<el-radio-button value="base">{{ $t('database.baseConf') }}</el-radio-button>
|
||||||
<el-radio-button value="all">{{ $t('database.allConf') }}</el-radio-button>
|
<el-radio-button value="all">{{ $t('database.allConf') }}</el-radio-button>
|
||||||
|
@ -125,19 +125,12 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<div v-if="confShowType === 'all'">
|
<div v-if="confShowType === 'all'">
|
||||||
<codemirror
|
<CodemirrorPro
|
||||||
:autofocus="true"
|
:heightDiff="400"
|
||||||
placeholder="# The SSH configuration file does not exist or is empty (/etc/ssh/sshd_config)"
|
class="mt-5"
|
||||||
:indent-with-tab="true"
|
|
||||||
:tabSize="4"
|
|
||||||
style="margin-top: 10px; height: calc(100vh - 405px)"
|
|
||||||
:lineWrapping="true"
|
|
||||||
:matchBrackets="true"
|
|
||||||
theme="cobalt"
|
|
||||||
:styleActiveLine="true"
|
|
||||||
:extensions="extensions"
|
|
||||||
v-model="sshConf"
|
v-model="sshConf"
|
||||||
/>
|
placeholder="# The SSH configuration file does not exist or is empty (/etc/ssh/sshd_config)"
|
||||||
|
></CodemirrorPro>
|
||||||
<el-button :disabled="loading" type="primary" @click="onSaveFile" style="margin-top: 5px">
|
<el-button :disabled="loading" type="primary" @click="onSaveFile" style="margin-top: 5px">
|
||||||
{{ $t('commons.button.save') }}
|
{{ $t('commons.button.save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
@ -155,10 +148,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { onMounted, reactive, ref } from 'vue';
|
||||||
import { Codemirror } from 'vue-codemirror';
|
|
||||||
import FireRouter from '@/views/host/ssh/index.vue';
|
import FireRouter from '@/views/host/ssh/index.vue';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
|
||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
|
||||||
import PubKey from '@/views/host/ssh/ssh/pubkey/index.vue';
|
import PubKey from '@/views/host/ssh/ssh/pubkey/index.vue';
|
||||||
import Root from '@/views/host/ssh/ssh/root/index.vue';
|
import Root from '@/views/host/ssh/ssh/root/index.vue';
|
||||||
import Port from '@/views/host/ssh/ssh/port/index.vue';
|
import Port from '@/views/host/ssh/ssh/port/index.vue';
|
||||||
|
@ -168,10 +158,10 @@ import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { getSSHConf, getSSHInfo, operateSSH, updateSSH, updateSSHByfile } from '@/api/modules/host';
|
import { getSSHConf, getSSHInfo, operateSSH, updateSSH, updateSSHByfile } from '@/api/modules/host';
|
||||||
import { ElMessageBox, FormInstance } from 'element-plus';
|
import { ElMessageBox, FormInstance } from 'element-plus';
|
||||||
|
import CodemirrorPro from '@/components/codemirror-pro/index.vue';
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const extensions = [javascript(), oneDark];
|
|
||||||
const confShowType = ref('base');
|
const confShowType = ref('base');
|
||||||
const pubKeyRef = ref();
|
const pubKeyRef = ref();
|
||||||
const portRef = ref();
|
const portRef = ref();
|
||||||
|
|
|
@ -143,22 +143,7 @@
|
||||||
<el-option :value="500" :label="500" />
|
<el-option :value="500" :label="500" />
|
||||||
<el-option :value="1000" :label="1000" />
|
<el-option :value="1000" :label="1000" />
|
||||||
</el-select>
|
</el-select>
|
||||||
<codemirror
|
<LogPro v-model="logContent"></LogPro>
|
||||||
ref="mymirror"
|
|
||||||
:autofocus="true"
|
|
||||||
:placeholder="$t('cronjob.noLogs')"
|
|
||||||
:indent-with-tab="true"
|
|
||||||
:tabSize="4"
|
|
||||||
style="height: calc(100vh - 498px); width: 100%; margin-top: 5px"
|
|
||||||
:lineWrapping="true"
|
|
||||||
:matchBrackets="true"
|
|
||||||
theme="cobalt"
|
|
||||||
:styleActiveLine="true"
|
|
||||||
:extensions="extensions"
|
|
||||||
@ready="handleReady"
|
|
||||||
v-model="logContent"
|
|
||||||
:disabled="true"
|
|
||||||
/>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -181,9 +166,6 @@
|
||||||
import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue';
|
import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { ElMessageBox } from 'element-plus';
|
import { ElMessageBox } from 'element-plus';
|
||||||
import { Codemirror } from 'vue-codemirror';
|
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
|
||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { shortcuts } from '@/utils/shortcuts';
|
import { shortcuts } from '@/utils/shortcuts';
|
||||||
import { Toolbox } from '@/api/interface/toolbox';
|
import { Toolbox } from '@/api/interface/toolbox';
|
||||||
|
@ -197,13 +179,6 @@ const hasRecords = ref();
|
||||||
|
|
||||||
let timer: NodeJS.Timer | null = null;
|
let timer: NodeJS.Timer | null = null;
|
||||||
|
|
||||||
const mymirror = ref();
|
|
||||||
const extensions = [javascript(), oneDark];
|
|
||||||
const view = shallowRef();
|
|
||||||
const handleReady = (payload) => {
|
|
||||||
view.value = payload.view;
|
|
||||||
};
|
|
||||||
|
|
||||||
const recordShow = ref(false);
|
const recordShow = ref(false);
|
||||||
interface DialogProps {
|
interface DialogProps {
|
||||||
rowData: Toolbox.ClamInfo;
|
rowData: Toolbox.ClamInfo;
|
||||||
|
@ -318,13 +293,6 @@ const loadRecordLog = async () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logContent.value = res.data;
|
logContent.value = res.data;
|
||||||
nextTick(() => {
|
|
||||||
const state = view.value.state;
|
|
||||||
view.value.dispatch({
|
|
||||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
|
||||||
scrollIntoView: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClean = async () => {
|
const onClean = async () => {
|
||||||
|
|
|
@ -38,22 +38,14 @@
|
||||||
<el-option :value="500" :label="500" />
|
<el-option :value="500" :label="500" />
|
||||||
<el-option :value="1000" :label="1000" />
|
<el-option :value="1000" :label="1000" />
|
||||||
</el-select>
|
</el-select>
|
||||||
<codemirror
|
<CodemirrorPro
|
||||||
:autofocus="true"
|
:heightDiff="400"
|
||||||
:placeholder="$t('commons.msg.noneData')"
|
class="mt-5"
|
||||||
:indent-with-tab="true"
|
|
||||||
:tabSize="4"
|
|
||||||
:style="{ height: `calc(100vh - ${loadHeight()})`, 'margin-top': '10px' }"
|
|
||||||
:lineWrapping="true"
|
|
||||||
:matchBrackets="true"
|
|
||||||
theme="cobalt"
|
|
||||||
:styleActiveLine="true"
|
|
||||||
@ready="handleReady"
|
|
||||||
:extensions="extensions"
|
|
||||||
v-model="content"
|
v-model="content"
|
||||||
:disabled="!canUpdate()"
|
:disabled="!canUpdate()"
|
||||||
/>
|
:placeholder="$t('commons.msg.noneData')"
|
||||||
<el-button type="primary" style="margin-top: 10px" v-if="canUpdate()" @click="onSave">
|
></CodemirrorPro>
|
||||||
|
<el-button type="primary" class="mt-5" v-if="canUpdate()" @click="onSave">
|
||||||
{{ $t('commons.button.save') }}
|
{{ $t('commons.button.save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,36 +58,19 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onMounted, ref, shallowRef } from 'vue';
|
import { nextTick, onMounted, ref, shallowRef } from 'vue';
|
||||||
import { Codemirror } from 'vue-codemirror';
|
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
|
||||||
import ClamStatus from '@/views/toolbox/clam/status/index.vue';
|
import ClamStatus from '@/views/toolbox/clam/status/index.vue';
|
||||||
import { searchClamFile, updateClamFile } from '@/api/modules/toolbox';
|
import { searchClamFile, updateClamFile } from '@/api/modules/toolbox';
|
||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
import CodemirrorPro from '@/components/codemirror-pro/index.vue';
|
||||||
import { GlobalStore } from '@/store';
|
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
const globalStore = GlobalStore();
|
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const extensions = [javascript(), oneDark];
|
|
||||||
const view = shallowRef();
|
|
||||||
const handleReady = (payload) => {
|
|
||||||
view.value = payload.view;
|
|
||||||
};
|
|
||||||
|
|
||||||
const activeName = ref('clamd');
|
const activeName = ref('clamd');
|
||||||
const tail = ref(200);
|
const tail = ref(200);
|
||||||
const content = ref();
|
const content = ref();
|
||||||
const confirmRef = ref();
|
const confirmRef = ref();
|
||||||
|
|
||||||
const loadHeight = () => {
|
|
||||||
let height = globalStore.openMenuTabs ? '405px' : '375px';
|
|
||||||
if (!canUpdate()) {
|
|
||||||
height = globalStore.openMenuTabs ? '383px' : '353px';
|
|
||||||
}
|
|
||||||
return height;
|
|
||||||
};
|
|
||||||
|
|
||||||
const canUpdate = () => {
|
const canUpdate = () => {
|
||||||
return activeName.value.indexOf('-log') === -1;
|
return activeName.value.indexOf('-log') === -1;
|
||||||
};
|
};
|
||||||
|
@ -110,13 +85,6 @@ const search = async (itemName?: string) => {
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
content.value = res.data;
|
content.value = res.data;
|
||||||
nextTick(() => {
|
|
||||||
const state = view.value.state;
|
|
||||||
view.value.dispatch({
|
|
||||||
selection: { anchor: state.doc.length, head: state.doc.length },
|
|
||||||
scrollIntoView: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|
|
@ -1,28 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
<codemirror
|
<LogPro v-model="content" :heightDiff="320"></LogPro>
|
||||||
:autofocus="true"
|
|
||||||
:placeholder="$t('commons.msg.noneData')"
|
|
||||||
:indent-with-tab="true"
|
|
||||||
:tabSize="4"
|
|
||||||
style="height: calc(100vh - 375px)"
|
|
||||||
:lineWrapping="true"
|
|
||||||
:matchBrackets="true"
|
|
||||||
theme="cobalt"
|
|
||||||
:styleActiveLine="true"
|
|
||||||
:extensions="extensions"
|
|
||||||
v-model="content"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { Codemirror } from 'vue-codemirror';
|
|
||||||
import { GetSupervisorLog } from '@/api/modules/host-tool';
|
import { GetSupervisorLog } from '@/api/modules/host-tool';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import LogPro from '@/components/log-pro/index.vue';
|
||||||
import { oneDark } from '@codemirror/theme-one-dark';
|
|
||||||
|
|
||||||
const extensions = [javascript(), oneDark];
|
|
||||||
|
|
||||||
let content = ref('');
|
let content = ref('');
|
||||||
let loading = ref(false);
|
let loading = ref(false);
|
||||||
|
|
Loading…
Add table
Reference in a new issue