1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 16:29:17 +08:00

feat: 修改页面二级导航栏样式

This commit is contained in:
ssongliu 2023-01-31 23:28:37 +08:00
parent e83bc0b675
commit d9a0ea1fe7
37 changed files with 844 additions and 833 deletions

View File

@ -364,6 +364,7 @@ export default {
rdbInfo: 'Rule list has 0 value, please confirm and try again!',
},
container: {
createContainer: 'Create container',
containerList: 'Container list',
operatorHelper: '{0} will be performed on the selected container. Do you want to continue?',
start: 'Start',
@ -387,7 +388,6 @@ export default {
emptyUser: 'When empty, you will log in with the default user of container',
containerTerminal: 'Container terminal',
containerCreate: 'Container create',
port: 'Port',
exposePort: 'Expose port',
exposeAll: 'Expose all',
@ -454,6 +454,7 @@ export default {
createVolume: 'Create volume',
repo: 'Repo',
createRepo: 'Create repo',
name: 'Name',
protocol: 'protocol',
httpRepo: 'The http repository needs to restart the docker service to add credit',
@ -467,7 +468,9 @@ export default {
registrieHelper: 'One in a row, for example:\n172.16.10.111:8081 \n172.16.10.112:8081',
compose: 'Compose',
createCompose: 'Create compose',
composeTemplate: 'Compose template',
createComposeTemplate: 'Create compose template',
description: 'Description',
content: 'Content',
containerNumber: 'Container number',
@ -773,6 +776,7 @@ export default {
upgradeNotes: 'Release note',
upgradeNow: 'Upgrade now',
monitor: 'Monitor',
enableMonitor: 'Enable',
storeDays: 'Expiration time (day)',
cleanMonitor: 'Clearing monitoring records',

View File

@ -4,7 +4,7 @@ export default {
false: '否',
example: '例如',
button: {
create: '',
create: '',
add: '添加',
save: '保存',
set: '设置',
@ -381,6 +381,7 @@ export default {
rdbInfo: '规则列表存在 0 请确认后重试',
},
container: {
createContainer: '创建容器',
containerList: '容器列表',
operatorHelper: '将对选中容器进行 {0} 操作是否继续',
start: '启动',
@ -404,7 +405,6 @@ export default {
containerTerminal: '容器终端',
emptyUser: '为空时将使用容器默认的用户登录',
containerCreate: '容器创建',
port: '端口',
exposePort: '暴露端口',
exposeAll: '暴露所有',
@ -462,7 +462,7 @@ export default {
imageNameHelper: '镜像名称及 Tagnginx:latest',
network: '网络',
createNetwork: '添加网络',
createNetwork: '创建网络',
networkName: '网络名',
driver: '模式',
option: '参数',
@ -477,6 +477,7 @@ export default {
createVolume: '创建存储卷',
repo: '仓库',
createRepo: '创建仓库',
name: '名称',
protocol: '协议',
downloadUrl: '下载地址',
@ -487,7 +488,9 @@ export default {
registrieHelper: '一行一个\n172.16.10.111:8081 \n172.16.10.112:8081',
compose: '编排',
createCompose: '创建编排',
composeTemplate: '编排模版',
createComposeTemplate: '创建编排模版',
description: '描述',
content: '内容',
containerNumber: '容器数量',
@ -788,6 +791,7 @@ export default {
mfaHelper2: '使用手机应用扫描以下二维码获取 6 位验证码',
mfaHelper3: '输入手机应用上的 6 位数字',
monitor: '监控',
enableMonitor: '监控状态',
storeDays: '过期时间 ()',
cleanMonitor: '清空监控记录',

View File

@ -4,94 +4,103 @@ const containerRouter = {
sort: 5,
path: '/containers',
component: Layout,
redirect: '/containers',
redirect: '/containers/container',
meta: {
icon: 'p-docker',
title: 'menu.container',
},
children: [
{
path: '',
name: 'Container',
component: () => import('@/views/container/container/index.vue'),
props: true,
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'composeDetail/:filters?',
name: 'ComposeDetail',
component: () => import('@/views/container/compose/detail/index.vue'),
props: true,
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'image',
name: 'Image',
component: () => import('@/views/container/image/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'network',
name: 'Network',
component: () => import('@/views/container/network/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'volume',
name: 'Volume',
component: () => import('@/views/container/volume/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'repo',
name: 'Repo',
component: () => import('@/views/container/repo/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'compose',
name: 'Compose',
component: () => import('@/views/container/compose/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'template',
name: 'ComposeTemplate',
component: () => import('@/views/container/template/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'setting',
name: 'ContainerSetting',
component: () => import('@/views/container/setting/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
path: '/containers',
name: 'Containers',
redirect: '/containers/container',
component: () => import('@/views/container/index.vue'),
meta: {},
children: [
{
path: 'container',
name: 'Container',
component: () => import('@/views/container/container/index.vue'),
props: true,
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'composeDetail/:filters?',
name: 'ComposeDetail',
component: () => import('@/views/container/compose/detail/index.vue'),
props: true,
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'image',
name: 'Image',
component: () => import('@/views/container/image/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'network',
name: 'Network',
component: () => import('@/views/container/network/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'volume',
name: 'Volume',
component: () => import('@/views/container/volume/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'repo',
name: 'Repo',
component: () => import('@/views/container/repo/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'compose',
name: 'Compose',
component: () => import('@/views/container/compose/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'template',
name: 'ComposeTemplate',
component: () => import('@/views/container/template/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
{
path: 'setting',
name: 'ContainerSetting',
component: () => import('@/views/container/setting/index.vue'),
hidden: true,
meta: {
activeMenu: '/containers',
},
},
],
},
],
};

View File

@ -4,29 +4,38 @@ const databaseRouter = {
sort: 4,
path: '/databases',
component: Layout,
redirect: '/databases',
redirect: '/databases/mysql',
meta: {
icon: 'p-database',
title: 'menu.database',
},
children: [
{
path: '',
name: 'Mysql',
component: () => import('@/views/database/mysql/index.vue'),
hidden: true,
meta: {
activeMenu: '/databases',
},
},
{
path: 'redis',
name: 'Redis',
component: () => import('@/views/database/redis/index.vue'),
hidden: true,
meta: {
activeMenu: '/databases',
},
path: '/databases',
name: 'Databases',
redirect: '/databases/mysql',
component: () => import('@/views/database/index.vue'),
meta: {},
children: [
{
path: 'mysql',
name: 'Mysql',
component: () => import('@/views/database/mysql/index.vue'),
hidden: true,
meta: {
activeMenu: '/databases',
},
},
{
path: 'redis',
name: 'Redis',
component: () => import('@/views/database/redis/index.vue'),
hidden: true,
meta: {
activeMenu: '/databases',
},
},
],
},
],
};

View File

@ -4,38 +4,47 @@ const logsRouter = {
sort: 7,
path: '/logs',
component: Layout,
redirect: '/logs',
redirect: '/logs/operation',
meta: {
title: 'menu.logs',
icon: 'p-log',
},
children: [
{
path: '',
name: 'OperationLog',
component: () => import('@/views/log/operation/index.vue'),
hidden: true,
meta: {
activeMenu: '/logs',
},
},
{
path: 'login',
name: 'LoginLog',
component: () => import('@/views/log/login/index.vue'),
hidden: true,
meta: {
activeMenu: '/logs',
},
},
{
path: 'system',
name: 'SystemLog',
component: () => import('@/views/log/system/index.vue'),
hidden: true,
meta: {
activeMenu: '/logs',
},
path: '/logs',
name: 'Log',
redirect: '/logs/operation',
component: () => import('@/views/log/index.vue'),
meta: {},
children: [
{
path: 'operation',
name: 'OperationLog',
component: () => import('@/views/log/operation/index.vue'),
hidden: true,
meta: {
activeMenu: '/logs',
},
},
{
path: 'login',
name: 'LoginLog',
component: () => import('@/views/log/login/index.vue'),
hidden: true,
meta: {
activeMenu: '/logs',
},
},
{
path: 'system',
name: 'SystemLog',
component: () => import('@/views/log/system/index.vue'),
hidden: true,
meta: {
activeMenu: '/logs',
},
},
],
},
],
};

View File

@ -4,81 +4,90 @@ const settingRouter = {
sort: 8,
path: '/settings',
component: Layout,
redirect: '/setting',
redirect: '/settings/panel',
meta: {
title: 'menu.settings',
icon: 'p-config',
},
children: [
{
path: '/setting',
name: 'Panel',
component: () => import('@/views/setting/panel/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
key: 'Setting',
},
},
{
path: '/setting/backupaccount',
name: 'BackupAccount',
component: () => import('@/views/setting/backup-account/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
key: 'Setting',
},
},
{
path: '/setting/about',
name: 'About',
component: () => import('@/views/setting/about/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
key: 'Setting',
},
},
{
path: '/setting/monitor',
name: 'Monitor',
component: () => import('@/views/setting/monitor/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
key: 'Setting',
},
},
{
path: '/setting/safe',
name: 'Safe',
component: () => import('@/views/setting/safe/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
key: 'Setting',
},
},
{
path: '/setting/snapshot',
name: 'Snapshot',
hidden: true,
component: () => import('@/views/setting/snapshot/index.vue'),
meta: {
requiresAuth: true,
key: 'Setting',
},
},
{
path: '/expired',
name: 'Expired',
hidden: true,
component: () => import('@/views/setting/expired.vue'),
meta: {
requiresAuth: true,
key: 'Expired',
},
path: '/settings',
name: 'Setting',
redirect: '/settings/panel',
component: () => import('@/views/setting/index.vue'),
meta: {},
children: [
{
path: 'panel',
name: 'Panel',
component: () => import('@/views/setting/panel/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
activeMenu: 'Setting',
},
},
{
path: 'backupaccount',
name: 'BackupAccount',
component: () => import('@/views/setting/backup-account/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
activeMenu: 'Setting',
},
},
{
path: 'about',
name: 'About',
component: () => import('@/views/setting/about/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
activeMenu: 'Setting',
},
},
{
path: 'monitor',
name: 'Monitor',
component: () => import('@/views/setting/monitor/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
activeMenu: 'Setting',
},
},
{
path: 'safe',
name: 'Safe',
component: () => import('@/views/setting/safe/index.vue'),
hidden: true,
meta: {
requiresAuth: true,
activeMenu: 'Setting',
},
},
{
path: 'snapshot',
name: 'Snapshot',
hidden: true,
component: () => import('@/views/setting/snapshot/index.vue'),
meta: {
requiresAuth: true,
activeMenu: 'Setting',
},
},
{
path: 'expired',
name: 'Expired',
hidden: true,
component: () => import('@/views/setting/expired.vue'),
meta: {
requiresAuth: true,
activeMenu: 'Expired',
},
},
],
},
],
};

View File

@ -33,7 +33,7 @@
</el-row>
</template>
<template #rightButton>
<el-button @click="sync" type="text" :plain="true">{{ $t('app.syncAppList') }}</el-button>
<el-button @click="sync" link :plain="true">{{ $t('app.syncAppList') }}</el-button>
</template>
<template #main>
<el-row :gutter="5">

View File

@ -11,7 +11,6 @@
import LayoutContent from '@/layout/layout-content.vue';
import RouterButton from '@/components/router-button/index.vue';
import i18n from '@/lang';
const buttons = [
{
label: i18n.global.t('app.all'),

View File

@ -1,7 +1,5 @@
<template>
<div v-loading="loading">
<Submenu activeName="compose" />
<div v-show="isOnDetail">
<ComposeDetial @back="backList" ref="composeDetailRef" />
</div>
@ -12,19 +10,25 @@
</el-button>
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
</el-card>
<el-card v-if="!isOnDetail" style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
<LayoutContent :header="$t('container.compose')">
<LayoutContent
v-loading="loading"
v-if="!isOnDetail"
:title="$t('container.compose')"
:class="{ mask: dockerStatus != 'Running' }"
>
<template #toolbar>
<el-button type="primary" @click="onOpenDialog()">
{{ $t('container.createCompose') }}
</el-button>
</template>
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
:data="data"
@search="search"
>
<template #toolbar>
<el-button icon="Plus" type="primary" @click="onOpenDialog()">
{{ $t('commons.button.create') }}
</el-button>
</template>
<el-table-column
:label="$t('commons.table.name')"
show-overflow-tooltip
@ -57,8 +61,8 @@
fix
/>
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<EditDialog ref="dialogEditRef" />
<CreateDialog @search="search" ref="dialogRef" />
@ -72,7 +76,6 @@ import LayoutContent from '@/layout/layout-content.vue';
import EditDialog from '@/views/container/compose/edit/index.vue';
import CreateDialog from '@/views/container/compose/create/index.vue';
import ComposeDetial from '@/views/container/compose/detail/index.vue';
import Submenu from '@/views/container/index.vue';
import { composeOperator, loadDockerStatus, searchCompose } from '@/api/modules/container';
import i18n from '@/lang';
import { ElMessage } from 'element-plus';

View File

@ -2,7 +2,7 @@
<el-drawer v-model="createVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<template #header>
<div class="card-header">
<span>{{ $t('container.containerCreate') }}</span>
<span>{{ $t('container.createContainer') }}</span>
</div>
</template>
<el-form ref="formRef" v-loading="loading" :model="form" :rules="rules" label-width="80px">

View File

@ -1,6 +1,5 @@
<template>
<div>
<Submenu activeName="container" />
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
@ -8,47 +7,51 @@
</el-button>
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
</el-card>
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
<LayoutContent :header="$t('container.container')">
<LayoutContent
v-loading="loading"
:title="$t('container.container')"
:class="{ mask: dockerStatus != 'Running' }"
>
<template #toolbar>
<el-button type="primary" @click="onCreate()">
{{ $t('container.createContainer') }}
</el-button>
<el-button-group style="margin-left: 10px">
<el-button :disabled="checkStatus('start')" @click="onOperate('start')">
{{ $t('container.start') }}
</el-button>
<el-button :disabled="checkStatus('stop')" @click="onOperate('stop')">
{{ $t('container.stop') }}
</el-button>
<el-button :disabled="checkStatus('restart')" @click="onOperate('restart')">
{{ $t('container.restart') }}
</el-button>
<el-button :disabled="checkStatus('kill')" @click="onOperate('kill')">
{{ $t('container.kill') }}
</el-button>
<el-button :disabled="checkStatus('pause')" @click="onOperate('pause')">
{{ $t('container.pause') }}
</el-button>
<el-button :disabled="checkStatus('unpause')" @click="onOperate('unpause')">
{{ $t('container.unpause') }}
</el-button>
<el-button :disabled="checkStatus('remove')" @click="onOperate('remove')">
{{ $t('container.remove') }}
</el-button>
</el-button-group>
</template>
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
:data="data"
@search="search"
>
<template #toolbar>
<el-button icon="Plus" type="primary" @click="onCreate()">
{{ $t('commons.button.create') }}
</el-button>
<el-button-group style="margin-left: 10px">
<el-button :disabled="checkStatus('start')" @click="onOperate('start')">
{{ $t('container.start') }}
</el-button>
<el-button :disabled="checkStatus('stop')" @click="onOperate('stop')">
{{ $t('container.stop') }}
</el-button>
<el-button :disabled="checkStatus('restart')" @click="onOperate('restart')">
{{ $t('container.restart') }}
</el-button>
<el-button :disabled="checkStatus('kill')" @click="onOperate('kill')">
{{ $t('container.kill') }}
</el-button>
<el-button :disabled="checkStatus('pause')" @click="onOperate('pause')">
{{ $t('container.pause') }}
</el-button>
<el-button :disabled="checkStatus('unpause')" @click="onOperate('unpause')">
{{ $t('container.unpause') }}
</el-button>
<el-button :disabled="checkStatus('remove')" @click="onOperate('remove')">
{{ $t('container.remove') }}
</el-button>
</el-button-group>
</template>
<el-table-column type="selection" fix />
<el-table-column
:label="$t('commons.table.name')"
show-overflow-tooltip
min-width="100"
min-width="80"
prop="name"
fix
>
@ -59,7 +62,7 @@
<el-table-column
:label="$t('container.image')"
show-overflow-tooltip
min-width="100"
min-width="80"
prop="imageName"
/>
<el-table-column :label="$t('commons.table.status')" min-width="50" prop="state" fix>
@ -67,7 +70,7 @@
<Status :key="row.state" :status="row.state"></Status>
</template>
</el-table-column>
<el-table-column :label="$t('container.upTime')" min-width="100" prop="runTime" fix />
<el-table-column :label="$t('container.upTime')" min-width="80" prop="runTime" fix />
<el-table-column
prop="createTime"
:label="$t('commons.table.date')"
@ -75,15 +78,15 @@
show-overflow-tooltip
/>
<fu-table-operations
width="200px"
width="220px"
:ellipsis="10"
:buttons="buttons"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<CodemirrorDialog ref="mydetail" />
@ -105,7 +108,6 @@ import ContainerLogDialog from '@/views/container/container/log/index.vue';
import TerminalDialog from '@/views/container/container/terminal/index.vue';
import CodemirrorDialog from '@/components/codemirror-dialog/codemirror.vue';
import Status from '@/components/status/index.vue';
import Submenu from '@/views/container/index.vue';
import { reactive, onMounted, ref } from 'vue';
import { dateFormat } from '@/utils/util';
import { ContainerOperator, inspect, loadDockerStatus, searchContainer } from '@/api/modules/container';
@ -114,6 +116,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
import i18n from '@/lang';
import router from '@/routers';
const loading = ref();
const data = ref();
const selects = ref<any>([]);
const paginationConfig = reactive({
@ -154,10 +157,16 @@ const search = async () => {
pageSize: paginationConfig.pageSize,
filters: filterItem,
};
await searchContainer(params).then((res) => {
data.value = res.data.items || [];
paginationConfig.total = res.data.total;
});
loading.value = true;
await searchContainer(params)
.then((res) => {
loading.value = false;
data.value = res.data.items || [];
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
};
const dialogCreateRef = ref();
@ -239,12 +248,15 @@ const onOperate = async (operation: string) => {
};
ps.push(ContainerOperator(param));
}
loading.value = true;
Promise.all(ps)
.then(() => {
loading.value = false;
search();
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
search();
});
});

View File

@ -1,6 +1,5 @@
<template>
<div v-loading="loading">
<Submenu activeName="image" />
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
@ -8,20 +7,21 @@
</el-button>
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
</el-card>
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
<LayoutContent :header="$t('container.image')">
<LayoutContent v-loading="loading" :title="$t('container.image')" :class="{ mask: dockerStatus != 'Running' }">
<template #toolbar>
<el-button @click="onOpenPull">
{{ $t('container.imagePull') }}
</el-button>
<el-button @click="onOpenload">
{{ $t('container.importImage') }}
</el-button>
<el-button @click="onOpenBuild">
{{ $t('container.build') }}
</el-button>
</template>
<template #main>
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search">
<template #toolbar>
<el-button @click="onOpenPull">
{{ $t('container.imagePull') }}
</el-button>
<el-button @click="onOpenload">
{{ $t('container.importImage') }}
</el-button>
<el-button @click="onOpenBuild">
{{ $t('container.build') }}
</el-button>
</template>
<el-table-column label="ID" show-overflow-tooltip prop="id" min-width="60" />
<el-table-column :label="$t('container.tag')" prop="tags" min-width="160" fix>
<template #default="{ row }">
@ -33,7 +33,7 @@
<el-table-column :label="$t('container.size')" prop="size" min-width="70" fix />
<el-table-column :label="$t('commons.table.createdAt')" min-width="80" fix>
<template #default="{ row }">
{{ dateFormatSimple(row.createdAt) }}
{{ dateFormatSimple(row.createdAt) }}
</template>
</el-table-column>
<fu-table-operations
@ -43,8 +43,8 @@
:label="$t('commons.table.operate')"
/>
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<Pull ref="dialogPullRef" @search="search" />
<Tag ref="dialogTagRef" @search="search" />
@ -82,7 +82,6 @@
import ComplexTable from '@/components/complex-table/index.vue';
import { reactive, onMounted, ref } from 'vue';
import { dateFormatSimple } from '@/utils/util';
import Submenu from '@/views/container/index.vue';
import { Container } from '@/api/interface/container';
import LayoutContent from '@/layout/layout-content.vue';
import Pull from '@/views/container/image/pull/index.vue';

View File

@ -1,77 +1,49 @@
<template>
<div>
<el-card class="topRouterCard">
<el-radio-group :model-value="props.activeName" @change="handleChange">
<el-radio-button class="topRouterButton" size="default" label="container">
{{ $t('container.container') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="compose">
{{ $t('container.compose') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="image">
{{ $t('container.image') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="network">
{{ $t('container.network') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="volume">
{{ $t('container.volume') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="repo">
{{ $t('container.repo') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="template">
{{ $t('container.composeTemplate') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="setting">
{{ $t('container.setting') }}
</el-radio-button>
</el-radio-group>
</el-card>
<RouterButton :buttons="buttons" />
<LayoutContent>
<router-view></router-view>
</LayoutContent>
</div>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router';
const router = useRouter();
import i18n from '@/lang';
import LayoutContent from '@/layout/layout-content.vue';
import RouterButton from '@/components/router-button/index.vue';
interface MenuProps {
activeName: string;
}
const props = withDefaults(defineProps<MenuProps>(), {
activeName: 'container',
});
const routerTo = (path: string) => {
router.push({ path: path });
};
const handleChange = (val: string) => {
switch (val) {
case 'container':
routerTo('/containers');
break;
case 'compose':
routerTo('/containers/compose');
break;
case 'image':
routerTo('/containers/image');
break;
case 'network':
routerTo('/containers/network');
break;
case 'volume':
routerTo('/containers/volume');
break;
case 'repo':
routerTo('/containers/repo');
break;
case 'template':
routerTo('/containers/template');
break;
case 'setting':
routerTo('/containers/setting');
break;
}
};
const buttons = [
{
label: i18n.global.t('container.container'),
path: '/containers/container',
},
{
label: i18n.global.t('container.compose'),
path: '/containers/compose',
},
{
label: i18n.global.t('container.image'),
path: '/containers/image',
},
{
label: i18n.global.t('container.network'),
path: '/containers/network',
},
{
label: i18n.global.t('container.volume'),
path: '/containers/volume',
},
{
label: i18n.global.t('container.repo'),
path: '/containers/repo',
},
{
label: i18n.global.t('container.composeTemplate'),
path: '/containers/template',
},
{
label: i18n.global.t('container.setting'),
path: '/containers/setting',
},
];
</script>

View File

@ -1,6 +1,5 @@
<template>
<div>
<Submenu activeName="network" />
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
@ -8,22 +7,27 @@
</el-button>
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
</el-card>
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
<LayoutContent :header="$t('container.network')">
<LayoutContent
v-loading="loading"
:title="$t('container.network')"
:class="{ mask: dockerStatus != 'Running' }"
>
<template #toolbar>
<el-button type="primary" @click="onCreate()">
{{ $t('container.createNetwork') }}
</el-button>
<el-button plain :disabled="selects.length === 0" @click="batchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
:data="data"
@search="search"
>
<template #toolbar>
<el-button icon="Plus" type="primary" @click="onCreate()">
{{ $t('commons.button.create') }}
</el-button>
<el-button type="danger" plain :disabled="selects.length === 0" @click="batchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<el-table-column type="selection" :selectable="selectable" fix />
<el-table-column
:label="$t('commons.table.name')"
@ -67,8 +71,8 @@
/>
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" fix />
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<CodemirrorDialog ref="codemirror" />
<CreateDialog @search="search" ref="dialogCreateRef" />
@ -80,7 +84,6 @@ import LayoutContent from '@/layout/layout-content.vue';
import ComplexTable from '@/components/complex-table/index.vue';
import CreateDialog from '@/views/container/network/create/index.vue';
import CodemirrorDialog from '@/components/codemirror-dialog/codemirror.vue';
import Submenu from '@/views/container/index.vue';
import { reactive, onMounted, ref } from 'vue';
import { dateFormat } from '@/utils/util';
import { deleteNetwork, searchNetwork, inspect, loadDockerStatus } from '@/api/modules/container';
@ -89,6 +92,8 @@ import i18n from '@/lang';
import { useDeleteData } from '@/hooks/use-delete-data';
import router from '@/routers';
const loading = ref();
const detailInfo = ref();
const codemirror = ref();
@ -130,13 +135,19 @@ const search = async () => {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
};
await searchNetwork(params).then((res) => {
data.value = res.data.items || [];
for (const item of data.value) {
item.isSystem = isSystem(item.name);
}
paginationConfig.total = res.data.total;
});
loading.value = true;
await searchNetwork(params)
.then((res) => {
loading.value = false;
data.value = res.data.items || [];
for (const item of data.value) {
item.isSystem = isSystem(item.name);
}
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
};
const batchDelete = async (row: Container.NetworkInfo | null) => {

View File

@ -1,6 +1,5 @@
<template>
<div>
<Submenu activeName="repo" />
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
@ -8,22 +7,23 @@
</el-button>
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
</el-card>
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
<LayoutContent :header="$t('container.repo')">
<LayoutContent v-loading="loading" :title="$t('container.repo')" :class="{ mask: dockerStatus != 'Running' }">
<template #toolbar>
<el-button type="primary" @click="onOpenDialog('create')">
{{ $t('container.createRepo') }}
</el-button>
<el-button plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
:data="data"
@search="search"
>
<template #toolbar>
<el-button icon="Plus" type="primary" @click="onOpenDialog('create')">
{{ $t('commons.button.create') }}
</el-button>
<el-button type="danger" plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<el-table-column type="selection" :selectable="selectable" fix />
<el-table-column :label="$t('commons.table.name')" prop="name" min-width="60" />
<el-table-column
@ -46,13 +46,13 @@
</el-table-column>
<el-table-column :label="$t('commons.table.createdAt')" min-width="80" fix>
<template #default="{ row }">
{{ dateFormatSimple(row.createdAt) }}
{{ dateFormatSimple(row.createdAt) }}
</template>
</el-table-column>
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" />
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<OperatorDialog @search="search" ref="dialogRef" />
<DeleteDialog @search="search" ref="dialogDeleteRef" />
</div>
@ -63,7 +63,6 @@ import LayoutContent from '@/layout/layout-content.vue';
import ComplexTable from '@/components/complex-table/index.vue';
import OperatorDialog from '@/views/container/repo/operator/index.vue';
import DeleteDialog from '@/views/container/repo/delete/index.vue';
import Submenu from '@/views/container/index.vue';
import { reactive, onMounted, ref } from 'vue';
import { dateFormatSimple } from '@/utils/util';
import { Container } from '@/api/interface/container';
@ -71,6 +70,7 @@ import { loadDockerStatus, searchImageRepo } from '@/api/modules/container';
import i18n from '@/lang';
import router from '@/routers';
const loading = ref();
const data = ref();
const selects = ref<any>([]);
const paginationConfig = reactive({
@ -96,10 +96,16 @@ const search = async () => {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
};
await searchImageRepo(params).then((res) => {
data.value = res.data.items || [];
paginationConfig.total = res.data.total;
});
loading.value = true;
await searchImageRepo(params)
.then((res) => {
loading.value = false;
data.value = res.data.items || [];
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
};
function selectable(row) {

View File

@ -1,6 +1,5 @@
<template>
<div v-loading="loading">
<Submenu activeName="setting" />
<div>
<div class="app-content" style="margin-top: 20px">
<el-card class="app-card">
<el-row :gutter="20">
@ -49,8 +48,9 @@
</el-row>
</el-card>
</div>
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('container.setting')">
<LayoutContent v-loading="loading" :title="$t('container.setting')" :divider="true">
<template #main>
<el-radio-group v-model="confShowType" @change="changeMode">
<el-radio-button label="base">{{ $t('database.baseConf') }}</el-radio-button>
<el-radio-button label="all">{{ $t('database.allConf') }}</el-radio-button>
@ -114,8 +114,8 @@
{{ $t('commons.button.save') }}
</el-button>
</div>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmitSave"></ConfirmDialog>
</div>
@ -124,7 +124,6 @@
<script lang="ts" setup>
import { ElMessage, FormInstance } from 'element-plus';
import { onMounted, reactive, ref } from 'vue';
import Submenu from '@/views/container/index.vue';
import { Codemirror } from 'vue-codemirror';
import LayoutContent from '@/layout/layout-content.vue';
import { javascript } from '@codemirror/lang-javascript';

View File

@ -1,6 +1,5 @@
<template>
<div>
<Submenu activeName="template" />
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
@ -8,22 +7,27 @@
</el-button>
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
</el-card>
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
<LayoutContent :header="$t('container.composeTemplate')">
<LayoutContent
v-loading="loading"
:title="$t('container.composeTemplate')"
:class="{ mask: dockerStatus != 'Running' }"
>
<template #toolbar>
<el-button type="primary" @click="onOpenDialog('create')">
{{ $t('container.createComposeTemplate') }}
</el-button>
<el-button plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
:data="data"
@search="search"
>
<template #toolbar>
<el-button icon="Plus" type="primary" @click="onOpenDialog('create')">
{{ $t('commons.button.create') }}
</el-button>
<el-button type="danger" plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<el-table-column type="selection" fix />
<el-table-column
:label="$t('commons.table.name')"
@ -39,13 +43,13 @@
<el-table-column :label="$t('container.description')" prop="description" min-width="200" fix />
<el-table-column :label="$t('commons.table.createdAt')" min-width="80" fix>
<template #default="{ row }">
{{ dateFormatSimple(row.createdAt) }}
{{ dateFormatSimple(row.createdAt) }}
</template>
</el-table-column>
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" />
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<el-dialog v-model="detailVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="70%">
<template #header>
@ -81,7 +85,6 @@
<script lang="ts" setup>
import LayoutContent from '@/layout/layout-content.vue';
import ComplexTable from '@/components/complex-table/index.vue';
import Submenu from '@/views/container/index.vue';
import { Codemirror } from 'vue-codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
@ -94,6 +97,7 @@ import { useDeleteData } from '@/hooks/use-delete-data';
import i18n from '@/lang';
import router from '@/routers';
const loading = ref();
const data = ref();
const selects = ref<any>([]);
const detailVisiable = ref(false);
@ -123,10 +127,16 @@ const search = async () => {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
};
await searchComposeTemplate(params).then((res) => {
data.value = res.data.items || [];
paginationConfig.total = res.data.total;
});
loading.value = true;
await searchComposeTemplate(params)
.then((res) => {
loading.value = false;
data.value = res.data.items || [];
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
};
const onOpenDetail = async (row: Container.TemplateInfo) => {

View File

@ -1,6 +1,5 @@
<template>
<div>
<Submenu activeName="volume" />
<el-card width="30%" v-if="dockerStatus != 'Running'" class="mask-prompt">
<span style="font-size: 14px">{{ $t('container.serviceUnavailable') }}</span>
<el-button type="primary" link style="font-size: 14px; margin-bottom: 5px" @click="goSetting">
@ -8,22 +7,23 @@
</el-button>
<span style="font-size: 14px">{{ $t('container.startIn') }}</span>
</el-card>
<el-card style="margin-top: 20px" :class="{ mask: dockerStatus != 'Running' }">
<LayoutContent :header="$t('container.volume')">
<LayoutContent v-loading="loading" :title="$t('container.volume')" :class="{ mask: dockerStatus != 'Running' }">
<template #toolbar>
<el-button type="primary" @click="onCreate()">
{{ $t('container.createVolume') }}
</el-button>
<el-button plain :disabled="selects.length === 0" @click="batchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
:data="data"
@search="search"
>
<template #toolbar>
<el-button icon="Plus" type="primary" @click="onCreate()">
{{ $t('commons.button.create') }}
</el-button>
<el-button type="danger" plain :disabled="selects.length === 0" @click="batchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<el-table-column type="selection" fix />
<el-table-column
:label="$t('commons.table.name')"
@ -56,8 +56,8 @@
/>
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" fix />
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<CodemirrorDialog ref="codemirror" />
<CreateDialog @search="search" ref="dialogCreateRef" />
@ -68,7 +68,6 @@
import LayoutContent from '@/layout/layout-content.vue';
import ComplexTable from '@/components/complex-table/index.vue';
import CreateDialog from '@/views/container/volume/create/index.vue';
import Submenu from '@/views/container/index.vue';
import CodemirrorDialog from '@/components/codemirror-dialog/codemirror.vue';
import { reactive, onMounted, ref } from 'vue';
import { dateFormat } from '@/utils/util';
@ -78,6 +77,7 @@ import i18n from '@/lang';
import { useDeleteData } from '@/hooks/use-delete-data';
import router from '@/routers';
const loading = ref();
const detailInfo = ref();
const codemirror = ref();
@ -115,10 +115,16 @@ const search = async () => {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
};
await searchVolume(params).then((res) => {
data.value = res.data.items || [];
paginationConfig.total = res.data.total;
});
loading.value = true;
await searchVolume(params)
.then((res) => {
loading.value = false;
data.value = res.data.items || [];
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
};
const onInspect = async (id: string) => {

View File

@ -1,28 +1,29 @@
<template>
<div>
<el-card class="topRouterCard">
<el-radio-group v-model="active">
<el-radio-button class="topRouterButton" size="default" label="cronjob">
{{ $t('cronjob.cronTask') }}
</el-radio-button>
</el-radio-group>
</el-card>
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('cronjob.cronTask')">
<RouterButton
:buttons="[
{
label: i18n.global.t('cronjob.cronTask'),
path: '/cronjobs',
},
]"
/>
<LayoutContent v-loading="loading" :title="$t('cronjob.cronTask')">
<template #toolbar>
<el-button type="primary" @click="onOpenDialog('create')">
{{ $t('commons.button.create') }}{{ $t('cronjob.cronTask') }}
</el-button>
<el-button plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
@search="search"
:data="data"
>
<template #toolbar>
<el-button type="primary" icon="Plus" @click="onOpenDialog('create')">
{{ $t('commons.button.create') }}
</el-button>
<el-button type="danger" plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
<el-table-column type="selection" fix />
<el-table-column :label="$t('cronjob.taskName')" prop="name" />
<el-table-column :label="$t('commons.table.status')" prop="status">
@ -87,8 +88,8 @@
fix
/>
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<OperatrDialog @search="search" ref="dialogRef" />
<RecordDialog ref="dialogRecordRef" />
@ -109,9 +110,9 @@ import { Cronjob } from '@/api/interface/cronjob';
import { useDeleteData } from '@/hooks/use-delete-data';
import { ElMessage, ElMessageBox } from 'element-plus';
const loading = ref();
const selects = ref<any>([]);
const active = ref('cronjob');
const data = ref();
const paginationConfig = reactive({
currentPage: 1,
@ -134,14 +135,21 @@ const search = async () => {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
};
const res = await getCronjobPage(params);
data.value = res.data.items || [];
for (const item of data.value) {
if (item.targetDir !== '-') {
item.targetDir = loadBackupName(item.targetDir);
}
}
paginationConfig.total = res.data.total;
loading.value = true;
await getCronjobPage(params)
.then((res) => {
loading.value = false;
data.value = res.data.items || [];
for (const item of data.value) {
if (item.targetDir !== '-') {
item.targetDir = loadBackupName(item.targetDir);
}
}
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
};
const dialogRecordRef = ref<DialogExpose>();

View File

@ -1,36 +1,24 @@
<template>
<div>
<el-card class="topRouterCard">
<el-radio-group :model-value="props.activeName" @change="handleChange">
<el-radio-button class="topRouterButton" size="default" label="mysql">Mysql</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="redis">Redis</el-radio-button>
</el-radio-group>
</el-card>
<RouterButton :buttons="buttons" />
<LayoutContent>
<router-view></router-view>
</LayoutContent>
</div>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router';
const router = useRouter();
interface MenuProps {
activeName: string;
}
const props = withDefaults(defineProps<MenuProps>(), {
activeName: 'mysql',
});
import LayoutContent from '@/layout/layout-content.vue';
import RouterButton from '@/components/router-button/index.vue';
const routerTo = (path: string) => {
router.push({ path: path });
};
const handleChange = (val: string) => {
switch (val) {
case 'mysql':
routerTo('/databases');
break;
case 'redis':
routerTo('/databases/redis');
break;
}
};
const buttons = [
{
label: 'Mysql',
path: '/databases/mysql',
},
{
label: 'Redis',
path: '/databases/redis',
},
];
</script>

View File

@ -1,105 +1,97 @@
<template>
<div v-loading="loading">
<Submenu activeName="mysql" />
<AppStatus
:app-key="'mysql'"
style="margin-top: 20px"
v-model:loading="loading"
@setting="onSetting"
@is-exist="checkExist"
/>
<Setting ref="settingRef" style="margin-top: 20px" />
<LayoutContent :title="'Mysql ' + $t('menu.database')">
<template #app>
<AppStatus
:app-key="'mysql'"
style="margin-top: 20px"
@setting="onSetting"
@is-exist="checkExist"
></AppStatus>
</template>
<el-card
width="30%"
v-if="mysqlStatus != 'Running' && !isOnSetting && mysqlIsExist && !loading"
class="mask-prompt"
>
<span style="font-size: 14px">{{ $t('commons.service.serviceNotStarted', ['Mysql']) }}</span>
</el-card>
<div style="margin-top: 20px" v-if="mysqlIsExist && !isOnSetting">
<el-button type="primary" @click="onOpenDialog()">
{{ $t('database.create') }}
</el-button>
<el-button @click="onChangeRootPassword" type="primary" plain>
{{ $t('database.rootPassword') }}
</el-button>
<el-button @click="onChangeAccess" type="primary" plain>
{{ $t('database.remoteAccess') }}
</el-button>
<el-button @click="goDashboard" type="primary" plain>phpMyAdmin</el-button>
</div>
<div v-if="mysqlIsExist" :class="{ mask: mysqlStatus != 'Running' }">
<el-card v-if="!isOnSetting" style="margin-top: 10px">
<LayoutContent :header="'Mysql ' + $t('menu.database')">
<ComplexTable :pagination-config="paginationConfig" @search="search" :data="data">
<el-table-column :label="$t('commons.table.name')" prop="name" />
<el-table-column :label="$t('commons.login.username')" prop="username" />
<el-table-column :label="$t('commons.login.password')" prop="password">
<template #default="{ row }">
<div>
<span style="float: left; line-height: 25px" v-if="!row.showPassword">
***********
</span>
<div style="cursor: pointer; float: left" v-if="!row.showPassword">
<el-icon
style="margin-left: 5px; margin-top: 3px"
@click="row.showPassword = true"
:size="16"
>
<View />
</el-icon>
</div>
<span style="float: left" v-if="row.showPassword">{{ row.password }}</span>
<div style="cursor: pointer; float: left" v-if="row.showPassword">
<el-icon
style="margin-left: 5px; margin-top: 3px"
@click="row.showPassword = false"
:size="16"
>
<Hide />
</el-icon>
</div>
<div style="cursor: pointer; float: left">
<el-icon
style="margin-left: 5px; margin-top: 3px"
:size="16"
@click="onCopyPassword(row)"
>
<DocumentCopy />
</el-icon>
</div>
<template #toolbar v-if="mysqlIsExist && !isOnSetting">
<el-button type="primary" @click="onOpenDialog()">
{{ $t('database.create') }}
</el-button>
<el-button @click="onChangeRootPassword" type="primary" plain>
{{ $t('database.rootPassword') }}
</el-button>
<el-button @click="onChangeAccess" type="primary" plain>
{{ $t('database.remoteAccess') }}
</el-button>
<el-button @click="goDashboard" type="primary" plain>phpMyAdmin</el-button>
</template>
<template #main v-if="mysqlIsExist && !isOnSetting">
<ComplexTable :pagination-config="paginationConfig" @search="search" :data="data">
<el-table-column :label="$t('commons.table.name')" prop="name" />
<el-table-column :label="$t('commons.login.username')" prop="username" />
<el-table-column :label="$t('commons.login.password')" prop="password">
<template #default="{ row }">
<div>
<span style="float: left; line-height: 25px" v-if="!row.showPassword">***********</span>
<div style="cursor: pointer; float: left" v-if="!row.showPassword">
<el-icon
style="margin-left: 5px; margin-top: 3px"
@click="row.showPassword = true"
:size="16"
>
<View />
</el-icon>
</div>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.description')" prop="description">
<template #default="{ row }">
<fu-read-write-switch
:data="row.description"
v-model="row.edit"
@change="onChange(row)"
>
<el-input v-model="row.description" @blur="row.edit = false" />
</fu-read-write-switch>
</template>
</el-table-column>
<el-table-column
prop="createdAt"
:label="$t('commons.table.date')"
:formatter="dateFormat"
show-overflow-tooltip
/>
<fu-table-operations
width="300px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
</LayoutContent>
</el-card>
</div>
<span style="float: left" v-if="row.showPassword">{{ row.password }}</span>
<div style="cursor: pointer; float: left" v-if="row.showPassword">
<el-icon
style="margin-left: 5px; margin-top: 3px"
@click="row.showPassword = false"
:size="16"
>
<Hide />
</el-icon>
</div>
<div style="cursor: pointer; float: left">
<el-icon
style="margin-left: 5px; margin-top: 3px"
:size="16"
@click="onCopyPassword(row)"
>
<DocumentCopy />
</el-icon>
</div>
</div>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.description')" prop="description">
<template #default="{ row }">
<fu-read-write-switch :data="row.description" v-model="row.edit" @change="onChange(row)">
<el-input v-model="row.description" @blur="row.edit = false" />
</fu-read-write-switch>
</template>
</el-table-column>
<el-table-column
prop="createdAt"
:label="$t('commons.table.date')"
:formatter="dateFormat"
show-overflow-tooltip
/>
<fu-table-operations
width="300px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
<el-card
width="30%"
v-if="mysqlStatus != 'Running' && !isOnSetting && mysqlIsExist && !loading"
class="mask-prompt"
>
<span style="font-size: 14px">{{ $t('commons.service.serviceNotStarted', ['Mysql']) }}</span>
</el-card>
</template>
</LayoutContent>
<Setting ref="settingRef" style="margin-top: 20px" />
<el-dialog v-model="changeVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
<template #header>
<div class="card-header">
@ -195,7 +187,6 @@ import UploadDialog from '@/views/database/mysql/upload/index.vue';
import AppResources from '@/views/database/mysql/check/index.vue';
import Setting from '@/views/database/mysql/setting/index.vue';
import AppStatus from '@/components/app-status/index.vue';
import Submenu from '@/views/database/index.vue';
import { dateFormat } from '@/utils/util';
import { reactive, ref } from 'vue';
import {

View File

@ -1,34 +1,26 @@
<template>
<div v-loading="loading">
<Submenu activeName="redis" />
<AppStatus
:app-key="'redis'"
style="margin-top: 20px"
@before="onBefore"
@setting="onSetting"
@is-exist="checkExist"
v-model:loading="loading"
></AppStatus>
<el-card
width="30%"
v-if="redisStatus != 'Running' && !isOnSetting && redisIsExist && !loading"
class="mask-prompt"
>
<span style="font-size: 14px">{{ $t('commons.service.serviceNotStarted', ['Redis']) }}</span>
</el-card>
<div v-show="redisIsExist" :class="{ mask: redisStatus != 'Running' }">
<el-button style="margin-top: 20px" type="primary" plain @click="goDashboard" icon="Position">
Redis-Commander
</el-button>
<el-button style="margin-top: 20px" type="primary" plain @click="onChangePassword">
{{ $t('database.changePassword') }}
</el-button>
<Terminal :key="isRefresh" style="margin-top: 10px" ref="terminalRef" />
</div>
<LayoutContent v-show="!isOnSetting && redisIsExist" :title="'Redis ' + $t('menu.database')">
<template #toolbar v-if="!isOnSetting && redisIsExist">
<el-button type="primary" plain @click="goDashboard" icon="Position">Redis-Commander</el-button>
<el-button plain @click="onChangePassword">
{{ $t('database.changePassword') }}
</el-button>
</template>
<template #main>
<Terminal :key="isRefresh" style="margin-top: 10px" ref="terminalRef" />
</template>
</LayoutContent>
<Setting ref="settingRef" style="margin-top: 10px" />
<Setting ref="settingRef" style="margin-top: 30px" />
<Password ref="passwordRef" @check-exist="initTerminal" @close-terminal="closeTerminal(true)" />
<el-dialog
v-model="commandVisiable"
@ -52,7 +44,7 @@
</template>
<script lang="ts" setup>
import Submenu from '@/views/database/index.vue';
import LayoutContent from '@/layout/layout-content.vue';
import Setting from '@/views/database/redis/setting/index.vue';
import Password from '@/views/database/redis/password/index.vue';
import Terminal from '@/views/database/redis/terminal/index.vue';

View File

@ -1,8 +1,6 @@
<template>
<div v-show="terminalShow" style="height: 100%">
<el-card>
<div style="height: calc(100vh - 230px)" :id="'terminal-exec'"></div>
</el-card>
<div style="height: calc(100vh - 230px)" :id="'terminal-exec'"></div>
</div>
</template>

View File

@ -1,12 +1,13 @@
<template>
<div>
<el-card class="topRouterCard">
<el-radio-group v-model="active">
<el-radio-button class="topRouterButton" size="default" label="home">
{{ $t('home.overview') }}
</el-radio-button>
</el-radio-group>
</el-card>
<RouterButton
:buttons="[
{
label: i18n.global.t('menu.monitor'),
path: '/home/index',
},
]"
/>
<el-row :gutter="20" style="margin-top: 20px">
<el-col :span="18">
<CardWithHeader :header="$t('home.overview')">
@ -163,7 +164,6 @@ import { loadBaseInfo, loadCurrentInfo } from '@/api/modules/dashboard';
import { getIOOptions, getNetworkOptions } from '@/api/modules/monitor';
const router = useRouter();
const active = ref('home');
const statuRef = ref();
const appRef = ref();

View File

@ -1,12 +1,13 @@
<template>
<div>
<el-card class="topRouterCard">
<el-radio-group v-model="active">
<el-radio-button class="topRouterButton" size="default" label="monitor">
{{ $t('menu.monitor') }}
</el-radio-button>
</el-radio-group>
</el-card>
<RouterButton
:buttons="[
{
label: i18n.global.t('menu.monitor'),
path: '/hosts/monitor',
},
]"
/>
<el-row :gutter="20" style="margin-top: 20px">
<el-col :span="24">
<el-card style="overflow: inherit">
@ -124,7 +125,6 @@ import { Monitor } from '@/api/interface/monitor';
import { dateFormatWithoutYear } from '@/utils/util';
import i18n from '@/lang';
const active = ref('monitor');
const zoomStart = ref();
const monitorBase = ref();
const timeRangeLoad = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);

View File

@ -1,47 +1,29 @@
<template>
<div>
<el-card class="topRouterCard">
<el-radio-group :model-value="props.activeName" @change="handleChange">
<el-radio-button class="topRouterButton" size="default" label="operation">
{{ $t('logs.operation') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="login">
{{ $t('logs.login') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="system">
{{ $t('logs.system') }}
</el-radio-button>
</el-radio-group>
</el-card>
<RouterButton :buttons="buttons" />
<LayoutContent>
<router-view></router-view>
</LayoutContent>
</div>
</template>
<script lang="ts" setup>
import { useRouter } from 'vue-router';
const router = useRouter();
import i18n from '@/lang';
import LayoutContent from '@/layout/layout-content.vue';
import RouterButton from '@/components/router-button/index.vue';
interface MenuProps {
activeName: string;
}
const props = withDefaults(defineProps<MenuProps>(), {
activeName: 'operation',
});
const routerTo = (path: string) => {
router.push({ path: path });
};
const handleChange = (val: string) => {
switch (val) {
case 'operation':
routerTo('/logs');
break;
case 'login':
routerTo('/logs/login');
break;
case 'system':
routerTo('/logs/system');
break;
}
};
const buttons = [
{
label: i18n.global.t('logs.operation'),
path: '/logs/operation',
},
{
label: i18n.global.t('logs.login'),
path: '/logs/login',
},
{
label: i18n.global.t('logs.system'),
path: '/logs/system',
},
];
</script>

View File

@ -1,15 +1,13 @@
<template>
<div>
<Submenu activeName="login" />
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('logs.login')">
<LayoutContent v-loading="loading" :title="$t('logs.login')">
<template #toolbar>
<el-button type="primary" plain @click="onClean()">
{{ $t('logs.deleteLogs') }}
</el-button>
</template>
<template #main>
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search">
<template #toolbar>
<el-button type="primary" @click="onClean()">
{{ $t('logs.deleteLogs') }}
</el-button>
</template>
<el-table-column min-width="40" :label="$t('logs.loginIP')" prop="ip" />
<el-table-column min-width="40" :label="$t('logs.loginAddress')" prop="address" />
<el-table-column :label="$t('logs.loginAgent')" show-overflow-tooltip prop="agent" />
@ -32,8 +30,8 @@
show-overflow-tooltip
/>
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmitClean"></ConfirmDialog>
</div>
</template>
@ -44,11 +42,11 @@ import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import LayoutContent from '@/layout/layout-content.vue';
import { dateFormat } from '@/utils/util';
import { cleanLogs, getLoginLogs } from '@/api/modules/log';
import Submenu from '@/views/log/index.vue';
import { onMounted, reactive, ref } from '@vue/runtime-core';
import i18n from '@/lang';
import { ElMessage } from 'element-plus';
const loading = ref();
const data = ref();
const confirmDialogRef = ref();
const paginationConfig = reactive({
@ -62,9 +60,16 @@ const search = async () => {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
};
const res = await getLoginLogs(params);
data.value = res.data.items;
paginationConfig.total = res.data.total;
loading.value = true;
await getLoginLogs(params)
.then((res) => {
loading.value = false;
data.value = res.data.items;
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
};
const onClean = async () => {

View File

@ -1,15 +1,13 @@
<template>
<div>
<Submenu activeName="operation" />
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('logs.operation')">
<LayoutContent v-loading="loading" :title="$t('logs.operation')">
<template #toolbar>
<el-button type="primary" plain @click="onClean()">
{{ $t('logs.deleteLogs') }}
</el-button>
</template>
<template #main>
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search">
<template #toolbar>
<el-button type="primary" @click="onClean()">
{{ $t('logs.deleteLogs') }}
</el-button>
</template>
<el-table-column :label="$t('logs.resource')" prop="group" fix>
<template #default="{ row }">
{{ $t('logs.detail.' + row.group) }}
@ -43,8 +41,8 @@
show-overflow-tooltip
/>
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmitClean"></ConfirmDialog>
</div>
@ -56,11 +54,11 @@ import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { dateFormat } from '@/utils/util';
import LayoutContent from '@/layout/layout-content.vue';
import { cleanLogs, getOperationLogs } from '@/api/modules/log';
import Submenu from '@/views/log/index.vue';
import { onMounted, reactive, ref } from '@vue/runtime-core';
import i18n from '@/lang';
import { ElMessage } from 'element-plus';
const loading = ref();
const data = ref();
const confirmDialogRef = ref();
const paginationConfig = reactive({
@ -74,9 +72,16 @@ const search = async () => {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
};
const res = await getOperationLogs(params);
data.value = res.data.items;
paginationConfig.total = res.data.total;
loading.value = true;
await getOperationLogs(params)
.then((res) => {
loading.value = false;
data.value = res.data.items;
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
};
const onClean = async () => {

View File

@ -1,8 +1,7 @@
<template>
<div>
<Submenu activeName="system" />
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('logs.system')">
<LayoutContent v-loading="loading" :title="$t('logs.system')">
<template #main>
<codemirror
:autofocus="true"
placeholder="None data"
@ -18,8 +17,8 @@
v-model="logs"
:readOnly="true"
/>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
</div>
</template>
@ -29,10 +28,10 @@ import LayoutContent from '@/layout/layout-content.vue';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
import { nextTick, onMounted, ref, shallowRef } from 'vue';
import Submenu from '@/views/log/index.vue';
import { LoadFile } from '@/api/modules/files';
import { loadBaseDir } from '@/api/modules/setting';
const loading = ref();
const extensions = [javascript(), oneDark];
const logs = ref();
const view = shallowRef();
@ -43,15 +42,21 @@ const handleReady = (payload) => {
const loadSystemlogs = async () => {
const pathRes = await loadBaseDir();
let logPath = pathRes.data.replaceAll('/data', '/log');
const res = await LoadFile({ path: `${logPath}/1Panel.log` });
logs.value = res.data;
nextTick(() => {
const state = view.value.state;
view.value.dispatch({
selection: { anchor: state.doc.length, head: state.doc.length },
scrollIntoView: true,
await LoadFile({ path: `${logPath}/1Panel.log` })
.then((res) => {
loading.value = false;
logs.value = res.data;
nextTick(() => {
const state = view.value.state;
view.value.dispatch({
selection: { anchor: state.doc.length, head: state.doc.length },
scrollIntoView: true,
});
});
})
.catch(() => {
loading.value = false;
});
});
};
onMounted(() => {

View File

@ -1,9 +1,8 @@
<template>
<div v-loading="loading">
<Submenu activeName="about" />
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('setting.about')">
<div style="text-align: center">
<div>
<LayoutContent v-loading="loading" :title="$t('setting.about')" :divider="true">
<template #main>
<div style="text-align: center; margin-top: 20px">
<div style="justify-self: center">
<img style="width: 80px" src="@/assets/images/ko_image.png" />
</div>
@ -34,8 +33,8 @@
</el-link>
</div>
</div>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<el-drawer :key="refresh" v-model="drawerShow" size="50%">
<el-form label-width="120px">
<el-form-item :label="$t('setting.newVersion')">
@ -58,7 +57,6 @@
<script lang="ts" setup>
import LayoutContent from '@/layout/layout-content.vue';
import { getSettingInfo, loadUpgradeInfoByOSS, upgrade } from '@/api/modules/setting';
import Submenu from '@/views/setting/index.vue';
import { onMounted, ref } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

View File

@ -1,35 +1,35 @@
<template>
<div>
<Submenu activeName="backupaccount" />
<el-form label-position="left" label-width="130px" :v-key="reflash">
<LayoutContent header="Local" style="margin-top: 20px">
<el-row :gutter="20">
<el-col :span="24">
<el-card>
<template #header>
<svg-icon style="font-size: 7px" iconName="p-file-folder"></svg-icon>
<span style="font-size: 16px; font-weight: 500">
&nbsp;{{ $t('setting.serverDisk') }}
</span>
<div style="float: right">
<el-button round @click="onOpenDialog('edit', 'local', localData)">
{{ $t('commons.button.edit') }}
</el-button>
</div>
</template>
<el-form-item :label="$t('setting.currentPath')">
{{ localData.varsJson['dir'] }}
</el-form-item>
<el-form-item :label="$t('commons.table.createdAt')">
{{ dateFormat(0, 0, localData.createdAt) }}
</el-form-item>
</el-card>
</el-col>
</el-row>
</LayoutContent>
<LayoutContent :title="$t('setting.backup')" :divider="true">
<template #main>
<el-form label-position="left" label-width="130px" :v-key="reflash">
<el-row :gutter="20">
<el-col :span="24">
<el-card>
<template #header>
<svg-icon style="font-size: 7px" iconName="p-file-folder"></svg-icon>
<span style="font-size: 16px; font-weight: 500">
&nbsp;{{ $t('setting.serverDisk') }}
</span>
<div style="float: right">
<el-button round @click="onOpenDialog('edit', 'local', localData)">
{{ $t('commons.button.edit') }}
</el-button>
</div>
</template>
<el-form-item :label="$t('setting.currentPath')">
{{ localData.varsJson['dir'] }}
</el-form-item>
<el-form-item :label="$t('commons.table.createdAt')">
{{ dateFormat(0, 0, localData.createdAt) }}
</el-form-item>
</el-card>
</el-col>
</el-row>
</el-form>
<LayoutContent :header="$t('setting.thirdParty')" style="margin-top: 20px">
<el-row :gutter="20">
<div style="margin-top: 20px"><span style="font-size: 14px; font-weight: 500">第三方账号</span></div>
<el-row :gutter="20" style="margin-top: 5px">
<el-col :span="12">
<el-card style="height: 265px">
<template #header>
@ -208,8 +208,8 @@
</el-card>
</el-col>
</el-row>
</LayoutContent>
</el-form>
</template>
</LayoutContent>
<DialogOperate ref="dialogRef" @search="search" />
</div>
</template>
@ -219,7 +219,6 @@ import { onMounted, ref } from 'vue';
import LayoutContent from '@/layout/layout-content.vue';
import { getBackupList, deleteBackup } from '@/api/modules/backup';
import DialogOperate from '@/views/setting/backup-account/operate/index.vue';
import Submenu from '@/views/setting/index.vue';
import { Backup } from '@/api/interface/backup';
import { ElForm } from 'element-plus';
import { useDeleteData } from '@/hooks/use-delete-data';

View File

@ -72,6 +72,7 @@ let settingForm = reactive<Setting.SettingInfo>({
language: '',
serverPort: 8888,
securityEntrance: '',
systemVersion: '',
expirationDays: 0,
expirationTime: '',
complexityVerification: 'enable',

View File

@ -1,64 +1,41 @@
<template>
<div>
<el-card class="topRouterCard">
<el-radio-group :model-value="props.activeName" @change="handleChange">
<el-radio-button class="topRouterButton" size="default" label="panel">
{{ $t('setting.panel') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="safe">
{{ $t('setting.safe') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="backupaccount">
{{ $t('setting.backupAccount') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="snapshot">
{{ $t('setting.snapshot') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="monitor">
{{ $t('menu.monitor') }}
</el-radio-button>
<el-radio-button class="topRouterButton" size="default" label="about">
{{ $t('setting.about') }}
</el-radio-button>
</el-radio-group>
</el-card>
<RouterButton :buttons="buttons" />
<LayoutContent>
<router-view></router-view>
</LayoutContent>
</div>
</template>
<script lang="ts" setup>
import router from '@/routers';
import i18n from '@/lang';
import LayoutContent from '@/layout/layout-content.vue';
import RouterButton from '@/components/router-button/index.vue';
interface MenuProps {
activeName: string;
}
const props = withDefaults(defineProps<MenuProps>(), {
activeName: 'all',
});
const routerTo = (path: string) => {
router.push({ path: path });
};
const handleChange = (val: string) => {
switch (val) {
case 'panel':
routerTo('/setting');
break;
case 'safe':
routerTo('/setting/safe');
break;
case 'backupaccount':
routerTo('/setting/backupaccount');
break;
case 'monitor':
routerTo('/setting/monitor');
break;
case 'about':
routerTo('/setting/about');
break;
case 'snapshot':
routerTo('/setting/snapshot');
break;
}
};
const buttons = [
{
label: i18n.global.t('setting.panel'),
path: '/settings/panel',
},
{
label: i18n.global.t('setting.safe'),
path: '/settings/safe',
},
{
label: i18n.global.t('setting.backupAccount'),
path: '/settings/backupaccount',
},
{
label: i18n.global.t('setting.monitor'),
path: '/settings/monitor',
},
{
label: i18n.global.t('setting.snapshot'),
path: '/settings/snapshot',
},
{
label: i18n.global.t('setting.about'),
path: '/settings/about',
},
];
</script>

View File

@ -1,9 +1,8 @@
<template>
<div>
<Submenu activeName="monitor" />
<el-form :model="form" ref="panelFormRef" label-position="left" label-width="160px">
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('menu.monitor')">
<LayoutContent v-loading="loading" :title="$t('setting.monitor')" :divider="true">
<template #main>
<el-form :model="form" ref="panelFormRef" label-position="left" label-width="160px">
<el-row>
<el-col :span="1"><br /></el-col>
<el-col :span="10">
@ -40,9 +39,9 @@
</el-form-item>
</el-col>
</el-row>
</LayoutContent>
</el-card>
</el-form>
</el-form>
</template>
</LayoutContent>
</div>
</template>
@ -52,10 +51,10 @@ import { ElMessage, FormInstance } from 'element-plus';
import LayoutContent from '@/layout/layout-content.vue';
import { cleanMonitors, getSettingInfo, updateSetting } from '@/api/modules/setting';
import { useDeleteData } from '@/hooks/use-delete-data';
import Submenu from '@/views/setting/index.vue';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
const loading = ref();
const form = reactive({
monitorStatus: 'disable',
monitorStoreDays: 30,
@ -86,8 +85,15 @@ const onSave = async (formEl: FormInstance | undefined, key: string, val: any) =
key: key,
value: val + '',
};
await updateSetting(param);
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
loading.value = true;
await updateSetting(param)
.then(() => {
loading.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
});
};
function callback(error: any) {
if (error) {

View File

@ -1,9 +1,8 @@
<template>
<div>
<Submenu activeName="panel" />
<el-form :model="form" ref="panelFormRef" label-position="left" v-loading="loading" label-width="160px">
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('setting.panel')">
<LayoutContent v-loading="loading" :title="$t('setting.panel')" :divider="true">
<template #main>
<el-form :model="form" ref="panelFormRef" label-position="left" v-loading="loading" label-width="160px">
<el-row>
<el-col :span="1"><br /></el-col>
<el-col :span="10">
@ -112,9 +111,9 @@
</el-form-item>
</el-col>
</el-row>
</LayoutContent>
</el-card>
</el-form>
</el-form>
</template>
</LayoutContent>
</div>
</template>
@ -123,7 +122,6 @@ import { ref, reactive, onMounted, computed } from 'vue';
import { ElMessage, ElForm } from 'element-plus';
import LayoutContent from '@/layout/layout-content.vue';
import { syncTime, getSettingInfo, updateSetting } from '@/api/modules/setting';
import Submenu from '@/views/setting/index.vue';
import { Rules } from '@/global/form-rules';
import { GlobalStore } from '@/store';
import { useI18n } from 'vue-i18n';

View File

@ -1,9 +1,8 @@
<template>
<div>
<Submenu activeName="safe" />
<el-form :model="form" ref="panelFormRef" v-loading="loading" label-position="left" label-width="160px">
<el-card style="margin-top: 20px">
<LayoutContent :header="$t('setting.safe')">
<LayoutContent v-loading="loading" :title="$t('setting.safe')" :divider="true">
<template #main>
<el-form :model="form" ref="panelFormRef" v-loading="loading" label-position="left" label-width="160px">
<el-row>
<el-col :span="1"><br /></el-col>
<el-col :span="10">
@ -102,9 +101,9 @@
</el-form-item>
</el-col>
</el-row>
</LayoutContent>
</el-card>
</el-form>
</el-form>
</template>
</LayoutContent>
<el-dialog
v-model="timeoutVisiable"
:destroy-on-close="true"
@ -180,7 +179,6 @@
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue';
import { ElMessage, ElForm } from 'element-plus';
import Submenu from '@/views/setting/index.vue';
import { Setting } from '@/api/interface/setting';
import LayoutContent from '@/layout/layout-content.vue';
import { updatePassword, updateSetting, getMFA, bindMFA, getSettingInfo } from '@/api/modules/setting';

View File

@ -1,12 +1,12 @@
<template>
<div v-loading="loading">
<Submenu activeName="snapshot" />
<el-card v-if="!isRecordShow" style="margin-top: 20px">
<LayoutContent :header="$t('setting.snapshot')">
<div>
<LayoutContent v-loading="loading" v-if="!isRecordShow" :title="$t('setting.snapshot')" :divider="true">
<template #main>
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
:data="data"
style="margin-top: 20px"
@search="search"
>
<template #toolbar>
@ -65,8 +65,8 @@
fix
/>
</ComplexTable>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<RecoverStatus ref="recoverStatusRef"></RecoverStatus>
<el-drawer v-model="dialogVisiable" :title="$t('setting.createSnapshot')" size="50%">
<el-form v-loading="loading" ref="snapRef" label-width="100px" :model="snapInfo" :rules="rules">
@ -109,7 +109,6 @@ import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { ElMessage } from 'element-plus';
import { Setting } from '@/api/interface/setting';
import Submenu from '@/views/setting/index.vue';
import LayoutContent from '@/layout/layout-content.vue';
import RecoverStatus from '@/views/setting/snapshot/status/index.vue';
import { getBackupList } from '@/api/modules/backup';