1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 14:08:06 +08:00

feat: 升级增加全局 loading

This commit is contained in:
ssongliu 2023-01-31 15:22:05 +08:00
parent 5100865f7e
commit e83bc0b675
21 changed files with 237 additions and 115 deletions

View File

@ -137,6 +137,11 @@ func (b *BaseApi) SafeEntrance(c *gin.Context) {
helper.SuccessWithData(c, nil) helper.SuccessWithData(c, nil)
} }
// @Tags Auth
// @Summary Check is First login
// @Description 判断是否为首次登录
// @Success 200
// @Router /auth/status [get]
func (b *BaseApi) CheckIsFirstLogin(c *gin.Context) { func (b *BaseApi) CheckIsFirstLogin(c *gin.Context) {
helper.SuccessWithData(c, authService.CheckIsFirst()) helper.SuccessWithData(c, authService.CheckIsFirst())
} }

View File

@ -28,6 +28,16 @@ func (b *BaseApi) GetSettingInfo(c *gin.Context) {
helper.SuccessWithData(c, setting) helper.SuccessWithData(c, setting)
} }
// @Tags System Setting
// @Summary Load system available status
// @Description 获取系统可用状态
// @Success 200
// @Security ApiKeyAuth
// @Router /settings/search/available [get]
func (b *BaseApi) GetSystemAvailable(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
// @Tags System Setting // @Tags System Setting
// @Summary Update system setting // @Summary Update system setting
// @Description 更新系统配置 // @Description 更新系统配置

View File

@ -13,6 +13,7 @@ const (
CodeErrNotFound = 404 CodeErrNotFound = 404
CodePasswordExpired = 405 CodePasswordExpired = 405
CodeAuth = 406 CodeAuth = 406
CodeGlobalLoading = 407
CodeErrInternalServer = 500 CodeErrInternalServer = 500
CodeErrHeader = 406 CodeErrHeader = 406
) )

View File

@ -43,7 +43,7 @@ func (m *monitor) Run() {
itemModel.Memory = memoryInfo.UsedPercent itemModel.Memory = memoryInfo.UsedPercent
if err := global.DB.Create(&itemModel).Error; err != nil { if err := global.DB.Create(&itemModel).Error; err != nil {
global.LOG.Debug("create monitor base failed, err: %v", err) global.LOG.Debugf("Insert basic monitoring data failed, err: %v", err)
} }
ioStat, _ := disk.IOCounters() ioStat, _ := disk.IOCounters()
@ -77,7 +77,7 @@ func (m *monitor) Run() {
itemIO.Time = writeTime itemIO.Time = writeTime
} }
if err := global.DB.Create(&itemIO).Error; err != nil { if err := global.DB.Create(&itemIO).Error; err != nil {
global.LOG.Debug("create monitor io failed, err: %v", err) global.LOG.Debugf("Insert io monitoring data failed, err: %v", err)
} }
} }
@ -96,7 +96,7 @@ func (m *monitor) Run() {
itemNet.Up = float64(v.BytesSent-aheadData.BytesSent) / 1024 / stime itemNet.Up = float64(v.BytesSent-aheadData.BytesSent) / 1024 / stime
itemNet.Down = float64(v.BytesRecv-aheadData.BytesRecv) / 1024 / stime itemNet.Down = float64(v.BytesRecv-aheadData.BytesRecv) / 1024 / stime
if err := global.DB.Create(&itemNet).Error; err != nil { if err := global.DB.Create(&itemNet).Error; err != nil {
global.LOG.Debug("create monitor network failed, err: %v", err) global.LOG.Debugf("Insert network monitoring data failed, err: %v", err)
} }
} }
netStatAll, _ := net.IOCounters(false) netStatAll, _ := net.IOCounters(false)
@ -114,7 +114,7 @@ func (m *monitor) Run() {
itemNet.Up = float64(netStatAll[0].BytesSent-aheadData.BytesSent) / 1024 / stime itemNet.Up = float64(netStatAll[0].BytesSent-aheadData.BytesSent) / 1024 / stime
itemNet.Down = float64(netStatAll[0].BytesRecv-aheadData.BytesRecv) / 1024 / stime itemNet.Down = float64(netStatAll[0].BytesRecv-aheadData.BytesRecv) / 1024 / stime
if err := global.DB.Create(&itemNet).Error; err != nil { if err := global.DB.Create(&itemNet).Error; err != nil {
global.LOG.Debug("create monitor network all failed, err: %v", err) global.LOG.Debugf("Insert network all monitoring data failed, err: %v", err)
} }
} }

