feat: 快照支持本地目录及多选备份账号 (#3693)

This commit is contained in:
ssongliu 2024-01-25 13:55:11 +08:00 committed by GitHub
parent e35998a4be
commit 61078a24fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 67 additions and 13 deletions

View File

@ -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"`

View File

@ -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)"`

View File

@ -69,6 +69,7 @@ func Init() {
migrations.UpdateOneDriveToken,
migrations.UpdateCronjobSpec,
migrations.UpdateBackupRecordPath,
migrations.UpdateSnapshotRecords,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)

View File

@ -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
},
}

View File

@ -90,6 +90,7 @@ export namespace Setting {
export interface SnapshotCreate {
id: number;
from: string;
defaultDownload: string;
description: string;
}
export interface SnapshotImport {

View File

@ -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) => {