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

View File

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

View File

@ -4,94 +4,103 @@ const containerRouter = {
sort: 5, sort: 5,
path: '/containers', path: '/containers',
component: Layout, component: Layout,
redirect: '/containers', redirect: '/containers/container',
meta: { meta: {
icon: 'p-docker', icon: 'p-docker',
title: 'menu.container', title: 'menu.container',
}, },
children: [ children: [
{ {
path: '', path: '/containers',
name: 'Container', name: 'Containers',
component: () => import('@/views/container/container/index.vue'), redirect: '/containers/container',
props: true, component: () => import('@/views/container/index.vue'),
hidden: true, meta: {},
meta: { children: [
activeMenu: '/containers', {
}, path: 'container',
}, name: 'Container',
{ component: () => import('@/views/container/container/index.vue'),
path: 'composeDetail/:filters?', props: true,
name: 'ComposeDetail', hidden: true,
component: () => import('@/views/container/compose/detail/index.vue'), meta: {
props: true, activeMenu: '/containers',
hidden: true, },
meta: { },
activeMenu: '/containers', {
}, path: 'composeDetail/:filters?',
}, name: 'ComposeDetail',
{ component: () => import('@/views/container/compose/detail/index.vue'),
path: 'image', props: true,
name: 'Image', hidden: true,
component: () => import('@/views/container/image/index.vue'), meta: {
hidden: true, activeMenu: '/containers',
meta: { },
activeMenu: '/containers', },
}, {
}, path: 'image',
{ name: 'Image',
path: 'network', component: () => import('@/views/container/image/index.vue'),
name: 'Network', hidden: true,
component: () => import('@/views/container/network/index.vue'), meta: {
hidden: true, activeMenu: '/containers',
meta: { },
activeMenu: '/containers', },
}, {
}, path: 'network',
{ name: 'Network',
path: 'volume', component: () => import('@/views/container/network/index.vue'),
name: 'Volume', hidden: true,
component: () => import('@/views/container/volume/index.vue'), meta: {
hidden: true, activeMenu: '/containers',
meta: { },
activeMenu: '/containers', },
}, {
}, path: 'volume',
{ name: 'Volume',
path: 'repo', component: () => import('@/views/container/volume/index.vue'),
name: 'Repo', hidden: true,
component: () => import('@/views/container/repo/index.vue'), meta: {
hidden: true, activeMenu: '/containers',
meta: { },
activeMenu: '/containers', },
}, {
}, path: 'repo',
{ name: 'Repo',
path: 'compose', component: () => import('@/views/container/repo/index.vue'),
name: 'Compose', hidden: true,
component: () => import('@/views/container/compose/index.vue'), meta: {
hidden: true, activeMenu: '/containers',
meta: { },
activeMenu: '/containers', },
}, {
}, path: 'compose',
{ name: 'Compose',
path: 'template', component: () => import('@/views/container/compose/index.vue'),
name: 'ComposeTemplate', hidden: true,
component: () => import('@/views/container/template/index.vue'), meta: {
hidden: true, activeMenu: '/containers',
meta: { },
activeMenu: '/containers', },
}, {
}, path: 'template',
{ name: 'ComposeTemplate',
path: 'setting', component: () => import('@/views/container/template/index.vue'),
name: 'ContainerSetting', hidden: true,
component: () => import('@/views/container/setting/index.vue'), meta: {
hidden: true, activeMenu: '/containers',
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, sort: 4,
path: '/databases', path: '/databases',
component: Layout, component: Layout,
redirect: '/databases', redirect: '/databases/mysql',
meta: { meta: {
icon: 'p-database', icon: 'p-database',
title: 'menu.database', title: 'menu.database',
}, },
children: [ children: [
{ {
path: '', path: '/databases',
name: 'Mysql', name: 'Databases',
component: () => import('@/views/database/mysql/index.vue'), redirect: '/databases/mysql',
hidden: true, component: () => import('@/views/database/index.vue'),
meta: { meta: {},
activeMenu: '/databases', children: [
}, {
}, path: 'mysql',
{ name: 'Mysql',
path: 'redis', component: () => import('@/views/database/mysql/index.vue'),
name: 'Redis', hidden: true,
component: () => import('@/views/database/redis/index.vue'), meta: {
hidden: true, activeMenu: '/databases',
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, sort: 7,
path: '/logs', path: '/logs',
component: Layout, component: Layout,
redirect: '/logs', redirect: '/logs/operation',
meta: { meta: {
title: 'menu.logs', title: 'menu.logs',
icon: 'p-log', icon: 'p-log',
}, },
children: [ children: [
{ {
path: '', path: '/logs',
name: 'OperationLog', name: 'Log',
component: () => import('@/views/log/operation/index.vue'), redirect: '/logs/operation',
hidden: true, component: () => import('@/views/log/index.vue'),
meta: { meta: {},
activeMenu: '/logs', children: [
}, {
}, path: 'operation',
{ name: 'OperationLog',
path: 'login', component: () => import('@/views/log/operation/index.vue'),
name: 'LoginLog', hidden: true,
component: () => import('@/views/log/login/index.vue'), meta: {
hidden: true, activeMenu: '/logs',
meta: { },
activeMenu: '/logs', },
}, {
}, path: 'login',
{ name: 'LoginLog',
path: 'system', component: () => import('@/views/log/login/index.vue'),
name: 'SystemLog', hidden: true,
component: () => import('@/views/log/system/index.vue'), meta: {
hidden: true, activeMenu: '/logs',
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, sort: 8,
path: '/settings', path: '/settings',
component: Layout, component: Layout,
redirect: '/setting', redirect: '/settings/panel',
meta: { meta: {
title: 'menu.settings', title: 'menu.settings',
icon: 'p-config', icon: 'p-config',
}, },
children: [ children: [
{ {
path: '/setting', path: '/settings',
name: 'Panel', name: 'Setting',
component: () => import('@/views/setting/panel/index.vue'), redirect: '/settings/panel',
hidden: true, component: () => import('@/views/setting/index.vue'),
meta: { meta: {},
requiresAuth: true, children: [
key: 'Setting', {
}, path: 'panel',
}, name: 'Panel',
{ component: () => import('@/views/setting/panel/index.vue'),
path: '/setting/backupaccount', hidden: true,
name: 'BackupAccount', meta: {
component: () => import('@/views/setting/backup-account/index.vue'), requiresAuth: true,
hidden: true, activeMenu: 'Setting',
meta: { },
requiresAuth: true, },
key: 'Setting', {
}, path: 'backupaccount',
}, name: 'BackupAccount',
{ component: () => import('@/views/setting/backup-account/index.vue'),
path: '/setting/about', hidden: true,
name: 'About', meta: {
component: () => import('@/views/setting/about/index.vue'), requiresAuth: true,
hidden: true, activeMenu: 'Setting',
meta: { },
requiresAuth: true, },
key: 'Setting', {
}, path: 'about',
}, name: 'About',
{ component: () => import('@/views/setting/about/index.vue'),
path: '/setting/monitor', hidden: true,
name: 'Monitor', meta: {
component: () => import('@/views/setting/monitor/index.vue'), requiresAuth: true,
hidden: true, activeMenu: 'Setting',
meta: { },
requiresAuth: true, },
key: 'Setting', {
}, path: 'monitor',
}, name: 'Monitor',
{ component: () => import('@/views/setting/monitor/index.vue'),
path: '/setting/safe', hidden: true,
name: 'Safe', meta: {
component: () => import('@/views/setting/safe/index.vue'), requiresAuth: true,
hidden: true, activeMenu: 'Setting',
meta: { },
requiresAuth: true, },
key: 'Setting', {
}, path: 'safe',
}, name: 'Safe',
{ component: () => import('@/views/setting/safe/index.vue'),
path: '/setting/snapshot', hidden: true,
name: 'Snapshot', meta: {
hidden: true, requiresAuth: true,
component: () => import('@/views/setting/snapshot/index.vue'), activeMenu: 'Setting',
meta: { },
requiresAuth: true, },
key: 'Setting', {
}, path: 'snapshot',
}, name: 'Snapshot',
{ hidden: true,
path: '/expired', component: () => import('@/views/setting/snapshot/index.vue'),
name: 'Expired', meta: {
hidden: true, requiresAuth: true,
component: () => import('@/views/setting/expired.vue'), activeMenu: 'Setting',
meta: { },
requiresAuth: true, },
key: 'Expired', {
}, 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> </el-row>
</template> </template>
<template #rightButton> <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>
<template #main> <template #main>
<el-row :gutter="5"> <el-row :gutter="5">

View File

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

View File

@ -1,7 +1,5 @@
<template> <template>
<div v-loading="loading"> <div v-loading="loading">
<Submenu activeName="compose" />
<div v-show="isOnDetail"> <div v-show="isOnDetail">
<ComposeDetial @back="backList" ref="composeDetailRef" /> <ComposeDetial @back="backList" ref="composeDetailRef" />
</div> </div>
@ -12,19 +10,25 @@
</el-button> </el-button>
<span style="font-size: 14px">{{ $t('container.startIn') }}</span> <span style="font-size: 14px">{{ $t('container.startIn') }}</span>
</el-card> </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 <ComplexTable
:pagination-config="paginationConfig" :pagination-config="paginationConfig"
v-model:selects="selects" v-model:selects="selects"
:data="data" :data="data"
@search="search" @search="search"
> >
<template #toolbar>
<el-button icon="Plus" type="primary" @click="onOpenDialog()">
{{ $t('commons.button.create') }}
</el-button>
</template>
<el-table-column <el-table-column
:label="$t('commons.table.name')" :label="$t('commons.table.name')"
show-overflow-tooltip show-overflow-tooltip
@ -57,8 +61,8 @@
fix fix
/> />
</ComplexTable> </ComplexTable>
</LayoutContent> </template>
</el-card> </LayoutContent>
<EditDialog ref="dialogEditRef" /> <EditDialog ref="dialogEditRef" />
<CreateDialog @search="search" ref="dialogRef" /> <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 EditDialog from '@/views/container/compose/edit/index.vue';
import CreateDialog from '@/views/container/compose/create/index.vue'; import CreateDialog from '@/views/container/compose/create/index.vue';
import ComposeDetial from '@/views/container/compose/detail/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 { composeOperator, loadDockerStatus, searchCompose } from '@/api/modules/container';
import i18n from '@/lang'; import i18n from '@/lang';
import { ElMessage } from 'element-plus'; 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%"> <el-drawer v-model="createVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span>{{ $t('container.containerCreate') }}</span> <span>{{ $t('container.createContainer') }}</span>
</div> </div>
</template> </template>
<el-form ref="formRef" v-loading="loading" :model="form" :rules="rules" label-width="80px"> <el-form ref="formRef" v-loading="loading" :model="form" :rules="rules" label-width="80px">

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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