View File

@ -67,6 +67,7 @@ func Routers() *gin.Engine {
} }
PrivateGroup := Router.Group("/api/v1") PrivateGroup := Router.Group("/api/v1")
PrivateGroup.Use(middleware.GlobalLoading())
//PrivateGroup.Use(middleware.SafetyAuth()) //PrivateGroup.Use(middleware.SafetyAuth())
{ {
systemRouter.InitBaseRouter(PrivateGroup) systemRouter.InitBaseRouter(PrivateGroup)

View File

@ -0,0 +1,24 @@
package middleware
import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/gin-gonic/gin"
)
func GlobalLoading() gin.HandlerFunc {
return func(c *gin.Context) {
settingRepo := repo.NewISettingRepo()
upgradeSetting, err := settingRepo.Get(settingRepo.WithByKey("SystemVersion"))
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
if upgradeSetting.Value == constant.StatusWaiting {
helper.ErrorWithDetail(c, constant.CodeGlobalLoading, "Upgrading", err)
return
}
c.Next()
}
}

View File

@ -16,6 +16,7 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
baseApi := v1.ApiGroupApp.BaseApi baseApi := v1.ApiGroupApp.BaseApi
{ {
settingRouter.POST("/search", baseApi.GetSettingInfo) settingRouter.POST("/search", baseApi.GetSettingInfo)
settingRouter.GET("/search/available", baseApi.GetSystemAvailable)
settingRouter.POST("/expired/handle", baseApi.HandlePasswordExpired) settingRouter.POST("/expired/handle", baseApi.HandlePasswordExpired)
settingRouter.POST("/update", baseApi.UpdateSetting) settingRouter.POST("/update", baseApi.UpdateSetting)
settingRouter.POST("/port/update", baseApi.UpdatePort) settingRouter.POST("/port/update", baseApi.UpdatePort)

View File

@ -74,7 +74,7 @@ func (c *ConnInfo) Run(shell string) (string, error) {
func (c *ConnInfo) Close() { func (c *ConnInfo) Close() {
if err := c.Client.Close(); err != nil { if err := c.Client.Close(); err != nil {
global.LOG.Error("close ssh client failed, err: %v", err) global.LOG.Errorf("close ssh client failed, err: %v", err)
} }
} }

View File

@ -58,6 +58,15 @@ class RequestHttp {
router.push({ name: 'Expired' }); router.push({ name: 'Expired' });
return data; return data;
} }
if (data.code == ResultEnum.ERRGLOBALLOADDING) {
globalStore.setGlobalLoading(true);
globalStore.setLoadingText(data.message);
return;
} else {
if (globalStore.isLoading) {
globalStore.setGlobalLoading(false);
}
}
if (data.code == ResultEnum.ERRAUTH) { if (data.code == ResultEnum.ERRAUTH) {
return data; return data;
} }

View File

@ -5,6 +5,9 @@ import { Setting } from '../interface/setting';
export const getSettingInfo = () => { export const getSettingInfo = () => {
return http.post<Setting.SettingInfo>(`/settings/search`); return http.post<Setting.SettingInfo>(`/settings/search`);
}; };
export const getSystemAvailable = () => {
return http.get(`/settings/search/available`);
};
export const updateSetting = (param: Setting.SettingUpdate) => { export const updateSetting = (param: Setting.SettingUpdate) => {
return http.post(`/settings/update`, param); return http.post(`/settings/update`, param);

View File

@ -1,5 +1,5 @@
<template> <template>
<Layout> <Layout v-loading="loading" :element-loading-text="loadinText" fullscreen>
<template #menu> <template #menu>
<Menu :panelName="themeConfig.panelName"></Menu> <Menu :panelName="themeConfig.panelName"></Menu>
</template> </template>
@ -12,17 +12,32 @@
import Layout from '@/layout/index.vue'; import Layout from '@/layout/index.vue';
import Footer from './footer/index.vue'; import Footer from './footer/index.vue';
import Menu from './menu/index.vue'; import Menu from './menu/index.vue';
import { onMounted, computed } from 'vue'; import { onMounted, computed, ref, watch, onBeforeUnmount } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { GlobalStore } from '@/store'; import { GlobalStore } from '@/store';
import { useTheme } from '@/hooks/use-theme'; import { useTheme } from '@/hooks/use-theme';
import { getSettingInfo } from '@/api/modules/setting'; import { getSettingInfo, getSystemAvailable } from '@/api/modules/setting';
const i18n = useI18n(); const i18n = useI18n();
const loading = ref(false);
const loadinText = ref();
const globalStore = GlobalStore(); const globalStore = GlobalStore();
const themeConfig = computed(() => globalStore.themeConfig); const themeConfig = computed(() => globalStore.themeConfig);
const { switchDark } = useTheme(); const { switchDark } = useTheme();
let timer: NodeJS.Timer | null = null;
watch(
() => globalStore.isLoading,
() => {
if (globalStore.isLoading) {
loadStatus();
} else {
loading.value = globalStore.isLoading;
}
},
);
const loadDataFromDB = async () => { const loadDataFromDB = async () => {
const res = await getSettingInfo(); const res = await getSettingInfo();
document.title = res.data.panelName; document.title = res.data.panelName;
@ -33,7 +48,33 @@ const loadDataFromDB = async () => {
globalStore.setThemeConfig({ ...themeConfig.value, panelName: res.data.panelName }); globalStore.setThemeConfig({ ...themeConfig.value, panelName: res.data.panelName });
switchDark(); switchDark();
}; };
const loadStatus = async () => {
loading.value = globalStore.isLoading;
loadinText.value = globalStore.loadingText;
if (loading.value) {
timer = setInterval(async () => {
await getSystemAvailable()
.then((res) => {
if (res) {
clearInterval(Number(timer));
timer = null;
}
})
.catch(() => {
clearInterval(Number(timer));
timer = null;
});
}, 1000 * 5);
}
};
onBeforeUnmount(() => {
clearInterval(Number(timer));
timer = null;
});
onMounted(() => { onMounted(() => {
loadStatus();
loadDataFromDB(); loadDataFromDB();
}); });
</script> </script>

View File

@ -6,6 +6,7 @@ export enum ResultEnum {
FORBIDDEN = 403, FORBIDDEN = 403,
EXPIRED = 405, EXPIRED = 405,
ERRAUTH = 406, ERRAUTH = 406,
ERRGLOBALLOADDING = 407,
TIMEOUT = 100000, TIMEOUT = 100000,
TYPE = 'success', TYPE = 'success',
} }

View File

@ -61,6 +61,9 @@ export default {
interval: 'Interval', interval: 'Interval',
title: 'Title', title: 'Title',
}, },
loadingText: {
Upgrading: 'System upgrade, please wait...',
},
msg: { msg: {
delete: 'This operation cannot be rolled back. Do you want to continue', delete: 'This operation cannot be rolled back. Do you want to continue',
deleteTitle: 'Delete', deleteTitle: 'Delete',
@ -706,7 +709,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',
thirdParty: 'Third-party', thirdParty: 'Third-party account',
createBackupAccount: 'Create {0} backup account', 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',
@ -765,7 +768,7 @@ export default {
upgrading: 'Please wait while the upgrade is underway...', upgrading: 'Please wait while the upgrade is underway...',
upgradeHelper: 'The upgrade requires a service restart. Do you want to continue?', upgradeHelper: 'The upgrade requires a service restart. Do you want to continue?',
noUpgrade: 'This is the latest version. You do not need to update it', noUpgrade: 'This is the latest version. You do not need to update it',
newVersion: 'NewVersion', newVersion: 'Latest version',
upgradeCheck: 'Check for updates', upgradeCheck: 'Check for updates',
upgradeNotes: 'Release note', upgradeNotes: 'Release note',
upgradeNow: 'Upgrade now', upgradeNow: 'Upgrade now',

View File

@ -64,6 +64,9 @@ export default {
interval: '耗时', interval: '耗时',
title: '标题', title: '标题',
}, },
loadingText: {
Upgrading: '系统升级中请稍候...',
},
msg: { msg: {
delete: '删除 操作不可回滚是否继续', delete: '删除 操作不可回滚是否继续',
deleteTitle: '删除', deleteTitle: '删除',
@ -722,7 +725,7 @@ export default {
duplicatePassword: '新密码不能与原始密码一致请重新输入', duplicatePassword: '新密码不能与原始密码一致请重新输入',
backup: '备份', backup: '备份',
thirdParty: '第三方', thirdParty: '第三方账号',
createBackupAccount: '添加 {0} 备份账号', createBackupAccount: '添加 {0} 备份账号',
noTypeForCreate: '当前无可创建备份类型', noTypeForCreate: '当前无可创建备份类型',
serverDisk: '服务器磁盘', serverDisk: '服务器磁盘',
@ -762,7 +765,7 @@ export default {
upgrading: '正在升级中请稍候...', upgrading: '正在升级中请稍候...',
upgradeHelper: '升级操作需要重启服务是否继续', upgradeHelper: '升级操作需要重启服务是否继续',
noUpgrade: '当前已是最新版本无需更新', noUpgrade: '当前已是最新版本无需更新',
newVersion: '新版本', newVersion: '新版本',
upgradeCheck: '检查更新', upgradeCheck: '检查更新',
upgradeNotes: '更新内容', upgradeNotes: '更新内容',
upgradeNow: '立即更新', upgradeNow: '立即更新',

View File

@ -3,10 +3,13 @@ import { GlobalState, ThemeConfigProp } from './interface';
import { createPinia } from 'pinia'; import { createPinia } from 'pinia';
import piniaPersistConfig from '@/config/pinia-persist'; import piniaPersistConfig from '@/config/pinia-persist';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
import i18n from '@/lang';
export const GlobalStore = defineStore({ export const GlobalStore = defineStore({
id: 'GlobalState', id: 'GlobalState',
state: (): GlobalState => ({ state: (): GlobalState => ({
isLoading: false,
loadingText: '',
isLogin: false, isLogin: false,
csrfToken: '', csrfToken: '',
language: '', language: '',
@ -22,6 +25,12 @@ export const GlobalStore = defineStore({
setLogStatus(login: boolean) { setLogStatus(login: boolean) {
this.isLogin = login; this.isLogin = login;
}, },
setGlobalLoading(loading: boolean) {
this.isLoading = loading;
},
setLoadingText(text: string) {
this.loadingText = i18n.global.t('commons.loadingText.' + text);
},
setCsrfToken(token: string) { setCsrfToken(token: string) {
this.csrfToken = token; this.csrfToken = token;
}, },

View File

@ -8,6 +8,8 @@ export interface ThemeConfigProp {
} }
export interface GlobalState { export interface GlobalState {
isLoading: boolean;
loadingText: string;
isLogin: boolean; isLogin: boolean;
csrfToken: string; csrfToken: string;
language: string; // zh | en language: string; // zh | en

View File

@ -294,6 +294,9 @@ const loadBackups = async () => {
const res = await getBackupList(); const res = await getBackupList();
backupOptions.value = []; backupOptions.value = [];
for (const item of res.data) { for (const item of res.data) {
if (item.id === 0) {
continue;
}
if (item.type === 'LOCAL') { if (item.type === 'LOCAL') {
localDirID.value = item.id; localDirID.value = item.id;
if (!dialogData.value.rowData!.targetDirID) { if (!dialogData.value.rowData!.targetDirID) {

View File

@ -1,6 +1,13 @@
<template> <template>
<div> <div>
<el-row :gutter="20"> <el-card class="topRouterCard">
<el-radio-group v-model="active">
<el-radio-button class="topRouterButton" size="default" label="monitor">
{{ $t('menu.monitor') }}
</el-radio-button>
</el-radio-group>
</el-card>
<el-row :gutter="20" style="margin-top: 20px">
<el-col :span="24"> <el-col :span="24">
<el-card style="overflow: inherit"> <el-card style="overflow: inherit">
<template #header> <template #header>
@ -117,13 +124,14 @@ import { Monitor } from '@/api/interface/monitor';
import { dateFormatWithoutYear } from '@/utils/util'; import { dateFormatWithoutYear } from '@/utils/util';
import i18n from '@/lang'; import i18n from '@/lang';
const active = ref('monitor');
const zoomStart = ref(); const zoomStart = ref();
const monitorBase = ref(); const monitorBase = ref();
const timeRangeLoad = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]); const timeRangeLoad = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
const timeRangeCpu = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]); const timeRangeCpu = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
const timeRangeMemory = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]); const timeRangeMemory = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
const timeRangeIO = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]); const timeRangeIO = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
const timeRangeNetwork = ref<Array<any>>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]); const timeRangeNetwork = ref<[Date, Date]>([new Date(new Date().setHours(0, 0, 0, 0)), new Date()]);
const networkChoose = ref(); const networkChoose = ref();
const netOptions = ref(); const netOptions = ref();
const shortcuts = [ const shortcuts = [

View File

@ -21,7 +21,7 @@
{{ localData.varsJson['dir'] }} {{ localData.varsJson['dir'] }}
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.table.createdAt')"> <el-form-item :label="$t('commons.table.createdAt')">
{{ dateFromat(0, 0, localData.createdAt) }} {{ dateFormat(0, 0, localData.createdAt) }}
</el-form-item> </el-form-item>
</el-card> </el-card>
</el-col> </el-col>
@ -31,93 +31,7 @@
<LayoutContent :header="$t('setting.thirdParty')" style="margin-top: 20px"> <LayoutContent :header="$t('setting.thirdParty')" style="margin-top: 20px">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-card> <el-card style="height: 265px">
<template #header>
<svg-icon style="font-size: 7px" iconName="p-minio"></svg-icon>
<span style="font-size: 16px; font-weight: 500">&nbsp;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">&nbsp;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> <template #header>
<svg-icon style="font-size: 7px" iconName="p-aws"></svg-icon> <svg-icon style="font-size: 7px" iconName="p-aws"></svg-icon>
<span style="font-size: 16px; font-weight: 500">&nbsp;{{ $t('setting.S3') }}</span> <span style="font-size: 16px; font-weight: 500">&nbsp;{{ $t('setting.S3') }}</span>
@ -145,7 +59,7 @@
{{ s3Data.bucket }} {{ s3Data.bucket }}
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.table.createdAt')"> <el-form-item :label="$t('commons.table.createdAt')">
{{ dateFromat(0, 0, s3Data.createdAt) }} {{ dateFormat(0, 0, s3Data.createdAt) }}
</el-form-item> </el-form-item>
</div> </div>
<el-alert v-else center style="height: 167px; background-color: #e2e4ec" :closable="false"> <el-alert v-else center style="height: 167px; background-color: #e2e4ec" :closable="false">
@ -162,7 +76,93 @@
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-card> <el-card style="height: 265px">
<template #header>
<svg-icon style="font-size: 7px" iconName="p-oss"></svg-icon>
<span style="font-size: 16px; font-weight: 500">&nbsp;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')">
{{ dateFormat(0, 0, ossData.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', '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 style="height: 265px">
<template #header>
<svg-icon style="font-size: 7px" iconName="p-minio"></svg-icon>
<span style="font-size: 16px; font-weight: 500">&nbsp;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')">
{{ dateFormat(0, 0, minioData.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', 'MINIO')"
>
{{ $t('setting.createBackupAccount', ['MINIO']) }}
</el-button>
</el-alert>
</el-card>
</el-col>
<el-col :span="12">
<el-card style="height: 265px">
<template #header> <template #header>
<svg-icon style="font-size: 7px" iconName="p-SFTP"></svg-icon> <svg-icon style="font-size: 7px" iconName="p-SFTP"></svg-icon>
<span style="font-size: 16px; font-weight: 500">&nbsp;SFTP</span> <span style="font-size: 16px; font-weight: 500">&nbsp;SFTP</span>
@ -191,7 +191,7 @@
{{ sftpData.bucket }} {{ sftpData.bucket }}
</el-form-item> </el-form-item>
<el-form-item :label="$t('commons.table.createdAt')"> <el-form-item :label="$t('commons.table.createdAt')">
{{ dateFormatSimple(sftpData.createdAt) }} {{ dateFormatSimple(sftpData.createdAt) }}
</el-form-item> </el-form-item>
</div> </div>
<el-alert v-else center style="height: 167px; background-color: #e2e4ec" :closable="false"> <el-alert v-else center style="height: 167px; background-color: #e2e4ec" :closable="false">
@ -214,7 +214,7 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { dateFormatSimple } from '@/utils/util'; import { dateFormatSimple, dateFormat } from '@/utils/util';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import LayoutContent from '@/layout/layout-content.vue'; import LayoutContent from '@/layout/layout-content.vue';
import { getBackupList, deleteBackup } from '@/api/modules/backup'; import { getBackupList, deleteBackup } from '@/api/modules/backup';

View File

@ -187,8 +187,6 @@ import { updatePassword, updateSetting, getMFA, bindMFA, getSettingInfo } from '
import i18n from '@/lang'; import i18n from '@/lang';
import { Rules } from '@/global/form-rules'; import { Rules } from '@/global/form-rules';
import { dateFormatSimple } from '@/utils/util'; import { dateFormatSimple } from '@/utils/util';
const emit = defineEmits(['search']);
import { GlobalStore } from '@/store'; import { GlobalStore } from '@/store';
import router from '@/routers'; import router from '@/routers';

View File

@ -54,7 +54,7 @@
<el-table-column <el-table-column
prop="createdAt" prop="createdAt"
:label="$t('commons.table.date')" :label="$t('commons.table.date')"
:formatter="dateFromat" :formatter="dateFormat"
show-overflow-tooltip show-overflow-tooltip
/> />
<fu-table-operations <fu-table-operations
@ -102,7 +102,7 @@
import ComplexTable from '@/components/complex-table/index.vue'; import ComplexTable from '@/components/complex-table/index.vue';
import { snapshotCreate, searchSnapshotPage, snapshotDelete } from '@/api/modules/setting'; import { snapshotCreate, searchSnapshotPage, snapshotDelete } from '@/api/modules/setting';
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { dateFromat } from '@/utils/util'; import { dateFormat } from '@/utils/util';
import { useDeleteData } from '@/hooks/use-delete-data'; import { useDeleteData } from '@/hooks/use-delete-data';
import { ElForm } from 'element-plus'; import { ElForm } from 'element-plus';
import { Rules } from '@/global/form-rules'; import { Rules } from '@/global/form-rules';
@ -167,7 +167,7 @@ const loadBackups = async () => {
const res = await getBackupList(); const res = await getBackupList();
backupOptions.value = []; backupOptions.value = [];
for (const item of res.data) { for (const item of res.data) {
if (item.type !== 'LOCAL') { if (item.type !== 'LOCAL' && item.id !== 0) {
backupOptions.value.push({ label: loadBackupName(item.type), value: item.type }); backupOptions.value.push({ label: loadBackupName(item.type), value: item.type });
} }
} }