Browse Source

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

pull/3696/head
ssongliu 10 months ago committed by GitHub
parent
commit
61078a24fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 7
      backend/app/dto/setting.go
  2. 13
      backend/app/model/snapshot.go
  3. 1
      backend/init/migration/migrate.go
  4. 17
      backend/init/migration/migrations/v_1_9.go
  5. 1
      frontend/src/api/interface/setting.ts
  6. 41
      frontend/src/views/setting/snapshot/index.vue

7
backend/app/dto/setting.go

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

13
backend/app/model/snapshot.go

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

1
backend/init/migration/migrate.go

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

17
backend/init/migration/migrations/v_1_9.go

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

1
frontend/src/api/interface/setting.ts

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

41
frontend/src/views/setting/snapshot/index.vue

@ -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…
Cancel
Save