mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 备份账号页面调整
This commit is contained in:
parent
e7af9de9ed
commit
dc5b6fba55
@ -36,13 +36,36 @@ func NewIBackupService() IBackupService {
|
|||||||
func (u *BackupService) List() ([]dto.BackupInfo, error) {
|
func (u *BackupService) List() ([]dto.BackupInfo, error) {
|
||||||
ops, err := backupRepo.List(commonRepo.WithOrderBy("created_at desc"))
|
ops, err := backupRepo.List(commonRepo.WithOrderBy("created_at desc"))
|
||||||
var dtobas []dto.BackupInfo
|
var dtobas []dto.BackupInfo
|
||||||
|
ossExist, s3Exist, sftpExist, minioExist := false, false, false, false
|
||||||
for _, group := range ops {
|
for _, group := range ops {
|
||||||
|
switch group.Type {
|
||||||
|
case "OSS":
|
||||||
|
ossExist = true
|
||||||
|
case "S3":
|
||||||
|
s3Exist = true
|
||||||
|
case "SFTP":
|
||||||
|
sftpExist = true
|
||||||
|
case "MINIO":
|
||||||
|
minioExist = true
|
||||||
|
}
|
||||||
var item dto.BackupInfo
|
var item dto.BackupInfo
|
||||||
if err := copier.Copy(&item, &group); err != nil {
|
if err := copier.Copy(&item, &group); err != nil {
|
||||||
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||||
}
|
}
|
||||||
dtobas = append(dtobas, item)
|
dtobas = append(dtobas, item)
|
||||||
}
|
}
|
||||||
|
if !ossExist {
|
||||||
|
dtobas = append(dtobas, dto.BackupInfo{Type: "OSS"})
|
||||||
|
}
|
||||||
|
if !s3Exist {
|
||||||
|
dtobas = append(dtobas, dto.BackupInfo{Type: "S3"})
|
||||||
|
}
|
||||||
|
if !sftpExist {
|
||||||
|
dtobas = append(dtobas, dto.BackupInfo{Type: "SFTP"})
|
||||||
|
}
|
||||||
|
if !minioExist {
|
||||||
|
dtobas = append(dtobas, dto.BackupInfo{Type: "MINIO"})
|
||||||
|
}
|
||||||
return dtobas, err
|
return dtobas, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ export namespace Backup {
|
|||||||
credential: string;
|
credential: string;
|
||||||
vars: string;
|
vars: string;
|
||||||
varsJson: object;
|
varsJson: object;
|
||||||
|
createdAt: Date;
|
||||||
}
|
}
|
||||||
export interface BackupOperate {
|
export interface BackupOperate {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -699,6 +699,7 @@ export default {
|
|||||||
duplicatePassword: 'The new password cannot be the same as the original password, please re-enter!',
|
duplicatePassword: 'The new password cannot be the same as the original password, please re-enter!',
|
||||||
|
|
||||||
backup: 'Backup',
|
backup: 'Backup',
|
||||||
|
createBackupAccount: 'Create {0} backup account',
|
||||||
noTypeForCreate: 'No backup type is currently created',
|
noTypeForCreate: 'No backup type is currently created',
|
||||||
serverDisk: 'Server disks',
|
serverDisk: 'Server disks',
|
||||||
currentPath: 'Current path',
|
currentPath: 'Current path',
|
||||||
@ -734,6 +735,7 @@ export default {
|
|||||||
complexityHelper:
|
complexityHelper:
|
||||||
'The password must contain at least eight characters and contain at least three uppercase letters, lowercase letters, digits, and special characters',
|
'The password must contain at least eight characters and contain at least three uppercase letters, lowercase letters, digits, and special characters',
|
||||||
mfa: 'MFA',
|
mfa: 'MFA',
|
||||||
|
mfaHelper: 'After this function is enabled, the mobile application verification code will be verified',
|
||||||
mfaHelper1: 'Download a MFA verification mobile app such as:',
|
mfaHelper1: 'Download a MFA verification mobile app such as:',
|
||||||
mfaHelper2: 'Scan the following QR code using the mobile app to obtain the 6-digit verification code',
|
mfaHelper2: 'Scan the following QR code using the mobile app to obtain the 6-digit verification code',
|
||||||
mfaHelper3: 'Enter six digits from the app',
|
mfaHelper3: 'Enter six digits from the app',
|
||||||
|
@ -239,7 +239,7 @@ export default {
|
|||||||
database: {
|
database: {
|
||||||
delete: '删除操作无法回滚,请输入 "',
|
delete: '删除操作无法回滚,请输入 "',
|
||||||
deleteHelper: '" 删除此数据库',
|
deleteHelper: '" 删除此数据库',
|
||||||
create: '创建数据库',
|
create: '新建数据库',
|
||||||
noMysql: '当前未检测到 {0} 数据库,请进入应用商店点击安装!',
|
noMysql: '当前未检测到 {0} 数据库,请进入应用商店点击安装!',
|
||||||
mysqlBadStatus: '当前 mysql 应用状态异常,请在',
|
mysqlBadStatus: '当前 mysql 应用状态异常,请在',
|
||||||
adjust: '中查看原因或修改配置',
|
adjust: '中查看原因或修改配置',
|
||||||
@ -713,6 +713,7 @@ export default {
|
|||||||
duplicatePassword: '新密码不能与原始密码一致,请重新输入!',
|
duplicatePassword: '新密码不能与原始密码一致,请重新输入!',
|
||||||
|
|
||||||
backup: '备份',
|
backup: '备份',
|
||||||
|
createBackupAccount: '添加 {0} 备份账号',
|
||||||
noTypeForCreate: '当前无可创建备份类型',
|
noTypeForCreate: '当前无可创建备份类型',
|
||||||
serverDisk: '服务器磁盘',
|
serverDisk: '服务器磁盘',
|
||||||
currentPath: '当前路径',
|
currentPath: '当前路径',
|
||||||
@ -767,8 +768,9 @@ export default {
|
|||||||
expiredHelper: '当前密码已过期,请重新修改密码:',
|
expiredHelper: '当前密码已过期,请重新修改密码:',
|
||||||
timeoutHelper: '【 {0} 天后 】面板密码即将过期,过期后需要重新设置密码',
|
timeoutHelper: '【 {0} 天后 】面板密码即将过期,过期后需要重新设置密码',
|
||||||
complexity: '密码复杂度验证',
|
complexity: '密码复杂度验证',
|
||||||
complexityHelper: '密码必须满足密码长度大于 8 位且包含字母、数字及特殊字符',
|
complexityHelper: '开启后密码必须满足密码长度大于 8 位且包含字母、数字及特殊字符',
|
||||||
mfa: '两步验证',
|
mfa: '两步验证',
|
||||||
|
mfaHelper: '开启后会验证手机应用验证码',
|
||||||
mfaHelper1: '下载两步验证手机应用 如:',
|
mfaHelper1: '下载两步验证手机应用 如:',
|
||||||
mfaHelper2: '使用手机应用扫描以下二维码,获取 6 位验证码',
|
mfaHelper2: '使用手机应用扫描以下二维码,获取 6 位验证码',
|
||||||
mfaHelper3: '输入手机应用上的 6 位数字',
|
mfaHelper3: '输入手机应用上的 6 位数字',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="composeVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="50%">
|
<el-drawer v-model="composeVisiable" :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.compose') }}</span>
|
<span>{{ $t('container.compose') }}</span>
|
||||||
@ -39,7 +39,7 @@
|
|||||||
placeholder="#Define or paste the content of your docker-compose file here"
|
placeholder="#Define or paste the content of your docker-compose file here"
|
||||||
:indent-with-tab="true"
|
:indent-with-tab="true"
|
||||||
:tabSize="4"
|
:tabSize="4"
|
||||||
style="max-height: 500px; width: 100%; min-height: 200px"
|
style="width: 100%; height: calc(100vh - 251px)"
|
||||||
:lineWrapping="true"
|
:lineWrapping="true"
|
||||||
:matchBrackets="true"
|
:matchBrackets="true"
|
||||||
theme="cobalt"
|
theme="cobalt"
|
||||||
@ -59,7 +59,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="createVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="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.containerCreate') }}</span>
|
||||||
@ -188,7 +188,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<span class="input-help">{{ $t('container.emptyUser') }}</span>
|
<span class="input-help">{{ $t('container.emptyUser') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('container.custom')" prop="custom">
|
<el-form-item :label="$t('container.custom')" prop="custom">
|
||||||
<el-switch v-model="form.isCustom" @change="form.command = ''" />
|
<el-switch v-model="form.isCustom" @change="onChangeCommand" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="form.isCustom" label="Command" prop="command" :rules="Rules.requiredInput">
|
<el-form-item v-if="form.isCustom" label="Command" prop="command" :rules="Rules.requiredInput">
|
||||||
<el-input style="width: 30%" clearable v-model="form.command" />
|
<el-input style="width: 30%" clearable v-model="form.command" />
|
||||||
@ -84,6 +84,11 @@ const acceptParams = async (params: DialogProps): Promise<void> => {
|
|||||||
window.addEventListener('resize', changeTerminalSize);
|
window.addEventListener('resize', changeTerminalSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onChangeCommand = async () => {
|
||||||
|
console.log('addqwd');
|
||||||
|
form.command = '';
|
||||||
|
};
|
||||||
|
|
||||||
const onWSReceive = (message: any) => {
|
const onWSReceive = (message: any) => {
|
||||||
if (!isJson(message.data)) {
|
if (!isJson(message.data)) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-drawer
|
||||||
v-model="buildVisiable"
|
v-model="buildVisiable"
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
@close="onCloseLog"
|
@close="onCloseLog"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
width="50%"
|
size="50%"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
@ -27,7 +27,7 @@
|
|||||||
placeholder="#Define or paste the content of your Dockerfile here"
|
placeholder="#Define or paste the content of your Dockerfile here"
|
||||||
:indent-with-tab="true"
|
:indent-with-tab="true"
|
||||||
:tabSize="4"
|
:tabSize="4"
|
||||||
style="max-height: 500px; width: 100%; min-height: 200px"
|
style="width: 100%; height: calc(100vh - 350px)"
|
||||||
:lineWrapping="true"
|
:lineWrapping="true"
|
||||||
:matchBrackets="true"
|
:matchBrackets="true"
|
||||||
theme="cobalt"
|
theme="cobalt"
|
||||||
@ -81,7 +81,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-drawer
|
||||||
v-model="pullVisiable"
|
v-model="pullVisiable"
|
||||||
@close="onCloseLog"
|
@close="onCloseLog"
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
width="50%"
|
size="50%"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
@ -58,7 +58,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-drawer
|
||||||
v-model="pushVisiable"
|
v-model="pushVisiable"
|
||||||
@close="onCloseLog"
|
@close="onCloseLog"
|
||||||
:destroy-on-close="true"
|
:destroy-on-close="true"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
width="50%"
|
size="50%"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
@ -35,7 +35,7 @@
|
|||||||
placeholder="Waiting for push output..."
|
placeholder="Waiting for push output..."
|
||||||
:indent-with-tab="true"
|
:indent-with-tab="true"
|
||||||
:tabSize="4"
|
:tabSize="4"
|
||||||
style="max-height: 300px"
|
style="height: calc(100vh - 301px)"
|
||||||
:lineWrapping="true"
|
:lineWrapping="true"
|
||||||
:matchBrackets="true"
|
:matchBrackets="true"
|
||||||
theme="cobalt"
|
theme="cobalt"
|
||||||
@ -55,7 +55,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="saveVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
|
<el-drawer v-model="saveVisiable" :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.exportImage') }}</span>
|
<span>{{ $t('container.exportImage') }}</span>
|
||||||
@ -40,7 +40,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="tagVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
|
<el-drawer v-model="tagVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>Tag {{ $t('container.image') }}</span>
|
<span>Tag {{ $t('container.image') }}</span>
|
||||||
@ -35,7 +35,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="createVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
|
<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.createNetwork') }}</span>
|
<span>{{ $t('container.createNetwork') }}</span>
|
||||||
@ -53,7 +53,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="repoVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="50%">
|
<el-drawer v-model="repoVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>{{ title }}{{ $t('container.repo') }}</span>
|
<span>{{ title }}{{ $t('container.repo') }}</span>
|
||||||
@ -60,7 +60,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="templateVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="50%">
|
<el-drawer v-model="templateVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>{{ title }}{{ $t('container.composeTemplate') }}</span>
|
<span>{{ title }}{{ $t('container.composeTemplate') }}</span>
|
||||||
@ -18,7 +18,7 @@
|
|||||||
placeholder="#Define or paste the content of your docker-compose file here"
|
placeholder="#Define or paste the content of your docker-compose file here"
|
||||||
:indent-with-tab="true"
|
:indent-with-tab="true"
|
||||||
:tabSize="4"
|
:tabSize="4"
|
||||||
style="max-height: 500px; width: 100%; min-height: 200px"
|
style="width: 100%; height: calc(100vh - 251px)"
|
||||||
:lineWrapping="true"
|
:lineWrapping="true"
|
||||||
:matchBrackets="true"
|
:matchBrackets="true"
|
||||||
theme="cobalt"
|
theme="cobalt"
|
||||||
@ -39,7 +39,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="createVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
|
<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.createVolume') }}</span>
|
<span>{{ $t('container.createVolume') }}</span>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="cronjobVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="50%">
|
<el-drawer v-model="cronjobVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>{{ title }}{{ $t('cronjob.cronTask') }}</span>
|
<span>{{ title }}{{ $t('cronjob.cronTask') }}</span>
|
||||||
@ -138,7 +138,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-dialog v-model="backupVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="50%">
|
<el-drawer v-model="backupVisiable" :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('database.backup') }} - {{ dbName }}</span>
|
<span>{{ $t('database.backup') }} - {{ dbName }}</span>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" fix />
|
<fu-table-operations :buttons="buttons" :label="$t('commons.table.operate')" fix />
|
||||||
</ComplexTable>
|
</ComplexTable>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="createVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
|
<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('database.create') }}</span>
|
<span>{{ $t('database.create') }}</span>
|
||||||
@ -9,7 +9,7 @@
|
|||||||
<el-form-item :label="$t('commons.table.name')" prop="name">
|
<el-form-item :label="$t('commons.table.name')" prop="name">
|
||||||
<el-input clearable v-model.trim="form.name">
|
<el-input clearable v-model.trim="form.name">
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-select v-model="form.format" style="width: 125px">
|
<el-select v-model="form.format" style="width: 80px">
|
||||||
<el-option label="utf8mb4" value="utf8mb4" />
|
<el-option label="utf8mb4" value="utf8mb4" />
|
||||||
<el-option label="utf-8" value="utf8" />
|
<el-option label="utf-8" value="utf8" />
|
||||||
<el-option label="gbk" value="gbk" />
|
<el-option label="gbk" value="gbk" />
|
||||||
@ -26,7 +26,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('database.permission')" prop="permission">
|
<el-form-item :label="$t('database.permission')" prop="permission">
|
||||||
<el-select style="width: 100%" v-model="form.permission">
|
<el-select v-model="form.permission">
|
||||||
<el-option value="localhost" :label="$t('database.permissionLocal')" />
|
<el-option value="localhost" :label="$t('database.permissionLocal')" />
|
||||||
<el-option value="%" :label="$t('database.permissionAll')" />
|
<el-option value="%" :label="$t('database.permissionAll')" />
|
||||||
<el-option value="ip" :label="$t('database.permissionForIP')" />
|
<el-option value="ip" :label="$t('database.permissionForIP')" />
|
||||||
@ -47,7 +47,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -17,79 +17,87 @@
|
|||||||
>
|
>
|
||||||
<span style="font-size: 14px">{{ $t('commons.service.serviceNotStarted', ['Mysql']) }}</span>
|
<span style="font-size: 14px">{{ $t('commons.service.serviceNotStarted', ['Mysql']) }}</span>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
<div style="margin-top: 20px" v-if="mysqlIsExist && !isOnSetting">
|
||||||
|
<el-button type="primary" @click="onOpenDialog()">
|
||||||
|
{{ $t('database.create') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onChangeRootPassword" type="primary" plain>
|
||||||
|
{{ $t('database.rootPassword') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onChangeAccess" type="primary" plain>
|
||||||
|
{{ $t('database.remoteAccess') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="goDashboard" type="primary" plain>phpMyAdmin</el-button>
|
||||||
|
</div>
|
||||||
<div v-if="mysqlIsExist" :class="{ mask: mysqlStatus != 'Running' }">
|
<div v-if="mysqlIsExist" :class="{ mask: mysqlStatus != 'Running' }">
|
||||||
<el-card v-if="!isOnSetting" style="margin-top: 20px">
|
<el-card v-if="!isOnSetting" style="margin-top: 10px">
|
||||||
<ComplexTable :pagination-config="paginationConfig" @search="search" :data="data">
|
<LayoutContent :header="'Mysql ' + $t('menu.database')">
|
||||||
<template #toolbar>
|
<ComplexTable :pagination-config="paginationConfig" @search="search" :data="data">
|
||||||
<el-button type="primary" icon="Plus" @click="onOpenDialog()">
|
<el-table-column :label="$t('commons.table.name')" prop="name" />
|
||||||
{{ $t('commons.button.create') }}
|
<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="onChangeRootPassword" type="primary" plain>
|
<template #default="{ row }">
|
||||||
{{ $t('database.rootPassword') }}
|
<div>
|
||||||
</el-button>
|
<span style="float: left; line-height: 25px" v-if="!row.showPassword">
|
||||||
<el-button @click="onChangeAccess" type="primary" plain>
|
***********
|
||||||
{{ $t('database.remoteAccess') }}
|
</span>
|
||||||
</el-button>
|
<div style="cursor: pointer; float: left" v-if="!row.showPassword">
|
||||||
<el-button @click="goDashboard" type="primary" plain icon="Position">phpMyAdmin</el-button>
|
<el-icon
|
||||||
</template>
|
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>
|
||||||
<div style="cursor: pointer; float: left" v-if="!row.showPassword">
|
<span style="float: left" v-if="row.showPassword">{{ row.password }}</span>
|
||||||
<el-icon
|
<div style="cursor: pointer; float: left" v-if="row.showPassword">
|
||||||
style="margin-left: 5px; margin-top: 3px"
|
<el-icon
|
||||||
@click="row.showPassword = true"
|
style="margin-left: 5px; margin-top: 3px"
|
||||||
:size="16"
|
@click="row.showPassword = false"
|
||||||
>
|
:size="16"
|
||||||
<View />
|
>
|
||||||
</el-icon>
|
<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>
|
||||||
<span style="float: left" v-if="row.showPassword">{{ row.password }}</span>
|
</template>
|
||||||
<div style="cursor: pointer; float: left" v-if="row.showPassword">
|
</el-table-column>
|
||||||
<el-icon
|
<el-table-column :label="$t('commons.table.description')" prop="description">
|
||||||
style="margin-left: 5px; margin-top: 3px"
|
<template #default="{ row }">
|
||||||
@click="row.showPassword = false"
|
<fu-read-write-switch
|
||||||
:size="16"
|
:data="row.description"
|
||||||
>
|
v-model="row.edit"
|
||||||
<Hide />
|
@change="onChange(row)"
|
||||||
</el-icon>
|
>
|
||||||
</div>
|
<el-input v-model="row.description" @blur="row.edit = false" />
|
||||||
<div style="cursor: pointer; float: left">
|
</fu-read-write-switch>
|
||||||
<el-icon
|
</template>
|
||||||
style="margin-left: 5px; margin-top: 3px"
|
</el-table-column>
|
||||||
:size="16"
|
<el-table-column
|
||||||
@click="onCopyPassword(row)"
|
prop="createdAt"
|
||||||
>
|
:label="$t('commons.table.date')"
|
||||||
<DocumentCopy />
|
:formatter="dateFromat"
|
||||||
</el-icon>
|
show-overflow-tooltip
|
||||||
</div>
|
/>
|
||||||
</div>
|
<fu-table-operations
|
||||||
</template>
|
width="300px"
|
||||||
</el-table-column>
|
:buttons="buttons"
|
||||||
<el-table-column :label="$t('commons.table.description')" prop="description">
|
:ellipsis="10"
|
||||||
<template #default="{ row }">
|
:label="$t('commons.table.operate')"
|
||||||
<fu-read-write-switch :data="row.description" v-model="row.edit" @change="onChange(row)">
|
fix
|
||||||
<el-input v-model="row.description" @blur="row.edit = false" />
|
/>
|
||||||
</fu-read-write-switch>
|
</ComplexTable>
|
||||||
</template>
|
</LayoutContent>
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
|
||||||
prop="createdAt"
|
|
||||||
:label="$t('commons.table.date')"
|
|
||||||
:formatter="dateFromat"
|
|
||||||
show-overflow-tooltip
|
|
||||||
/>
|
|
||||||
<fu-table-operations
|
|
||||||
width="300px"
|
|
||||||
:buttons="buttons"
|
|
||||||
:ellipsis="10"
|
|
||||||
:label="$t('commons.table.operate')"
|
|
||||||
fix
|
|
||||||
/>
|
|
||||||
</ComplexTable>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
<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%">
|
||||||
@ -175,6 +183,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
import ComplexTable from '@/components/complex-table/index.vue';
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
import OperateDialog from '@/views/database/mysql/create/index.vue';
|
import OperateDialog from '@/views/database/mysql/create/index.vue';
|
||||||
import DeleteDialog from '@/views/database/mysql/delete/index.vue';
|
import DeleteDialog from '@/views/database/mysql/delete/index.vue';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-dialog v-model="upVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="70%">
|
<el-drawer v-model="upVisiable" :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('commons.button.import') }}</span>
|
<span>{{ $t('commons.button.import') }}</span>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
fix
|
fix
|
||||||
/>
|
/>
|
||||||
</ComplexTable>
|
</ComplexTable>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -1,71 +1,190 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Submenu activeName="backupaccount" />
|
<Submenu activeName="backupaccount" />
|
||||||
<el-card style="margin-top: 20px">
|
<el-form label-position="left" label-width="130px" :v-key="reflash">
|
||||||
<template #header>
|
<el-row :gutter="20" style="margin-top: 20px">
|
||||||
<div class="card-header">
|
<el-col :span="24">
|
||||||
<span>{{ $t('setting.backup') }}</span>
|
<el-card>
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-button type="primary" icon="Plus" @click="onOpenDialog('create')">
|
|
||||||
{{ $t('commons.button.create') }}
|
|
||||||
</el-button>
|
|
||||||
<el-row :gutter="20" class="row-box">
|
|
||||||
<el-col v-for="item in data" :key="item.id" :span="8" style="margin-top: 20px">
|
|
||||||
<el-card class="el-card">
|
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<svg-icon style="font-size: 7px" iconName="p-file-folder"></svg-icon>
|
||||||
<svg-icon style="font-size: 7px" :iconName="loadIconName(item.type)"></svg-icon>
|
<span style="font-size: 16px; font-weight: 500"> {{ $t('setting.serverDisk') }}</span>
|
||||||
<span style="font-size: 16px; font-weight: 500">
|
<div style="float: right">
|
||||||
{{ loadBackupName(item.type) }}
|
<el-button round @click="onOpenDialog('edit', 'local', localData)">
|
||||||
</span>
|
{{ $t('commons.button.edit') }}
|
||||||
<div style="float: right">
|
</el-button>
|
||||||
<el-button @click="onOpenDialog('edit', item)">
|
|
||||||
{{ $t('commons.button.edit') }}
|
|
||||||
</el-button>
|
|
||||||
<el-button v-if="item.type !== 'LOCAL'" @click="onBatchDelete(item)">
|
|
||||||
{{ $t('commons.button.delete') }}
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-form label-position="left" label-width="130px">
|
<el-form-item :label="$t('setting.currentPath')">
|
||||||
<el-form-item v-if="item.type === 'LOCAL'" :label="$t('setting.currentPath')">
|
{{ localData.varsJson['dir'] }}
|
||||||
{{ item.varsJson['dir'] }}
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
<el-form-item v-if="item.type === 'S3'" label="Region">
|
{{ dateFromat(0, 0, localData.createdAt) }}
|
||||||
{{ item.varsJson['region'] }}
|
</el-form-item>
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="hasBucket(item.type)" label="Endpoint">
|
|
||||||
{{ item.varsJson['endpoint'] }}
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="hasBucket(item.type)" label="Bucket">
|
|
||||||
{{ item.bucket }}
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="item.type === 'SFTP'" :label="$t('setting.address')">
|
|
||||||
{{ item.varsJson['address'] }}
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="item.type === 'SFTP'" :label="$t('setting.port')">
|
|
||||||
{{ item.varsJson['port'] }}
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="item.type === 'SFTP'" :label="$t('setting.path')">
|
|
||||||
{{ item.bucket }}
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('commons.table.createdAt')">
|
|
||||||
{{ dateFromat(0, 0, item.createdAt) }}
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-card>
|
<el-row :gutter="20" style="margin-top: 20px">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<svg-icon style="font-size: 7px" iconName="p-MINIO"></svg-icon>
|
||||||
|
<span style="font-size: 16px; font-weight: 500"> MIMIO</span>
|
||||||
|
<div style="float: right">
|
||||||
|
<el-button :disabled="minioData.id === 0" round @click="onBatchDelete(minioData)">
|
||||||
|
{{ $t('commons.button.delete') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
round
|
||||||
|
:disabled="minioData.id === 0"
|
||||||
|
@click="onOpenDialog('edit', 'MINIO', minioData)"
|
||||||
|
>
|
||||||
|
{{ $t('commons.button.edit') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-if="minioData.id !== 0">
|
||||||
|
<el-form-item label="Endpoint">
|
||||||
|
{{ minioData.varsJson['endpoint'] }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Bucket">
|
||||||
|
{{ minioData.bucket }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
|
{{ dateFromat(0, 0, minioData.createdAt) }}
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<el-alert v-else center style="height: 127px; background-color: #e2e4ec" :closable="false">
|
||||||
|
<el-button size="large" round plain type="primary" @click="onOpenDialog('create', 'MINIO')">
|
||||||
|
{{ $t('setting.createBackupAccount', ['MINIO']) }}
|
||||||
|
</el-button>
|
||||||
|
</el-alert>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<svg-icon style="font-size: 7px" iconName="p-OSS"></svg-icon>
|
||||||
|
<span style="font-size: 16px; font-weight: 500"> OSS</span>
|
||||||
|
<div style="float: right">
|
||||||
|
<el-button round :disabled="ossData.id === 0" @click="onBatchDelete(ossData)">
|
||||||
|
{{ $t('commons.button.delete') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
round
|
||||||
|
:disabled="ossData.id === 0"
|
||||||
|
@click="onOpenDialog('edit', 'OSS', ossData)"
|
||||||
|
>
|
||||||
|
{{ $t('commons.button.edit') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-if="ossData.id !== 0">
|
||||||
|
<el-form-item label="Endpoint">
|
||||||
|
{{ ossData.varsJson['endpoint'] }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Bucket">
|
||||||
|
{{ ossData.bucket }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
|
{{ dateFromat(0, 0, ossData.createdAt) }}
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<el-alert v-else center style="height: 127px; background-color: #e2e4ec" :closable="false">
|
||||||
|
<el-button size="large" round plain type="primary" @click="onOpenDialog('create', 'OSS')">
|
||||||
|
{{ $t('setting.createBackupAccount', ['OSS']) }}
|
||||||
|
</el-button>
|
||||||
|
</el-alert>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20" style="margin-top: 20px">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<svg-icon style="font-size: 7px" iconName="p-aws"></svg-icon>
|
||||||
|
<span style="font-size: 16px; font-weight: 500"> {{ $t('setting.S3') }}</span>
|
||||||
|
<div style="float: right">
|
||||||
|
<el-button round :disabled="s3Data.id === 0" @click="onBatchDelete(s3Data)">
|
||||||
|
{{ $t('commons.button.delete') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
round
|
||||||
|
:disabled="s3Data.id === 0"
|
||||||
|
@click="onOpenDialog('edit', 'S3', s3Data)"
|
||||||
|
>
|
||||||
|
{{ $t('commons.button.edit') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-if="s3Data.id !== 0">
|
||||||
|
<el-form-item label="Region">
|
||||||
|
{{ s3Data.varsJson['region'] }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Endpoint">
|
||||||
|
{{ s3Data.varsJson['endpoint'] }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="Bucket">
|
||||||
|
{{ s3Data.bucket }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
|
{{ dateFromat(0, 0, s3Data.createdAt) }}
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<el-alert v-else center style="height: 167px; background-color: #e2e4ec" :closable="false">
|
||||||
|
<el-button size="large" round plain type="primary" @click="onOpenDialog('create', 'S3')">
|
||||||
|
{{ $t('setting.createBackupAccount', ['S3']) }}
|
||||||
|
</el-button>
|
||||||
|
</el-alert>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
<svg-icon style="font-size: 7px" iconName="p-SFTP"></svg-icon>
|
||||||
|
<span style="font-size: 16px; font-weight: 500"> SFTP</span>
|
||||||
|
<div style="float: right">
|
||||||
|
<el-button round :disabled="sftpData.id === 0" @click="onBatchDelete(sftpData)">
|
||||||
|
{{ $t('commons.button.delete') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
round
|
||||||
|
plain
|
||||||
|
:disabled="sftpData.id === 0"
|
||||||
|
@click="onOpenDialog('edit', 'SFTP', sftpData)"
|
||||||
|
>
|
||||||
|
{{ $t('commons.button.edit') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div v-if="sftpData.id !== 0">
|
||||||
|
<el-form-item :label="$t('setting.address')">
|
||||||
|
{{ sftpData.varsJson['address'] }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.port')">
|
||||||
|
{{ sftpData.varsJson['port'] }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.path')">
|
||||||
|
{{ sftpData.bucket }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('commons.table.createdAt')">
|
||||||
|
{{ dateFromat(0, 0, sftpData.createdAt) }}
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<el-alert v-else center style="height: 167px; background-color: #e2e4ec" :closable="false">
|
||||||
|
<el-button size="large" round plain type="primary" @click="onOpenDialog('create', 'SFTP')">
|
||||||
|
{{ $t('setting.createBackupAccount', ['SFTP']) }}
|
||||||
|
</el-button>
|
||||||
|
</el-alert>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
<DialogOperate ref="dialogRef" @search="search" />
|
<DialogOperate ref="dialogRef" @search="search" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { dateFromat } from '@/utils/util';
|
import { dateFromat } from '@/utils/util';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { loadBackupName } from '@/views/setting/helper';
|
|
||||||
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 Submenu from '@/views/setting/index.vue';
|
||||||
@ -74,12 +193,96 @@ import { ElForm } from 'element-plus';
|
|||||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||||
|
|
||||||
const data = ref();
|
const data = ref();
|
||||||
|
const reflash = ref(false);
|
||||||
|
const localData = ref<Backup.BackupInfo>({
|
||||||
|
id: 0,
|
||||||
|
type: 'LOCAL',
|
||||||
|
accessKey: '',
|
||||||
|
bucket: '',
|
||||||
|
credential: '',
|
||||||
|
vars: '',
|
||||||
|
varsJson: {
|
||||||
|
dir: '',
|
||||||
|
},
|
||||||
|
createdAt: new Date(),
|
||||||
|
});
|
||||||
|
const ossData = ref<Backup.BackupInfo>({
|
||||||
|
id: 0,
|
||||||
|
type: 'OSS',
|
||||||
|
accessKey: '',
|
||||||
|
bucket: '',
|
||||||
|
credential: '',
|
||||||
|
vars: '',
|
||||||
|
varsJson: {
|
||||||
|
region: '',
|
||||||
|
endpoint: '',
|
||||||
|
},
|
||||||
|
createdAt: new Date(),
|
||||||
|
});
|
||||||
|
const minioData = ref<Backup.BackupInfo>({
|
||||||
|
id: 0,
|
||||||
|
type: 'MINIO',
|
||||||
|
accessKey: '',
|
||||||
|
bucket: '',
|
||||||
|
credential: '',
|
||||||
|
vars: '',
|
||||||
|
varsJson: {
|
||||||
|
region: '',
|
||||||
|
endpoint: '',
|
||||||
|
},
|
||||||
|
createdAt: new Date(),
|
||||||
|
});
|
||||||
|
const sftpData = ref<Backup.BackupInfo>({
|
||||||
|
id: 0,
|
||||||
|
type: 'SFTP',
|
||||||
|
accessKey: '',
|
||||||
|
bucket: '',
|
||||||
|
credential: '',
|
||||||
|
vars: '',
|
||||||
|
varsJson: {
|
||||||
|
address: '',
|
||||||
|
port: 0,
|
||||||
|
},
|
||||||
|
createdAt: new Date(),
|
||||||
|
});
|
||||||
|
const s3Data = ref<Backup.BackupInfo>({
|
||||||
|
id: 0,
|
||||||
|
type: 'S3',
|
||||||
|
accessKey: '',
|
||||||
|
bucket: '',
|
||||||
|
credential: '',
|
||||||
|
vars: '',
|
||||||
|
varsJson: {
|
||||||
|
region: '',
|
||||||
|
endpoint: '',
|
||||||
|
},
|
||||||
|
createdAt: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
const res = await getBackupList();
|
const res = await getBackupList();
|
||||||
data.value = res.data;
|
data.value = res.data || [];
|
||||||
for (const bac of data.value) {
|
for (const bac of data.value) {
|
||||||
bac.varsJson = JSON.parse(bac.vars);
|
if (bac.id !== 0) {
|
||||||
|
bac.varsJson = JSON.parse(bac.vars);
|
||||||
|
}
|
||||||
|
switch (bac.type) {
|
||||||
|
case 'LOCAL':
|
||||||
|
localData.value = bac;
|
||||||
|
break;
|
||||||
|
case 'OSS':
|
||||||
|
ossData.value = bac;
|
||||||
|
break;
|
||||||
|
case 'S3':
|
||||||
|
s3Data.value = bac;
|
||||||
|
break;
|
||||||
|
case 'MINIO':
|
||||||
|
minioData.value = bac;
|
||||||
|
break;
|
||||||
|
case 'SFTP':
|
||||||
|
sftpData.value = bac;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,46 +296,21 @@ const onBatchDelete = async (row: Backup.BackupInfo | null) => {
|
|||||||
const dialogRef = ref();
|
const dialogRef = ref();
|
||||||
const onOpenDialog = async (
|
const onOpenDialog = async (
|
||||||
title: string,
|
title: string,
|
||||||
|
accountType: string,
|
||||||
rowData: Partial<Backup.BackupInfo> = {
|
rowData: Partial<Backup.BackupInfo> = {
|
||||||
id: 0,
|
id: 0,
|
||||||
|
type: accountType,
|
||||||
varsJson: {},
|
varsJson: {},
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
let types = [] as Array<string>;
|
console.log(rowData);
|
||||||
for (const item of data.value) {
|
|
||||||
types.push(item.type);
|
|
||||||
}
|
|
||||||
let params = {
|
let params = {
|
||||||
title,
|
title,
|
||||||
types,
|
|
||||||
rowData: { ...rowData },
|
rowData: { ...rowData },
|
||||||
};
|
};
|
||||||
dialogRef.value!.acceptParams(params);
|
dialogRef.value!.acceptParams(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
function hasBucket(val: string) {
|
|
||||||
return val === 'OSS' || val === 'S3' || val === 'MINIO';
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadIconName = (type: string) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'OSS':
|
|
||||||
return 'p-oss';
|
|
||||||
break;
|
|
||||||
case 'S3':
|
|
||||||
return 'p-aws';
|
|
||||||
break;
|
|
||||||
case 'SFTP':
|
|
||||||
return 'p-SFTP';
|
|
||||||
break;
|
|
||||||
case 'MINIO':
|
|
||||||
return 'p-minio';
|
|
||||||
break;
|
|
||||||
case 'LOCAL':
|
|
||||||
return 'p-file-folder';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
search();
|
search();
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="dialogVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="50%">
|
<el-drawer v-model="dialogVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>{{ title }}{{ $t('setting.backupAccount') }}</span>
|
<span>{{ title }}{{ $t('setting.backupAccount') }}</span>
|
||||||
@ -7,14 +7,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-form ref="formRef" v-loading="loading" :model="dialogData.rowData" label-width="120px">
|
<el-form ref="formRef" v-loading="loading" :model="dialogData.rowData" label-width="120px">
|
||||||
<el-form-item :label="$t('commons.table.type')" prop="type" :rules="Rules.requiredSelect">
|
<el-form-item :label="$t('commons.table.type')" prop="type" :rules="Rules.requiredSelect">
|
||||||
<el-select
|
<span>{{ dialogData.rowData!.type }}</span>
|
||||||
style="width: 100%"
|
|
||||||
v-model="dialogData.rowData!.type"
|
|
||||||
@change="changeType"
|
|
||||||
:disabled="title === $t('commons.button.edit')"
|
|
||||||
>
|
|
||||||
<el-option v-for="item in typeOptions" :key="item.label" :value="item.value" :label="item.label" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="dialogData.rowData!.type === 'LOCAL'"
|
v-if="dialogData.rowData!.type === 'LOCAL'"
|
||||||
@ -116,7 +109,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -132,7 +125,6 @@ import { deepCopy } from '@/utils/util';
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
type FormInstance = InstanceType<typeof ElForm>;
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
const typeOptions = ref();
|
|
||||||
const buckets = ref();
|
const buckets = ref();
|
||||||
|
|
||||||
const endpoints = ref('http');
|
const endpoints = ref('http');
|
||||||
@ -141,7 +133,6 @@ const emit = defineEmits<{ (e: 'search'): void }>();
|
|||||||
|
|
||||||
interface DialogProps {
|
interface DialogProps {
|
||||||
title: string;
|
title: string;
|
||||||
types: Array<string>;
|
|
||||||
rowData?: Backup.BackupInfo;
|
rowData?: Backup.BackupInfo;
|
||||||
getTableList?: () => Promise<any>;
|
getTableList?: () => Promise<any>;
|
||||||
}
|
}
|
||||||
@ -149,7 +140,6 @@ const title = ref<string>('');
|
|||||||
const dialogVisiable = ref(false);
|
const dialogVisiable = ref(false);
|
||||||
const dialogData = ref<DialogProps>({
|
const dialogData = ref<DialogProps>({
|
||||||
title: '',
|
title: '',
|
||||||
types: [],
|
|
||||||
});
|
});
|
||||||
const acceptParams = (params: DialogProps): void => {
|
const acceptParams = (params: DialogProps): void => {
|
||||||
dialogData.value = params;
|
dialogData.value = params;
|
||||||
@ -161,36 +151,9 @@ const acceptParams = (params: DialogProps): void => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
title.value = i18n.global.t('commons.button.' + dialogData.value.title);
|
||||||
loadOption(params.types);
|
|
||||||
dialogVisiable.value = true;
|
dialogVisiable.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadOption = (existTypes: Array<string>) => {
|
|
||||||
let options = [
|
|
||||||
{ label: i18n.global.t('setting.serverDisk'), value: 'LOCAL' },
|
|
||||||
{ label: i18n.global.t('setting.OSS'), value: 'OSS' },
|
|
||||||
{ label: i18n.global.t('setting.S3'), value: 'S3' },
|
|
||||||
{ label: 'SFTP', value: 'SFTP' },
|
|
||||||
{ label: 'MinIO', value: 'MINIO' },
|
|
||||||
];
|
|
||||||
for (const item of existTypes) {
|
|
||||||
for (let i = 0; i < options.length; i++) {
|
|
||||||
if (item === options[i].value) {
|
|
||||||
options.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
typeOptions.value = options;
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeType = async (val: string) => {
|
|
||||||
let itemType = val;
|
|
||||||
buckets.value = [];
|
|
||||||
if (formRef.value) {
|
|
||||||
formRef.value.resetFields();
|
|
||||||
}
|
|
||||||
dialogData.value.rowData!.type = itemType;
|
|
||||||
};
|
|
||||||
const loadDir = async (path: string) => {
|
const loadDir = async (path: string) => {
|
||||||
dialogData.value.rowData!.varsJson['dir'] = path;
|
dialogData.value.rowData!.varsJson['dir'] = path;
|
||||||
};
|
};
|
||||||
|
@ -3,205 +3,133 @@
|
|||||||
<Submenu activeName="panel" />
|
<Submenu activeName="panel" />
|
||||||
<el-form :model="form" ref="panelFormRef" label-position="left" v-loading="loading" label-width="160px">
|
<el-form :model="form" ref="panelFormRef" label-position="left" v-loading="loading" label-width="160px">
|
||||||
<el-card style="margin-top: 20px">
|
<el-card style="margin-top: 20px">
|
||||||
<template #header>
|
<LayoutContent :header="$t('setting.panel')">
|
||||||
<div class="card-header">
|
<el-row>
|
||||||
<span>{{ $t('setting.panel') }}</span>
|
<el-col :span="1"><br /></el-col>
|
||||||
</div>
|
<el-col :span="10">
|
||||||
</template>
|
<el-form-item
|
||||||
<el-row>
|
:label="$t('commons.login.username')"
|
||||||
<el-col :span="1"><br /></el-col>
|
:rules="Rules.requiredInput"
|
||||||
<el-col :span="10">
|
prop="userName"
|
||||||
<el-form-item
|
|
||||||
:label="$t('commons.login.username')"
|
|
||||||
:rules="Rules.requiredInput"
|
|
||||||
prop="userName"
|
|
||||||
>
|
|
||||||
<el-input clearable v-model="form.userName">
|
|
||||||
<template #append>
|
|
||||||
<el-button
|
|
||||||
@click="onSave(panelFormRef, 'UserName', form.userName)"
|
|
||||||
icon="Collection"
|
|
||||||
>
|
|
||||||
{{ $t('commons.button.save') }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('commons.login.password')"
|
|
||||||
:rules="Rules.requiredInput"
|
|
||||||
prop="password"
|
|
||||||
>
|
|
||||||
<el-input type="password" clearable disabled v-model="form.password">
|
|
||||||
<template #append>
|
|
||||||
<el-button icon="Setting" @click="onChangePassword">
|
|
||||||
{{ $t('commons.button.set') }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('setting.title')" :rules="Rules.requiredInput" prop="panelName">
|
|
||||||
<el-input clearable v-model="form.panelName">
|
|
||||||
<template #append>
|
|
||||||
<el-button
|
|
||||||
@click="onSave(panelFormRef, 'PanelName', form.panelName)"
|
|
||||||
icon="Collection"
|
|
||||||
>
|
|
||||||
{{ $t('commons.button.save') }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('setting.theme')" :rules="Rules.requiredSelect" prop="theme">
|
|
||||||
<el-radio-group @change="onSave(panelFormRef, 'Theme', form.theme)" v-model="form.theme">
|
|
||||||
<el-radio-button label="dark">
|
|
||||||
<el-icon><Moon /></el-icon>
|
|
||||||
{{ $t('setting.dark') }}
|
|
||||||
</el-radio-button>
|
|
||||||
<el-radio-button label="light">
|
|
||||||
<el-icon><Sunny /></el-icon>
|
|
||||||
{{ $t('setting.light') }}
|
|
||||||
</el-radio-button>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('setting.language')" :rules="Rules.requiredSelect" prop="language">
|
|
||||||
<el-radio-group
|
|
||||||
style="width: 100%"
|
|
||||||
@change="onSave(panelFormRef, 'Language', form.language)"
|
|
||||||
v-model="form.language"
|
|
||||||
>
|
>
|
||||||
<el-radio-button label="zh">中文</el-radio-button>
|
<el-input clearable v-model="form.userName">
|
||||||
<el-radio-button label="en">English</el-radio-button>
|
<template #append>
|
||||||
</el-radio-group>
|
<el-button
|
||||||
<div>
|
@click="onSave(panelFormRef, 'UserName', form.userName)"
|
||||||
<span class="input-help">
|
icon="Collection"
|
||||||
{{ $t('setting.languageHelper') }}
|
>
|
||||||
</span>
|
{{ $t('commons.button.save') }}
|
||||||
</div>
|
</el-button>
|
||||||
</el-form-item>
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('setting.sessionTimeout')" :rules="Rules.number" prop="sessionTimeout">
|
<el-form-item :label="$t('setting.title')" :rules="Rules.requiredInput" prop="panelName">
|
||||||
<el-input v-model.number="form.sessionTimeout">
|
<el-input clearable v-model="form.panelName">
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-button
|
<el-button
|
||||||
@click="onSave(panelFormRef, 'SessionTimeout', form.sessionTimeout)"
|
@click="onSave(panelFormRef, 'PanelName', form.panelName)"
|
||||||
icon="Collection"
|
icon="Collection"
|
||||||
>
|
>
|
||||||
{{ $t('commons.button.save') }}
|
{{ $t('commons.button.save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<div>
|
</el-form-item>
|
||||||
<span class="input-help">
|
|
||||||
{{ $t('setting.sessionTimeoutHelper', [form.sessionTimeout]) }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item :label="$t('setting.syncTime')">
|
<el-form-item :label="$t('setting.theme')" :rules="Rules.requiredSelect" prop="theme">
|
||||||
<el-input disabled v-model="form.localTime">
|
<el-radio-group
|
||||||
<template #append>
|
@change="onSave(panelFormRef, 'Theme', form.theme)"
|
||||||
<el-button v-show="!show" @click="onSyncTime" icon="Refresh">
|
v-model="form.theme"
|
||||||
{{ $t('commons.button.sync') }}
|
>
|
||||||
</el-button>
|
<el-radio-button label="dark">
|
||||||
<span v-show="show">{{ count }} S</span>
|
<el-icon><Moon /></el-icon>
|
||||||
</template>
|
{{ $t('setting.dark') }}
|
||||||
</el-input>
|
</el-radio-button>
|
||||||
</el-form-item>
|
<el-radio-button label="light">
|
||||||
</el-col>
|
<el-icon><Sunny /></el-icon>
|
||||||
</el-row>
|
{{ $t('setting.light') }}
|
||||||
|
</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="$t('setting.language')" :rules="Rules.requiredSelect" prop="language">
|
||||||
|
<el-radio-group
|
||||||
|
style="width: 100%"
|
||||||
|
@change="onSave(panelFormRef, 'Language', form.language)"
|
||||||
|
v-model="form.language"
|
||||||
|
>
|
||||||
|
<el-radio label="zh">中文</el-radio>
|
||||||
|
<el-radio label="en">English</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<div>
|
||||||
|
<span class="input-help">
|
||||||
|
{{ $t('setting.languageHelper') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('setting.sessionTimeout')"
|
||||||
|
:rules="Rules.number"
|
||||||
|
prop="sessionTimeout"
|
||||||
|
>
|
||||||
|
<el-input v-model.number="form.sessionTimeout">
|
||||||
|
<template #append>
|
||||||
|
<el-button
|
||||||
|
@click="onSave(panelFormRef, 'SessionTimeout', form.sessionTimeout)"
|
||||||
|
icon="Collection"
|
||||||
|
>
|
||||||
|
{{ $t('commons.button.save') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<div>
|
||||||
|
<span class="input-help">
|
||||||
|
{{ $t('setting.sessionTimeoutHelper', [form.sessionTimeout]) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item :label="$t('setting.syncTime')">
|
||||||
|
<el-input disabled v-model="form.localTime">
|
||||||
|
<template #append>
|
||||||
|
<el-button v-show="!show" @click="onSyncTime" icon="Refresh">
|
||||||
|
{{ $t('commons.button.sync') }}
|
||||||
|
</el-button>
|
||||||
|
<span v-show="show">{{ count }} S</span>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</LayoutContent>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-dialog
|
|
||||||
v-model="passwordVisiable"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:title="$t('setting.changePassword')"
|
|
||||||
width="30%"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
v-loading="dialogLoading"
|
|
||||||
ref="passFormRef"
|
|
||||||
label-width="80px"
|
|
||||||
label-position="left"
|
|
||||||
:model="passForm"
|
|
||||||
:rules="passRules"
|
|
||||||
>
|
|
||||||
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
|
|
||||||
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
v-if="form.complexityVerification === 'disable'"
|
|
||||||
:label="$t('setting.newPassword')"
|
|
||||||
prop="newPassword"
|
|
||||||
>
|
|
||||||
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
v-if="form.complexityVerification === 'enable'"
|
|
||||||
:label="$t('setting.newPassword')"
|
|
||||||
prop="newPasswordComplexity"
|
|
||||||
>
|
|
||||||
<el-input type="password" show-password clearable v-model="passForm.newPasswordComplexity" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('setting.retryPassword')" prop="retryPassword">
|
|
||||||
<el-input type="password" show-password clearable v-model="passForm.retryPassword" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button :disabled="dialogLoading" @click="passwordVisiable = false">
|
|
||||||
{{ $t('commons.button.cancel') }}
|
|
||||||
</el-button>
|
|
||||||
<el-button :disabled="dialogLoading" @click="submitChangePassword(passFormRef)">
|
|
||||||
{{ $t('commons.button.confirm') }}
|
|
||||||
</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, reactive, onMounted, computed } from 'vue';
|
import { ref, reactive, onMounted, computed } from 'vue';
|
||||||
import { ElMessage, ElForm } from 'element-plus';
|
import { ElMessage, ElForm } from 'element-plus';
|
||||||
import { updatePassword, syncTime, getSettingInfo, updateSetting } from '@/api/modules/setting';
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
|
import { syncTime, getSettingInfo, updateSetting } from '@/api/modules/setting';
|
||||||
import Submenu from '@/views/setting/index.vue';
|
import Submenu from '@/views/setting/index.vue';
|
||||||
import router from '@/routers/router';
|
|
||||||
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';
|
||||||
import { useTheme } from '@/hooks/use-theme';
|
import { useTheme } from '@/hooks/use-theme';
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const dialogLoading = ref(false);
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const globalStore = GlobalStore();
|
const globalStore = GlobalStore();
|
||||||
const themeConfig = computed(() => globalStore.themeConfig);
|
const themeConfig = computed(() => globalStore.themeConfig);
|
||||||
const { switchDark } = useTheme();
|
const { switchDark } = useTheme();
|
||||||
|
|
||||||
type FormInstance = InstanceType<typeof ElForm>;
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
const passFormRef = ref<FormInstance>();
|
|
||||||
const passRules = reactive({
|
|
||||||
oldPassword: [Rules.requiredInput],
|
|
||||||
newPassword: [Rules.requiredInput, { min: 6, message: i18n.t('commons.rule.commonPassword'), trigger: 'blur' }],
|
|
||||||
newPasswordComplexity: [Rules.requiredInput, Rules.password],
|
|
||||||
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
|
|
||||||
});
|
|
||||||
const passwordVisiable = ref<boolean>(false);
|
|
||||||
const passForm = reactive({
|
|
||||||
oldPassword: '',
|
|
||||||
newPassword: '',
|
|
||||||
newPasswordComplexity: '',
|
|
||||||
retryPassword: '',
|
|
||||||
});
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
userName: '',
|
userName: '',
|
||||||
password: '',
|
|
||||||
email: '',
|
email: '',
|
||||||
sessionTimeout: 0,
|
sessionTimeout: 0,
|
||||||
localTime: '',
|
localTime: '',
|
||||||
@ -219,7 +147,6 @@ const show = ref();
|
|||||||
const search = async () => {
|
const search = async () => {
|
||||||
const res = await getSettingInfo();
|
const res = await getSettingInfo();
|
||||||
form.userName = res.data.userName;
|
form.userName = res.data.userName;
|
||||||
form.password = '******';
|
|
||||||
form.sessionTimeout = Number(res.data.sessionTimeout);
|
form.sessionTimeout = Number(res.data.sessionTimeout);
|
||||||
form.localTime = res.data.localTime;
|
form.localTime = res.data.localTime;
|
||||||
form.panelName = res.data.panelName;
|
form.panelName = res.data.panelName;
|
||||||
@ -300,47 +227,6 @@ function callback(error: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkPassword(rule: any, value: any, callback: any) {
|
|
||||||
let password = form.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
|
|
||||||
if (password !== passForm.retryPassword) {
|
|
||||||
return callback(new Error(i18n.t('commons.rule.rePassword')));
|
|
||||||
}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
const onChangePassword = async () => {
|
|
||||||
passForm.oldPassword = '';
|
|
||||||
passForm.newPassword = '';
|
|
||||||
passForm.newPasswordComplexity = '';
|
|
||||||
passForm.retryPassword = '';
|
|
||||||
passwordVisiable.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
|
||||||
if (!formEl) return;
|
|
||||||
formEl.validate(async (valid) => {
|
|
||||||
if (!valid) return;
|
|
||||||
let password =
|
|
||||||
form.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
|
|
||||||
if (password === passForm.oldPassword) {
|
|
||||||
ElMessage.error(i18n.t('setting.duplicatePassword'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dialogLoading.value = true;
|
|
||||||
await updatePassword({ oldPassword: passForm.oldPassword, newPassword: password })
|
|
||||||
.then(() => {
|
|
||||||
dialogLoading.value = false;
|
|
||||||
passwordVisiable.value = false;
|
|
||||||
ElMessage.success(i18n.t('commons.msg.operationSuccess'));
|
|
||||||
router.push({ name: 'login', params: { code: '' } });
|
|
||||||
globalStore.setLogStatus(false);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
dialogLoading.value = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSyncTime = async () => {
|
const onSyncTime = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await syncTime()
|
await syncTime()
|
||||||
|
@ -3,93 +3,110 @@
|
|||||||
<Submenu activeName="safe" />
|
<Submenu activeName="safe" />
|
||||||
<el-form :model="form" ref="panelFormRef" v-loading="loading" label-position="left" label-width="160px">
|
<el-form :model="form" ref="panelFormRef" v-loading="loading" label-position="left" label-width="160px">
|
||||||
<el-card style="margin-top: 20px">
|
<el-card style="margin-top: 20px">
|
||||||
<template #header>
|
<LayoutContent :header="$t('setting.safe')">
|
||||||
<div class="card-header">
|
<el-row>
|
||||||
<span>{{ $t('setting.safe') }}</span>
|
<el-col :span="1"><br /></el-col>
|
||||||
</div>
|
<el-col :span="10">
|
||||||
</template>
|
<el-form-item
|
||||||
<el-row>
|
:label="$t('commons.login.password')"
|
||||||
<el-col :span="1"><br /></el-col>
|
:rules="Rules.requiredInput"
|
||||||
<el-col :span="10">
|
prop="password"
|
||||||
<el-form-item
|
|
||||||
:label="$t('setting.expirationTime')"
|
|
||||||
prop="expirationTime"
|
|
||||||
:rules="Rules.requiredInput"
|
|
||||||
>
|
|
||||||
<el-input disabled v-model="form.expirationTime">
|
|
||||||
<template #append>
|
|
||||||
<el-button @click="onChangeExpirationTime" icon="Setting">
|
|
||||||
{{ $t('commons.button.set') }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<div>
|
|
||||||
<span class="input-help" v-if="form.expirationTime !== $t('setting.unSetting')">
|
|
||||||
{{ $t('setting.timeoutHelper', [loadTimeOut()]) }}
|
|
||||||
</span>
|
|
||||||
<span class="input-help" v-else>
|
|
||||||
{{ $t('setting.noneSetting') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('setting.complexity')"
|
|
||||||
prop="complexityVerification"
|
|
||||||
:rules="Rules.requiredSelect"
|
|
||||||
>
|
|
||||||
<el-radio-group
|
|
||||||
style="width: 100%"
|
|
||||||
@change="onSave(panelFormRef, 'ComplexityVerification', form.complexityVerification)"
|
|
||||||
v-model="form.complexityVerification"
|
|
||||||
>
|
>
|
||||||
<el-radio-button label="enable">{{ $t('commons.button.enable') }}</el-radio-button>
|
<el-input type="password" clearable disabled v-model="form.password">
|
||||||
<el-radio-button label="disable">{{ $t('commons.button.disable') }}</el-radio-button>
|
<template #append>
|
||||||
</el-radio-group>
|
<el-button icon="Setting" @click="onChangePassword">
|
||||||
<div>
|
{{ $t('commons.button.set') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('setting.expirationTime')"
|
||||||
|
prop="expirationTime"
|
||||||
|
:rules="Rules.requiredInput"
|
||||||
|
>
|
||||||
|
<el-input disabled v-model="form.expirationTime">
|
||||||
|
<template #append>
|
||||||
|
<el-button @click="onChangeExpirationTime" icon="Setting">
|
||||||
|
{{ $t('commons.button.set') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<div>
|
||||||
|
<span class="input-help" v-if="form.expirationTime !== $t('setting.unSetting')">
|
||||||
|
{{ $t('setting.timeoutHelper', [loadTimeOut()]) }}
|
||||||
|
</span>
|
||||||
|
<span class="input-help" v-else>
|
||||||
|
{{ $t('setting.noneSetting') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('setting.complexity')"
|
||||||
|
prop="complexityVerification"
|
||||||
|
:rules="Rules.requiredSelect"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
@change="
|
||||||
|
onSave(panelFormRef, 'ComplexityVerification', form.complexityVerification)
|
||||||
|
"
|
||||||
|
v-model="form.complexityVerification"
|
||||||
|
active-value="enable"
|
||||||
|
inactive-value="disable"
|
||||||
|
/>
|
||||||
<span class="input-help">
|
<span class="input-help">
|
||||||
{{ $t('setting.complexityHelper') }}
|
{{ $t('setting.complexityHelper') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item
|
||||||
<el-form-item :label="$t('setting.mfa')" prop="securityEntrance" :rules="Rules.requiredSelect">
|
:label="$t('setting.mfa')"
|
||||||
<el-radio-group @change="handleMFA()" v-model="form.mfaStatus">
|
prop="securityEntrance"
|
||||||
<el-radio-button label="enable">{{ $t('commons.button.enable') }}</el-radio-button>
|
:rules="Rules.requiredSelect"
|
||||||
<el-radio-button label="disable">{{ $t('commons.button.disable') }}</el-radio-button>
|
>
|
||||||
</el-radio-group>
|
<el-switch
|
||||||
</el-form-item>
|
@change="handleMFA"
|
||||||
<div v-if="isMFAShow">
|
v-model="form.mfaStatus"
|
||||||
<el-card>
|
active-value="enable"
|
||||||
<ul style="margin-left: 120px; line-height: 24px">
|
inactive-value="disable"
|
||||||
<li>
|
/>
|
||||||
{{ $t('setting.mfaHelper1') }}
|
<span class="input-help">
|
||||||
<ul>
|
{{ $t('setting.mfaHelper') }}
|
||||||
<li>Google Authenticator</li>
|
</span>
|
||||||
<li>Microsoft Authenticator</li>
|
</el-form-item>
|
||||||
<li>1Password</li>
|
<el-form-item v-if="isMFAShow">
|
||||||
<li>LastPass</li>
|
<el-card style="width: 100%">
|
||||||
<li>Authenticator</li>
|
<ul style="line-height: 24px">
|
||||||
</ul>
|
<li>
|
||||||
</li>
|
{{ $t('setting.mfaHelper1') }}
|
||||||
<li>{{ $t('setting.mfaHelper2') }}</li>
|
<ul>
|
||||||
<el-image
|
<li>Google Authenticator</li>
|
||||||
style="margin-left: 15px; width: 100px; height: 100px"
|
<li>Microsoft Authenticator</li>
|
||||||
:src="otp.qrImage"
|
<li>1Password</li>
|
||||||
/>
|
<li>LastPass</li>
|
||||||
<li>{{ $t('setting.mfaHelper3') }}</li>
|
<li>Authenticator</li>
|
||||||
<el-input v-model="mfaCode"></el-input>
|
</ul>
|
||||||
<div style="margin-top: 10px; margin-bottom: 10px; float: right">
|
</li>
|
||||||
<el-button @click="onCancelMfaBind">
|
<li>{{ $t('setting.mfaHelper2') }}</li>
|
||||||
{{ $t('commons.button.cancel') }}
|
<el-image
|
||||||
</el-button>
|
style="margin-left: 15px; width: 100px; height: 100px"
|
||||||
<el-button type="primary" @click="onBind">
|
:src="otp.qrImage"
|
||||||
{{ $t('commons.button.saveAndEnable') }}
|
/>
|
||||||
</el-button>
|
<li>{{ $t('setting.mfaHelper3') }}</li>
|
||||||
</div>
|
<el-input v-model="mfaCode"></el-input>
|
||||||
</ul>
|
<div style="margin-top: 10px; margin-bottom: 10px; float: right">
|
||||||
</el-card>
|
<el-button @click="onCancelMfaBind">
|
||||||
</div>
|
{{ $t('commons.button.cancel') }}
|
||||||
</el-col>
|
</el-button>
|
||||||
</el-row>
|
<el-button type="primary" @click="onBind">
|
||||||
|
{{ $t('commons.button.saveAndEnable') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</el-card>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</LayoutContent>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
@ -114,6 +131,53 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
v-model="passwordVisiable"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:title="$t('setting.changePassword')"
|
||||||
|
width="30%"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
v-loading="dialogLoading"
|
||||||
|
ref="passFormRef"
|
||||||
|
label-width="80px"
|
||||||
|
label-position="left"
|
||||||
|
:model="passForm"
|
||||||
|
:rules="passRules"
|
||||||
|
>
|
||||||
|
<el-form-item :label="$t('setting.oldPassword')" prop="oldPassword">
|
||||||
|
<el-input type="password" show-password clearable v-model="passForm.oldPassword" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
v-if="form.complexityVerification === 'disable'"
|
||||||
|
:label="$t('setting.newPassword')"
|
||||||
|
prop="newPassword"
|
||||||
|
>
|
||||||
|
<el-input type="password" show-password clearable v-model="passForm.newPassword" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
v-if="form.complexityVerification === 'enable'"
|
||||||
|
:label="$t('setting.newPassword')"
|
||||||
|
prop="newPasswordComplexity"
|
||||||
|
>
|
||||||
|
<el-input type="password" show-password clearable v-model="passForm.newPasswordComplexity" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('setting.retryPassword')" prop="retryPassword">
|
||||||
|
<el-input type="password" show-password clearable v-model="passForm.retryPassword" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button :disabled="dialogLoading" @click="passwordVisiable = false">
|
||||||
|
{{ $t('commons.button.cancel') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button :disabled="dialogLoading" type="primary" @click="submitChangePassword(passFormRef)">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -122,20 +186,44 @@ 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 Submenu from '@/views/setting/index.vue';
|
||||||
import { Setting } from '@/api/interface/setting';
|
import { Setting } from '@/api/interface/setting';
|
||||||
import { updateSetting, getMFA, bindMFA, getSettingInfo } from '@/api/modules/setting';
|
import LayoutContent from '@/layout/layout-content.vue';
|
||||||
|
import { updatePassword, updateSetting, getMFA, bindMFA, getSettingInfo } from '@/api/modules/setting';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
import { dateFromat } from '@/utils/util';
|
import { dateFromat } from '@/utils/util';
|
||||||
|
import { GlobalStore } from '@/store';
|
||||||
|
import router from '@/routers';
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
const globalStore = GlobalStore();
|
||||||
|
const passFormRef = ref<FormInstance>();
|
||||||
|
const passRules = reactive({
|
||||||
|
oldPassword: [Rules.requiredInput],
|
||||||
|
newPassword: [
|
||||||
|
Rules.requiredInput,
|
||||||
|
{ min: 6, message: i18n.global.t('commons.rule.commonPassword'), trigger: 'blur' },
|
||||||
|
],
|
||||||
|
newPasswordComplexity: [Rules.requiredInput, Rules.password],
|
||||||
|
retryPassword: [Rules.requiredInput, { validator: checkPassword, trigger: 'blur' }],
|
||||||
|
});
|
||||||
|
const dialogLoading = ref(false);
|
||||||
|
const passwordVisiable = ref<boolean>(false);
|
||||||
|
const passForm = reactive({
|
||||||
|
oldPassword: '',
|
||||||
|
newPassword: '',
|
||||||
|
newPasswordComplexity: '',
|
||||||
|
retryPassword: '',
|
||||||
|
});
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
|
password: '',
|
||||||
serverPort: '',
|
serverPort: '',
|
||||||
securityEntrance: '',
|
securityEntrance: '',
|
||||||
expirationDays: 0,
|
expirationDays: 0,
|
||||||
expirationTime: '',
|
expirationTime: '',
|
||||||
complexityVerification: '',
|
complexityVerification: '',
|
||||||
mfaStatus: '',
|
mfaStatus: 'disable',
|
||||||
mfaSecret: '',
|
mfaSecret: 'disable',
|
||||||
});
|
});
|
||||||
type FormInstance = InstanceType<typeof ElForm>;
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
const timeoutFormRef = ref<FormInstance>();
|
const timeoutFormRef = ref<FormInstance>();
|
||||||
@ -146,6 +234,7 @@ const timeoutForm = reactive({
|
|||||||
|
|
||||||
const search = async () => {
|
const search = async () => {
|
||||||
const res = await getSettingInfo();
|
const res = await getSettingInfo();
|
||||||
|
form.password = '******';
|
||||||
form.securityEntrance = res.data.securityEntrance;
|
form.securityEntrance = res.data.securityEntrance;
|
||||||
form.expirationDays = Number(res.data.expirationDays);
|
form.expirationDays = Number(res.data.expirationDays);
|
||||||
form.expirationTime = res.data.expirationTime;
|
form.expirationTime = res.data.expirationTime;
|
||||||
@ -194,13 +283,56 @@ function callback(error: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkPassword(rule: any, value: any, callback: any) {
|
||||||
|
let password = form.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
|
||||||
|
if (password !== passForm.retryPassword) {
|
||||||
|
return callback(new Error(i18n.global.t('commons.rule.rePassword')));
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangePassword = async () => {
|
||||||
|
passForm.oldPassword = '';
|
||||||
|
passForm.newPassword = '';
|
||||||
|
passForm.newPasswordComplexity = '';
|
||||||
|
passForm.retryPassword = '';
|
||||||
|
passwordVisiable.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitChangePassword = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate(async (valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
let password =
|
||||||
|
form.complexityVerification === 'disable' ? passForm.newPassword : passForm.newPasswordComplexity;
|
||||||
|
if (password === passForm.oldPassword) {
|
||||||
|
ElMessage.error(i18n.global.t('setting.duplicatePassword'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dialogLoading.value = true;
|
||||||
|
await updatePassword({ oldPassword: passForm.oldPassword, newPassword: password })
|
||||||
|
.then(() => {
|
||||||
|
dialogLoading.value = false;
|
||||||
|
passwordVisiable.value = false;
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
router.push({ name: 'login', params: { code: '' } });
|
||||||
|
globalStore.setLogStatus(false);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
dialogLoading.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleMFA = async () => {
|
const handleMFA = async () => {
|
||||||
|
console.log('dawdwda');
|
||||||
if (form.mfaStatus === 'enable') {
|
if (form.mfaStatus === 'enable') {
|
||||||
const res = await getMFA();
|
const res = await getMFA();
|
||||||
otp.secret = res.data.secret;
|
otp.secret = res.data.secret;
|
||||||
otp.qrImage = res.data.qrImage;
|
otp.qrImage = res.data.qrImage;
|
||||||
isMFAShow.value = true;
|
isMFAShow.value = true;
|
||||||
} else {
|
} else {
|
||||||
|
isMFAShow.value = false;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await updateSetting({ key: 'MFAStatus', value: 'disable' })
|
await updateSetting({ key: 'MFAStatus', value: 'disable' })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user