mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-27 20:49:03 +08:00
feat: 快照支持本地目录及多选备份账号 (#3693)
This commit is contained in:
parent
e35998a4be
commit
61078a24fd
@ -99,9 +99,10 @@ type SnapshotStatus struct {
|
||||
}
|
||||
|
||||
type SnapshotCreate struct {
|
||||
ID uint `json:"id"`
|
||||
From string `json:"from" validate:"required"`
|
||||
Description string `json:"description" validate:"max=256"`
|
||||
ID uint `json:"id"`
|
||||
From string `json:"from" validate:"required"`
|
||||
DefaultDownload string `json:"defaultDownload" validate:"required"`
|
||||
Description string `json:"description" validate:"max=256"`
|
||||
}
|
||||
type SnapshotRecover struct {
|
||||
IsNew bool `json:"isNew"`
|
||||
|
@ -2,12 +2,13 @@ package model
|
||||
|
||||
type Snapshot struct {
|
||||
BaseModel
|
||||
Name string `json:"name" gorm:"type:varchar(64);not null;unique"`
|
||||
Description string `json:"description" gorm:"type:varchar(256)"`
|
||||
From string `json:"from"`
|
||||
Status string `json:"status" gorm:"type:varchar(64)"`
|
||||
Message string `json:"message" gorm:"type:varchar(256)"`
|
||||
Version string `json:"version" gorm:"type:varchar(256)"`
|
||||
Name string `json:"name" gorm:"type:varchar(64);not null;unique"`
|
||||
Description string `json:"description" gorm:"type:varchar(256)"`
|
||||
From string `json:"from"`
|
||||
DefaultDownload string `json:"defaultDownload" gorm:"type:varchar(64)"`
|
||||
Status string `json:"status" gorm:"type:varchar(64)"`
|
||||
Message string `json:"message" gorm:"type:varchar(256)"`
|
||||
Version string `json:"version" gorm:"type:varchar(256)"`
|
||||
|
||||
InterruptStep string `json:"interruptStep" gorm:"type:varchar(64)"`
|
||||
RecoverStatus string `json:"recoverStatus" gorm:"type:varchar(64)"`
|
||||
|
@ -69,6 +69,7 @@ func Init() {
|
||||
migrations.UpdateOneDriveToken,
|
||||
migrations.UpdateCronjobSpec,
|
||||
migrations.UpdateBackupRecordPath,
|
||||
migrations.UpdateSnapshotRecords,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
@ -415,3 +415,20 @@ var UpdateBackupRecordPath = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateSnapshotRecords = &gormigrate.Migration{
|
||||
ID: "20240124-update-snapshot-records",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.Snapshot{}); err != nil {
|
||||
return err
|
||||
}
|
||||
var snaps []model.Snapshot
|
||||
_ = tx.Find(&snaps).Error
|
||||
for _, snap := range snaps {
|
||||
_ = tx.Model(&model.Snapshot{}).
|
||||
Where("id = ?", snap.ID).
|
||||
Updates(map[string]interface{}{"default_download": snap.From}).Error
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ export namespace Setting {
|
||||
export interface SnapshotCreate {
|
||||
id: number;
|
||||
from: string;
|
||||
defaultDownload: string;
|
||||
description: string;
|
||||
}
|
||||
export interface SnapshotImport {
|
||||
|
@ -111,9 +111,9 @@
|
||||
<el-col :span="22">
|
||||
<el-form-item
|
||||
:label="$t('cronjob.target') + ' ( ' + $t('setting.thirdPartySupport') + ' )'"
|
||||
prop="from"
|
||||
prop="fromAccounts"
|
||||
>
|
||||
<el-select v-model="snapInfo.from" clearable>
|
||||
<el-select multiple @change="changeAccount" v-model="snapInfo.fromAccounts" clearable>
|
||||
<el-option
|
||||
v-for="item in backupOptions"
|
||||
:key="item.label"
|
||||
@ -122,6 +122,16 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('cronjob.default_download_path')" prop="default_download">
|
||||
<el-select v-model="snapInfo.default_download" clearable>
|
||||
<el-option
|
||||
v-for="item in accountOptions"
|
||||
:key="item.label"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.description')" prop="description">
|
||||
<el-input type="textarea" clearable v-model="snapInfo.description" />
|
||||
</el-form-item>
|
||||
@ -180,15 +190,20 @@ const recoverStatusRef = ref();
|
||||
const importRef = ref();
|
||||
const isRecordShow = ref();
|
||||
const backupOptions = ref();
|
||||
const accountOptions = ref();
|
||||
|
||||
type FormInstance = InstanceType<typeof ElForm>;
|
||||
const snapRef = ref<FormInstance>();
|
||||
const rules = reactive({
|
||||
from: [Rules.requiredSelect],
|
||||
fromAccounts: [Rules.requiredSelect],
|
||||
default_download: [Rules.requiredSelect],
|
||||
});
|
||||
|
||||
let snapInfo = reactive<Setting.SnapshotCreate>({
|
||||
id: 0,
|
||||
from: '',
|
||||
default_download: '',
|
||||
fromAccounts: [],
|
||||
description: '',
|
||||
});
|
||||
|
||||
@ -217,6 +232,7 @@ const submitAddSnapshot = (formEl: FormInstance | undefined) => {
|
||||
formEl.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
loading.value = true;
|
||||
snapInfo.from = snapInfo.fromAccounts.join(',');
|
||||
await snapshotCreate(snapInfo)
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
@ -238,10 +254,27 @@ const loadBackups = async () => {
|
||||
const res = await getBackupList();
|
||||
backupOptions.value = [];
|
||||
for (const item of res.data) {
|
||||
if (item.type !== 'LOCAL' && item.id !== 0) {
|
||||
if (item.id !== 0) {
|
||||
backupOptions.value.push({ label: i18n.global.t('setting.' + item.type), value: item.type });
|
||||
}
|
||||
}
|
||||
changeAccount();
|
||||
};
|
||||
|
||||
const changeAccount = async () => {
|
||||
accountOptions.value = [];
|
||||
for (const item of backupOptions.value) {
|
||||
let exit = false;
|
||||
for (const ac of snapInfo.fromAccounts) {
|
||||
if (item.value == ac) {
|
||||
exit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exit) {
|
||||
accountOptions.value.push(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const batchDelete = async (row: Setting.SnapshotInfo | null) => {
|
||||
|
Loading…
Reference in New Issue
Block a user