fix: 升级抽屉样式调整,安装包时间错误问题解决

This commit is contained in:
ssongliu 2023-02-07 15:33:47 +08:00 committed by ssongliu
parent 46be5b7537
commit 1bdc531c7d
21 changed files with 418 additions and 356 deletions

1
.gitignore vendored
View file

@ -23,3 +23,4 @@ build
/pkg/
backend/__debug_bin
cmd/server/__debug_bin
cmd/server/web

View file

@ -75,12 +75,10 @@ type SnapshotInfo struct {
}
type UpgradeInfo struct {
ID int64 `json:"id"`
NewVersion string `json:"newVersion"`
ReleaseNote string `json:"releaseNote"`
CreatedAt string `json:"createdAt"`
}
type Upgrade struct {
Source string `json:"source" validate:"required,oneof=github gitee"`
Version string `json:"version"`
}

View file

@ -2,7 +2,10 @@ package service
import (
"context"
"crypto/tls"
"errors"
"fmt"
"net/http"
"os"
"runtime"
"strconv"
@ -34,27 +37,34 @@ func (u *UpgradeService) SearchUpgrade() (*dto.UpgradeInfo, error) {
if err != nil {
return nil, err
}
infoFromGithub, err := u.loadLatestFromGithub()
if err != nil {
global.LOG.Error(err)
} else {
isNew, err := compareVersion(currentVerion.Value, infoFromGithub.NewVersion)
if !isNew || err != nil {
var releaseInfo dto.UpgradeInfo
isGiteeOK := checkValid("https://gitee.com/wanghe-fit2cloud/1Panel")
if isGiteeOK {
releaseInfo, err = u.loadLatestFromGitee()
if err != nil {
global.LOG.Error(err)
}
}
if len(releaseInfo.NewVersion) == 0 {
isGithubOK := checkValid("https://gitee.com/1Panel-dev/1Panel")
if isGithubOK {
releaseInfo, err = u.loadLatestFromGithub()
if err != nil {
global.LOG.Error(err)
return nil, err
}
}
}
if len(releaseInfo.NewVersion) != 0 {
isNew, err := compareVersion(currentVerion.Value, releaseInfo.NewVersion)
if !isNew && err != nil {
return nil, err
}
return infoFromGithub, nil
return &releaseInfo, nil
}
infoFromGitee, err := u.loadLatestFromGitee()
if err != nil {
global.LOG.Error(err)
return nil, err
}
isNew, err := compareVersion(currentVerion.Value, infoFromGitee.NewVersion)
if !isNew && err != nil {
return nil, err
}
return infoFromGitee, nil
return nil, errors.New("both gitee and github were unavailable")
}
func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
@ -71,9 +81,15 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
}
downloadPath := fmt.Sprintf("https://gitee.com/%s/%s/releases/download/%s/", "wanghe-fit2cloud", "1Panel", req.Version)
if req.Source == "github" {
isGiteeOK := checkValid(downloadPath)
if !isGiteeOK {
downloadPath = fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/", "wanghe-fit2cloud", "1Panel", req.Version)
isGithubOK := checkValid(downloadPath)
if !isGithubOK {
return errors.New("both gitee and github were unavailabl")
}
}
panelName := fmt.Sprintf("1panel-%s-%s", "linux", runtime.GOARCH)
fileName := fmt.Sprintf("1panel-online-installer-%s.tar.gz", req.Version)
_ = settingRepo.Update("SystemStatus", "Upgrading")
@ -174,36 +190,34 @@ func (u *UpgradeService) handleRollback(fileOp files.FileOp, originalDir string,
}
}
func (u *UpgradeService) loadLatestFromGithub() (*dto.UpgradeInfo, error) {
func (u *UpgradeService) loadLatestFromGithub() (dto.UpgradeInfo, error) {
var info dto.UpgradeInfo
client := github.NewClient(nil)
ctx, cancle := context.WithTimeout(context.Background(), 3*time.Second)
defer cancle()
stats, res, err := client.Repositories.GetLatestRelease(ctx, "wanghe-fit2cloud", "1Panel")
if res.StatusCode != 200 || err != nil {
return nil, fmt.Errorf("load upgrade info from github failed, err: %v", err)
return info, fmt.Errorf("load upgrade info from github failed, err: %v", err)
}
info := dto.UpgradeInfo{
NewVersion: string(*stats.Name),
ReleaseNote: string(*stats.Body),
CreatedAt: github.Timestamp(*stats.CreatedAt).Format("2006-01-02 15:04:05"),
}
return &info, nil
info.NewVersion = string(*stats.Name)
info.ReleaseNote = string(*stats.Body)
info.CreatedAt = stats.PublishedAt.Add(8 * time.Hour).Format("2006-01-02 15:04:05")
return info, nil
}
func (u *UpgradeService) loadLatestFromGitee() (*dto.UpgradeInfo, error) {
func (u *UpgradeService) loadLatestFromGitee() (dto.UpgradeInfo, error) {
var info dto.UpgradeInfo
client := gitee.NewAPIClient(gitee.NewConfiguration())
ctx, cancle := context.WithTimeout(context.Background(), 3*time.Second)
defer cancle()
stats, res, err := client.RepositoriesApi.GetV5ReposOwnerRepoReleasesLatest(ctx, "wanghe-fit2cloud", "1Panel", &gitee.GetV5ReposOwnerRepoReleasesLatestOpts{})
if res.StatusCode != 200 || err != nil {
return nil, fmt.Errorf("load upgrade info from gitee failed, err: %v", err)
return info, fmt.Errorf("load upgrade info from gitee failed, err: %v", err)
}
info := dto.UpgradeInfo{
NewVersion: string(stats.Name),
ReleaseNote: string(stats.Body),
CreatedAt: stats.CreatedAt.Format("2006-01-02 15:04:05"),
}
return &info, nil
info.NewVersion = string(stats.Name)
info.ReleaseNote = string(stats.Body)
info.CreatedAt = stats.CreatedAt.Format("2006-01-02 15:04:05")
return info, nil
}
func compareVersion(version, newVersion string) (bool, error) {
@ -245,3 +259,18 @@ func compareVersion(version, newVersion string) (bool, error) {
return false, nil
}
}
func checkValid(addr string) bool {
timeout := time.Duration(2 * time.Second)
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := http.Client{
Transport: tr,
Timeout: timeout,
}
if _, err := client.Get(addr); err != nil {
return false
}
return true
}

View file

@ -4,9 +4,7 @@
declare module 'vue' {
export interface GlobalComponents {
403: typeof import('./src/components/error-message/403.vue')['default']
404: typeof import('./src/components/error-message/404.vue')['default']
500: typeof import('./src/components/error-message/500.vue')['default']
AppLayout: typeof import('./src/components/app-layout/index.vue')['default']
AppStatus: typeof import('./src/components/app-status/index.vue')['default']
BackButton: typeof import('./src/components/back-button/index.vue')['default']

View file

@ -80,8 +80,4 @@ export namespace Setting {
releaseNote: string;
createdAt: string;
}
export interface Upgrade {
source: string;
version: string;
}
}

View file

@ -70,6 +70,6 @@ export const searchSnapshotPage = (param: ReqPage) => {
export const loadUpgradeInfo = () => {
return http.get<Setting.UpgradeInfo>(`/settings/upgrade`);
};
export const upgrade = (param: Setting.Upgrade) => {
return http.post(`/settings/upgrade`, param);
export const upgrade = (version: string) => {
return http.post(`/settings/upgrade`, { version: version });
};

View file

@ -535,7 +535,7 @@ export default {
missBackupAccount: '未能找到备份账号',
syncDate: '同步时间 ',
releaseMemory: '释放内存',
curl: '访问',
curl: '访问 URL',
taskName: '任务名称',
cronSpec: '执行周期',
directory: '备份目录',

View file

@ -1,21 +1,9 @@
import { Layout } from '@/routers/constant';
// 错误页面模块
const errorRouter = {
path: '/error',
component: Layout,
children: [
{
path: '403',
name: '403',
hidden: true,
component: () => import('@/components/error-message/403.vue'),
meta: {
requiresAuth: true,
title: '403页面',
key: '403',
},
},
{
path: '404',
name: '404',
@ -27,17 +15,6 @@ const errorRouter = {
key: '404',
},
},
{
path: '500',
name: '500',
hidden: true,
component: () => import('@/components/error-message/500.vue'),
meta: {
requiresAuth: false,
title: '500页面',
key: '500',
},
},
],
};
export default errorRouter;

View file

@ -1,17 +1,9 @@
<template>
<el-dialog
@close="onClose()"
v-model="newNameVisiable"
:destroy-on-close="true"
:close-on-click-modal="false"
width="30%"
>
<el-drawer v-model="newNameVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<div class="card-header">
<span>{{ $t('container.rename') }}</span>
</div>
<DrawerHeader :header="$t('container.rename')" :back="handleClose" />
</template>
<el-form ref="newNameRef" v-loading="loading" :model="renameForm">
<el-form ref="newNameRef" v-loading="loading" :model="renameForm" label-position="top">
<el-form-item :label="$t('container.newName')" :rules="Rules.requiredInput" prop="newName">
<el-input v-model="renameForm.newName"></el-input>
</el-form-item>
@ -26,7 +18,7 @@
</el-button>
</span>
</template>
</el-dialog>
</el-drawer>
</template>
<script lang="ts" setup>
@ -80,7 +72,8 @@ const acceptParams = (props: DialogProps): void => {
newNameVisiable.value = true;
};
const onClose = async () => {
const handleClose = async () => {
newNameVisiable.value = false;
emit('search');
};

View file

@ -1,11 +1,9 @@
<template>
<el-dialog v-model="loadVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
<el-drawer v-model="loadVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<div class="card-header">
<span>{{ $t('container.importImage') }}</span>
</div>
<DrawerHeader :header="$t('container.importImage')" :back="handleClose" />
</template>
<el-form v-loading="loading" ref="formRef" :model="form" label-width="80px">
<el-form v-loading="loading" ref="formRef" :model="form" label-position="top">
<el-form-item :label="$t('container.path')" :rules="Rules.requiredSelect" prop="path">
<el-input disabled v-model="form.path">
<template #append>
@ -24,7 +22,7 @@
</el-button>
</span>
</template>
</el-dialog>
</el-drawer>
</template>
<script lang="ts" setup>
@ -46,6 +44,9 @@ const acceptParams = () => {
loadVisiable.value = true;
form.path = '';
};
const handleClose = () => {
loadVisiable.value = false;
};
const emit = defineEmits<{ (e: 'search'): void }>();

View file

@ -10,7 +10,7 @@
<el-tag round class="status-content" v-if="form.status === 'Stopped'" type="info">
{{ $t('commons.status.stopped') }}
</el-tag>
<el-tag class="status-content" type="info">{{ $t('app.version') }}: {{ form.version }}</el-tag>
<el-tag class="status-content">{{ $t('app.version') }}: {{ form.version }}</el-tag>
<span v-if="form.status === 'Running'" class="buttons">
<el-button type="primary" @click="onOperator('stop')" link>

View file

@ -25,7 +25,11 @@
:data="data"
>
<el-table-column type="selection" fix />
<el-table-column :label="$t('cronjob.taskName')" prop="name" />
<el-table-column :label="$t('cronjob.taskName')" prop="name">
<template #default="{ row }">
<el-link @click="loadDetail(row)" type="primary">{{ row.name }}</el-link>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.status')" prop="status">
<template #default="{ row }">
<el-button
@ -227,6 +231,14 @@ const loadCopies = (item) => {
}
};
const loadDetail = (row: any) => {
isRecordShow.value = true;
let params = {
rowData: { ...row },
};
dialogRecordRef.value!.acceptParams(params);
};
const buttons = [
{
label: i18n.global.t('commons.button.handle'),
@ -253,11 +265,7 @@ const buttons = [
label: i18n.global.t('cronjob.record'),
icon: 'Clock',
click: (row: Cronjob.CronjobInfo) => {
isRecordShow.value = true;
let params = {
rowData: { ...row },
};
dialogRecordRef.value!.acceptParams(params);
loadDetail(row);
},
},
];

View file

@ -12,7 +12,7 @@
<el-option value="website" :label="$t('cronjob.website')" />
<el-option value="database" :label="$t('cronjob.database')" />
<el-option value="directory" :label="$t('cronjob.directory')" />
<el-option value="curl" :label="$t('cronjob.curl') + ' URL'" />
<el-option value="curl" :label="$t('cronjob.curl')" />
</el-select>
</el-form-item>

View file

@ -7,7 +7,7 @@
<el-tag round class="status-content" type="success">
{{ $t('cronjob.' + dialogData.rowData.type) }}
</el-tag>
<el-tag class="status-content" type="info">
<el-tag class="status-content">
<span
v-if="
dialogData.rowData?.specType.indexOf('N') === -1 ||
@ -53,7 +53,7 @@
</div>
<LayoutContent :title="$t('cronjob.record')" :reload="true">
<template #main>
<template #search>
<el-row :gutter="20">
<el-col :span="6">
<el-date-picker
@ -66,7 +66,20 @@
:end-placeholder="$t('commons.search.timeEnd')"
:shortcuts="shortcuts"
></el-date-picker>
<el-card style="margin-top: 20px">
</el-col>
<el-col :span="18">
<el-select @change="search()" v-model="searchInfo.status">
<el-option :label="$t('cronjob.all')" value="" />
<el-option :label="$t('cronjob.failedRecord')" value="Failed" />
<el-option :label="$t('cronjob.successRecord')" value="Success" />
</el-select>
</el-col>
</el-row>
</template>
<template #main>
<el-row :gutter="20">
<el-col :span="6">
<el-card>
<ul v-infinite-scroll="nextPage" class="infinite-list" style="overflow: auto">
<li
v-for="(item, index) in records"
@ -88,12 +101,7 @@
</el-card>
</el-col>
<el-col :span="18">
<el-select @change="search()" v-model="searchInfo.status">
<el-option :label="$t('cronjob.all')" value="" />
<el-option :label="$t('cronjob.failedRecord')" value="Failed" />
<el-option :label="$t('cronjob.successRecord')" value="Success" />
</el-select>
<el-card style="height: 382px; margin-top: 20px">
<el-card style="height: 362px">
<el-form>
<el-row v-if="hasScript()">
<span>{{ $t('cronjob.shellContent') }}</span>
@ -103,7 +111,7 @@
placeholder="None data"
:indent-with-tab="true"
:tabSize="4"
style="height: 120px; width: 100%; margin-top: 5px"
style="height: 100px; width: 100%; margin-top: 5px"
:lineWrapping="true"
:matchBrackets="true"
theme="cobalt"
@ -442,7 +450,7 @@ defineExpose({
<style lang="scss" scoped>
.infinite-list {
height: 330px;
height: 310px;
padding: 0;
margin: 0;
list-style: none;

View file

@ -3,7 +3,7 @@
<template #header>
<DrawerHeader :header="$t('database.create')" :back="handleClose" />
</template>
<el-form ref="formRef" label-position="top" :model="form" :rules="rules" label-width="80px">
<el-form ref="formRef" label-position="top" :model="form" :rules="rules">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('commons.table.name')" prop="name">

View file

@ -101,56 +101,6 @@
</el-card>
<Setting ref="settingRef" style="margin-top: 20px" />
<el-dialog v-model="changeVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
<template #header>
<div class="card-header">
<span>{{ $t('database.changePassword') }}</span>
</div>
</template>
<el-form>
<el-form v-loading="loading" ref="changeFormRef" :model="changeForm" label-width="80px">
<div v-if="changeForm.operation === 'password'">
<el-form-item :label="$t('commons.login.username')" prop="userName">
<el-input disabled v-model="changeForm.userName"></el-input>
</el-form-item>
<el-form-item
:label="$t('commons.login.password')"
prop="password"
:rules="Rules.requiredInput"
>
<el-input type="password" clearable show-password v-model="changeForm.password"></el-input>
</el-form-item>
</div>
<div v-if="changeForm.operation === 'privilege'">
<el-form-item :label="$t('database.permission')" prop="privilege">
<el-select style="width: 100%" v-model="changeForm.privilege">
<el-option value="localhost" :label="$t('database.permissionLocal')" />
<el-option value="%" :label="$t('database.permissionAll')" />
<el-option value="ip" :label="$t('database.permissionForIP')" />
</el-select>
</el-form-item>
<el-form-item
v-if="changeForm.privilege === 'ip'"
prop="privilegeIPs"
:rules="Rules.requiredInput"
>
<el-input clearable v-model="changeForm.privilegeIPs" />
</el-form-item>
</div>
</el-form>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="changeVisiable = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" @click="submitChangeInfo(changeFormRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-dialog>
<el-dialog
v-model="phpVisiable"
:title="$t('app.checkTitle')"
@ -170,6 +120,7 @@
</template>
</el-dialog>
<PasswordDialog ref="passwordRef" />
<RootPasswordDialog ref="rootPasswordRef" />
<RemoteAccessDialog ref="remoteAccessRef" />
<UploadDialog ref="uploadRef" />
@ -178,8 +129,6 @@
<AppResources ref="checkRef"></AppResources>
<DeleteDialog ref="deleteRef" @search="search" />
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit"></ConfirmDialog>
</div>
</template>
@ -188,28 +137,20 @@ import LayoutContent from '@/layout/layout-content.vue';
import ComplexTable from '@/components/complex-table/index.vue';
import OperateDialog from '@/views/database/mysql/create/index.vue';
import DeleteDialog from '@/views/database/mysql/delete/index.vue';
import RootPasswordDialog from '@/views/database/mysql/password/index.vue';
import PasswordDialog from '@/views/database/mysql/password/index.vue';
import RootPasswordDialog from '@/views/database/mysql/root-password/index.vue';
import RemoteAccessDialog from '@/views/database/mysql/remote/index.vue';
import BackupRecords from '@/views/database/mysql/backup/index.vue';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import UploadDialog from '@/views/database/mysql/upload/index.vue';
import AppResources from '@/views/database/mysql/check/index.vue';
import Setting from '@/views/database/mysql/setting/index.vue';
import AppStatus from '@/components/app-status/index.vue';
import { dateFormat } from '@/utils/util';
import { reactive, ref } from 'vue';
import {
deleteCheckMysqlDB,
loadRemoteAccess,
searchMysqlDBs,
updateMysqlAccess,
updateMysqlDescription,
updateMysqlPassword,
} from '@/api/modules/database';
import { deleteCheckMysqlDB, loadRemoteAccess, searchMysqlDBs, updateMysqlDescription } from '@/api/modules/database';
import i18n from '@/lang';
import { ElForm, ElMessage } from 'element-plus';
import { ElMessage } from 'element-plus';
import { Database } from '@/api/interface/database';
import { Rules } from '@/global/form-rules';
import { App } from '@/api/interface/app';
import { GetAppPort } from '@/api/modules/app';
import router from '@/routers';
@ -270,6 +211,8 @@ const onChangeAccess = async () => {
remoteAccessRef.value!.acceptParams(param);
};
const passwordRef = ref();
const settingRef = ref();
const onSetting = async () => {
isOnSetting.value = true;
@ -281,68 +224,6 @@ const onSetting = async () => {
settingRef.value!.acceptParams(params);
};
const changeVisiable = ref(false);
type FormInstance = InstanceType<typeof ElForm>;
const changeFormRef = ref<FormInstance>();
const changeForm = reactive({
id: 0,
mysqlName: '',
userName: '',
password: '',
operation: '',
privilege: '',
privilegeIPs: '',
value: '',
});
const submitChangeInfo = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let param = {
id: changeForm.id,
value: '',
};
if (changeForm.operation === 'password') {
const res = await deleteCheckMysqlDB(changeForm.id);
if (res.data && res.data.length > 0) {
let params = {
header: i18n.global.t('database.changePassword'),
operationInfo: i18n.global.t('database.changePasswordHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
};
confirmDialogRef.value!.acceptParams(params);
} else {
param.value = changeForm.password;
loading.value = true;
await updateMysqlPassword(param)
.then(() => {
loading.value = false;
search();
changeVisiable.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
});
}
return;
}
param.value = changeForm.privilege;
changeForm.mysqlName = mysqlName.value;
loading.value = true;
await updateMysqlAccess(param)
.then(() => {
loading.value = false;
search();
changeVisiable.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
});
});
};
const search = async () => {
let params = {
page: paginationConfig.currentPage,
@ -382,7 +263,7 @@ const loadDashboardPort = async () => {
const checkExist = (data: App.CheckInstalled) => {
mysqlIsExist.value = data.isExist;
mysqlName.value = data.name;
mysqlStatus.value = 'Failed';
mysqlStatus.value = data.status;
mysqlVersion.value = data.version;
mysqlContainer.value = data.containerName;
if (mysqlIsExist.value) {
@ -410,48 +291,36 @@ const onDelete = async (row: Database.MysqlDBInfo) => {
}
};
const confirmDialogRef = ref();
const onSubmit = async () => {
let param = {
id: changeForm.id,
value: changeForm.password,
};
loading.value = true;
await updateMysqlPassword(param)
.then(() => {
loading.value = false;
search();
changeVisiable.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
});
};
const buttons = [
{
label: i18n.global.t('database.changePassword'),
click: (row: Database.MysqlDBInfo) => {
changeForm.id = row.id;
changeForm.operation = 'password';
changeForm.userName = row.username;
changeForm.password = row.password;
changeVisiable.value = true;
let param = {
id: row.id,
operation: 'password',
username: row.username,
password: row.password,
};
passwordRef.value.acceptParams(param);
},
},
{
label: i18n.global.t('database.permission'),
click: (row: Database.MysqlDBInfo) => {
changeForm.id = row.id;
changeForm.operation = 'privilege';
let param = {
id: row.id,
operation: 'privilege',
privilege: '',
privilegeIPs: '',
password: '',
};
if (row.permission === '%' || row.permission === 'localhost') {
changeForm.privilege = row.permission;
param.privilege = row.permission;
} else {
changeForm.privilegeIPs = row.permission;
changeForm.privilege = 'ip';
param.privilegeIPs = row.permission;
param.privilege = 'ip';
}
changeVisiable.value = true;
passwordRef.value.acceptParams(param);
},
},
{

View file

@ -1,93 +1,174 @@
<template>
<el-dialog v-model="dialogVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
<template #header>
<div class="card-header">
<span>{{ $t('database.rootPassword') }}</span>
</div>
</template>
<el-form v-loading="loading" ref="formRef" :model="form" label-width="80px">
<el-form-item :label="$t('database.rootPassword')" :rules="Rules.requiredInput" prop="password">
<el-input type="password" show-password clearable v-model="form.password" />
</el-form-item>
</el-form>
<div>
<el-drawer v-model="changeVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
<template #header>
<DrawerHeader :header="$t('database.changePassword')" :back="handleClose" />
</template>
<el-form>
<el-form v-loading="loading" ref="changeFormRef" :model="changeForm" label-width="80px">
<div v-if="changeForm.operation === 'password'">
<el-form-item :label="$t('commons.login.username')" prop="userName">
<el-input disabled v-model="changeForm.userName"></el-input>
</el-form-item>
<el-form-item
:label="$t('commons.login.password')"
prop="password"
:rules="Rules.requiredInput"
>
<el-input type="password" clearable show-password v-model="changeForm.password"></el-input>
</el-form-item>
</div>
<div v-if="changeForm.operation === 'privilege'">
<el-form-item :label="$t('database.permission')" prop="privilege">
<el-select style="width: 100%" v-model="changeForm.privilege">
<el-option value="localhost" :label="$t('database.permissionLocal')" />
<el-option value="%" :label="$t('database.permissionAll')" />
<el-option value="ip" :label="$t('database.permissionForIP')" />
</el-select>
</el-form-item>
<el-form-item
v-if="changeForm.privilege === 'ip'"
prop="privilegeIPs"
:rules="Rules.requiredInput"
>
<el-input clearable v-model="changeForm.privilegeIPs" />
</el-form-item>
</div>
</el-form>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="changeVisiable = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="submitChangeInfo(changeFormRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-drawer>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit"></ConfirmDialog>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="dialogVisiable = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { ElForm, ElMessage } from 'element-plus';
import { updateMysqlPassword } from '@/api/modules/database';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { GetAppPassword } from '@/api/modules/app';
import { deleteCheckMysqlDB, updateMysqlAccess, updateMysqlPassword } from '@/api/modules/database';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { Rules } from '@/global/form-rules';
const loading = ref(false);
const dialogVisiable = ref(false);
const form = reactive({
const loading = ref();
const changeVisiable = ref(false);
type FormInstance = InstanceType<typeof ElForm>;
const changeFormRef = ref<FormInstance>();
const changeForm = reactive({
id: 0,
mysqlName: '',
userName: '',
password: '',
operation: '',
privilege: '',
privilegeIPs: '',
value: '',
});
const confirmDialogRef = ref();
type FormInstance = InstanceType<typeof ElForm>;
const formRef = ref<FormInstance>();
interface DialogProps {
id: number;
mysqlName: string;
username: string;
password: string;
operation: string;
privilege: string;
privilegeIPs: string;
value: string;
}
const acceptParams = (params: DialogProps): void => {
changeForm.id = params.id;
changeForm.mysqlName = params.mysqlName;
changeForm.userName = params.username;
changeForm.password = params.password;
changeForm.operation = params.operation;
changeForm.privilege = params.privilege;
changeForm.privilegeIPs = params.privilegeIPs;
changeForm.value = params.value;
console.log(changeForm.password);
changeVisiable.value = true;
};
const emit = defineEmits<{ (e: 'search'): void }>();
const acceptParams = (): void => {
form.password = '';
loadPassword();
dialogVisiable.value = true;
const handleClose = () => {
changeVisiable.value = false;
};
const loadPassword = async () => {
const res = await GetAppPassword('mysql');
form.password = res.data;
const submitChangeInfo = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let param = {
id: changeForm.id,
value: '',
};
if (changeForm.operation === 'password') {
const res = await deleteCheckMysqlDB(changeForm.id);
if (res.data && res.data.length > 0) {
let params = {
header: i18n.global.t('database.changePassword'),
operationInfo: i18n.global.t('database.changePasswordHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
};
confirmDialogRef.value!.acceptParams(params);
} else {
param.value = changeForm.password;
loading.value = true;
await updateMysqlPassword(param)
.then(() => {
loading.value = false;
emit('search');
changeVisiable.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
});
}
return;
}
param.value = changeForm.privilege;
loading.value = true;
await updateMysqlAccess(param)
.then(() => {
loading.value = false;
emit('search');
changeVisiable.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
});
});
};
const onSubmit = async () => {
let param = {
id: 0,
value: form.password,
id: changeForm.id,
value: changeForm.password,
};
loading.value = true;
await updateMysqlPassword(param)
.then(() => {
loading.value = false;
emit('search');
changeVisiable.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
dialogVisiable.value = false;
})
.catch(() => {
loading.value = false;
});
};
const onSave = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let params = {
header: i18n.global.t('database.confChange'),
operationInfo: i18n.global.t('database.restartNowHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
};
confirmDialogRef.value!.acceptParams(params);
});
};
defineExpose({
acceptParams,
});

View file

@ -1,15 +1,17 @@
<template>
<el-dialog v-model="dialogVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
<el-drawer v-model="dialogVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<div class="card-header">
<span>{{ $t('database.remoteAccess') }}</span>
</div>
<DrawerHeader :header="$t('database.remoteAccess')" :back="handleClose" />
</template>
<el-form v-loading="loading" ref="formRef" :model="form" label-width="80px">
<el-form-item :label="$t('database.remoteAccess')" :rules="Rules.requiredInput" prop="privilege">
<el-switch v-model="form.privilege" />
<span class="input-help">{{ $t('database.remoteConnHelper') }}</span>
</el-form-item>
<el-form v-loading="loading" ref="formRef" :model="form" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('database.remoteAccess')" :rules="Rules.requiredInput" prop="privilege">
<el-switch v-model="form.privilege" />
<span class="input-help">{{ $t('database.remoteConnHelper') }}</span>
</el-form-item>
</el-col>
</el-row>
</el-form>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit"></ConfirmDialog>
@ -22,7 +24,7 @@
</el-button>
</span>
</template>
</el-dialog>
</el-drawer>
</template>
<script lang="ts" setup>
@ -32,6 +34,7 @@ import i18n from '@/lang';
import { ElForm, ElMessage } from 'element-plus';
import { updateMysqlAccess } from '@/api/modules/database';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import DrawerHeader from '@/components/drawer-header/index.vue';
const loading = ref(false);
@ -54,6 +57,10 @@ const acceptParams = (prop: DialogProps): void => {
dialogVisiable.value = true;
};
const handleClose = () => {
dialogVisiable.value = false;
};
const onSubmit = async () => {
let param = {
id: 0,

View file

@ -0,0 +1,97 @@
<template>
<el-drawer v-model="dialogVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="30%">
<template #header>
<DrawerHeader :header="$t('database.rootPassword')" :back="handleClose" />
</template>
<el-form v-loading="loading" ref="formRef" :model="form" label-position="top">
<el-form-item :label="$t('database.rootPassword')" :rules="Rules.requiredInput" prop="password">
<el-input type="password" show-password clearable v-model="form.password" />
</el-form-item>
</el-form>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit"></ConfirmDialog>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="dialogVisiable = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-drawer>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { ElForm, ElMessage } from 'element-plus';
import { updateMysqlPassword } from '@/api/modules/database';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { GetAppPassword } from '@/api/modules/app';
import DrawerHeader from '@/components/drawer-header/index.vue';
const loading = ref(false);
const dialogVisiable = ref(false);
const form = reactive({
password: '',
});
const confirmDialogRef = ref();
type FormInstance = InstanceType<typeof ElForm>;
const formRef = ref<FormInstance>();
const acceptParams = (): void => {
form.password = '';
loadPassword();
dialogVisiable.value = true;
};
const handleClose = () => {
dialogVisiable.value = false;
};
const loadPassword = async () => {
const res = await GetAppPassword('mysql');
form.password = res.data;
};
const onSubmit = async () => {
let param = {
id: 0,
value: form.password,
};
loading.value = true;
await updateMysqlPassword(param)
.then(() => {
loading.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
dialogVisiable.value = false;
})
.catch(() => {
loading.value = false;
});
};
const onSave = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let params = {
header: i18n.global.t('database.confChange'),
operationInfo: i18n.global.t('database.restartNowHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
};
confirmDialogRef.value!.acceptParams(params);
});
};
defineExpose({
acceptParams,
});
</script>

View file

@ -35,7 +35,7 @@
</div>
</template>
</LayoutContent>
<el-drawer :key="refresh" v-model="drawerVisiable" size="50%">
<el-drawer :close-on-click-modal="false" :key="refresh" v-model="drawerVisiable" size="50%">
<template #header>
<DrawerHeader :header="$t('setting.upgrade')" :back="handleClose" />
</template>
@ -49,16 +49,13 @@
<el-form-item :label="$t('setting.upgradeNotes')">
<MdEditor style="height: calc(100vh - 330px)" v-model="upgradeInfo.releaseNote" previewOnly />
</el-form-item>
<el-form-item :label="$t('setting.source')">
<el-radio-group v-model="Source">
<el-radio label="gitee">Gitee</el-radio>
<el-radio label="github">GitHub</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onUpgrade">{{ $t('setting.upgradeNow') }}</el-button>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="onUpgrade">{{ $t('setting.upgradeNow') }}</el-button>
</span>
</template>
</el-drawer>
</div>
</template>
@ -75,7 +72,6 @@ import DrawerHeader from '@/components/drawer-header/index.vue';
const version = ref();
const upgradeInfo = ref();
const Source = ref('gitee');
const drawerVisiable = ref();
const refresh = ref();
@ -103,13 +99,20 @@ const handleClose = () => {
};
const onLoadUpgradeInfo = async () => {
const res = await loadUpgradeInfo();
if (!res.data) {
ElMessage.info(i18n.global.t('setting.noUpgrade'));
return;
}
upgradeInfo.value = res.data;
drawerVisiable.value = true;
loading.value = true;
await loadUpgradeInfo()
.then((res) => {
loading.value = false;
if (!res.data) {
ElMessage.info(i18n.global.t('setting.noUpgrade'));
return;
}
upgradeInfo.value = res.data;
drawerVisiable.value = true;
})
.catch(() => {
loading.value = false;
});
};
const onUpgrade = async () => {
ElMessageBox.confirm(i18n.global.t('setting.upgradeHelper', i18n.global.t('setting.upgrade')), {
@ -118,11 +121,7 @@ const onUpgrade = async () => {
type: 'info',
}).then(() => {
loading.value = true;
let param = {
version: upgradeInfo.value.newVersion,
source: Source.value,
};
upgrade(param)
upgrade(upgradeInfo.value.newVersion)
.then(() => {
loading.value = false;
drawerVisiable.value = false;

View file

@ -13,7 +13,7 @@
</el-col>
<el-col :lg="4" :xl="4">
<div class="span-font">
<el-tag type="info">
<el-tag>
{{ $t('website.expireDate') }}:
<span v-if="isEver(props.expireDate)">
{{ $t('website.neverExpire') }}