feat: 完成网站上传与恢复功能

This commit is contained in:
ssongliu 2022-12-01 16:21:49 +08:00 committed by ssongliu
parent e66ce1a9f2
commit 0d95cee924
13 changed files with 298 additions and 196 deletions

View File

@ -63,6 +63,24 @@ func (b *BaseApi) BackupWebsite(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
func (b *BaseApi) RecoverWebsiteByUpload(c *gin.Context) {
var req dto.WebSiteRecoverByFile
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := websiteService.RecoverByUpload(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
func (b *BaseApi) RecoverWebsite(c *gin.Context) {
var req dto.WebSiteRecover
if err := c.ShouldBindJSON(&req); err != nil {

View File

@ -57,6 +57,13 @@ type WebSiteRecover struct {
BackupName string `json:"backupName" validate:"required"`
}
type WebSiteRecoverByFile struct {
WebsiteName string `json:"websiteName" validate:"required"`
Type string `json:"type" validate:"required"`
FileDir string `json:"fileDir" validate:"required"`
FileName string `json:"fileName" validate:"required"`
}
type WebSiteDTO struct {
model.WebSite
}

View File

@ -152,7 +152,7 @@ func (u *BackupService) BatchDeleteRecord(ids []uint) error {
}
for _, record := range records {
if record.Source == "LOCAL" {
if err := os.Remove(record.FileDir + record.FileName); err != nil {
if err := os.Remove(record.FileDir + "/" + record.FileName); err != nil {
global.LOG.Errorf("remove file %s failed, err: %v", record.FileDir+record.FileName, err)
}
} else {

View File

@ -34,6 +34,7 @@ type IWebsiteService interface {
GetWebsiteOptions() ([]string, error)
Backup(domain string) error
Recover(req dto.WebSiteRecover) error
RecoverByUpload(req dto.WebSiteRecoverByFile) error
UpdateWebsite(req dto.WebSiteUpdate) error
DeleteWebSite(req dto.WebSiteDel) error
}
@ -149,15 +150,40 @@ func (w WebsiteService) Backup(domain string) error {
return nil
}
func (w WebsiteService) RecoverByUpload(req dto.WebSiteRecoverByFile) error {
if err := handleUnTar(fmt.Sprintf("%s/%s", req.FileDir, req.FileName), req.FileDir); err != nil {
return err
}
tmpDir := fmt.Sprintf("%s/%s", req.FileDir, strings.ReplaceAll(req.FileName, ".tar.gz", ""))
webJson, err := os.ReadFile(fmt.Sprintf("%s/website.json", tmpDir))
if err != nil {
return err
}
var websiteInfo WebSiteInfo
if err := json.Unmarshal(webJson, &websiteInfo); err != nil {
return err
}
if websiteInfo.WebsiteName != req.WebsiteName || websiteInfo.WebsiteType != req.Type {
return errors.New("上传文件与选中网站不匹配,无法恢复")
}
website, err := websiteRepo.GetFirst(websiteRepo.WithByDomain(req.WebsiteName))
if err != nil {
return err
}
if err := handleWebsiteRecover(&website, tmpDir); err != nil {
return err
}
return nil
}
func (w WebsiteService) Recover(req dto.WebSiteRecover) error {
website, err := websiteRepo.GetFirst(websiteRepo.WithByDomain(req.WebsiteName))
if err != nil {
return err
}
app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
if err != nil {
return err
}
if !strings.Contains(req.BackupName, "/") {
return errors.New("error path of request")
}
@ -167,71 +193,9 @@ func (w WebsiteService) Recover(req dto.WebSiteRecover) error {
return err
}
fileDir = fileDir + "/" + fileName
resource, err := appInstallResourceRepo.GetFirst(appInstallResourceRepo.WithAppInstallId(website.AppInstallID))
if err != nil {
return err
}
nginxInfo, err := appInstallRepo.LoadBaseInfoByKey("nginx")
if err != nil {
return err
}
mysqlInfo, err := appInstallRepo.LoadBaseInfoByKey("mysql")
if err != nil {
return err
}
db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId))
if err != nil {
return err
}
src, err := os.OpenFile(fmt.Sprintf("%s/%s.conf", fileDir, website.PrimaryDomain), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775)
if err != nil {
return err
}
defer src.Close()
var out *os.File
nginxConfDir := fmt.Sprintf("%s/nginx/%s/conf/conf.d/%s.conf", constant.AppInstallDir, nginxInfo.Name, website.PrimaryDomain)
if _, err := os.Stat(nginxConfDir); err != nil {
out, err = os.Create(fmt.Sprintf("%s/%s.conf", nginxConfDir, website.PrimaryDomain))
if err != nil {
return err
}
} else {
out, err = os.OpenFile(nginxConfDir, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
}
defer out.Close()
_, _ = io.Copy(out, src)
if website.Type == "deployment" {
cmd := exec.Command("docker", "exec", "-i", mysqlInfo.ContainerName, "mysql", "-uroot", "-p"+mysqlInfo.Password, db.Name)
sql, err := os.OpenFile(fmt.Sprintf("%s/%s.sql", fileDir, website.PrimaryDomain), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
cmd.Stdin = sql
stdout, err := cmd.CombinedOutput()
if err != nil {
return errors.New(string(stdout))
}
appDir := fmt.Sprintf("%s/%s", constant.AppInstallDir, app.App.Key)
if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", fileDir, website.PrimaryDomain), appDir); err != nil {
return err
}
if _, err := compose.Restart(fmt.Sprintf("%s/%s/docker-compose.yml", appDir, app.Name)); err != nil {
return err
}
} else {
appDir := fmt.Sprintf("%s/nginx/%s/www", constant.AppInstallDir, nginxInfo.Name)
if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", fileDir, website.PrimaryDomain), appDir); err != nil {
return err
}
}
cmd := exec.Command("docker", "exec", "-i", nginxInfo.ContainerName, "nginx", "-s", "reload")
stdout, err := cmd.CombinedOutput()
if err != nil {
return errors.New(string(stdout))
if err := handleWebsiteRecover(&website, fileDir); err != nil {
return err
}
return nil
}
@ -534,26 +498,6 @@ func handleWebsiteBackup(backupType, baseDir, backupDir, domain, backupName stri
if err != nil {
return err
}
app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
if err != nil {
return err
}
resource, err := appInstallResourceRepo.GetFirst(appInstallResourceRepo.WithAppInstallId(website.AppInstallID))
if err != nil {
return err
}
mysqlInfo, err := appInstallRepo.LoadBaseInfoByKey(resource.Key)
if err != nil {
return err
}
nginxInfo, err := appInstallRepo.LoadBaseInfoByKey("nginx")
if err != nil {
return err
}
db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId))
if err != nil {
return err
}
tmpDir := fmt.Sprintf("%s/%s/%s", baseDir, backupDir, backupName)
if _, err := os.Stat(tmpDir); err != nil && os.IsNotExist(err) {
@ -563,21 +507,28 @@ func handleWebsiteBackup(backupType, baseDir, backupDir, domain, backupName stri
}
}
}
if err := saveNginxConf(nginxInfo.Name, website.PrimaryDomain, tmpDir); err != nil {
return err
}
if err := saveWebsiteJson(&website, tmpDir); err != nil {
return err
}
if website.Type == "deployment" {
dbFile := fmt.Sprintf("%s/%s.sql", tmpDir, website.PrimaryDomain)
outfile, _ := os.OpenFile(dbFile, os.O_RDWR|os.O_CREATE, 0755)
cmd := exec.Command("docker", "exec", mysqlInfo.ContainerName, "mysqldump", "-uroot", "-p"+mysqlInfo.Password, db.Name)
cmd.Stdout = outfile
_ = cmd.Run()
_ = cmd.Wait()
nginxInfo, err := appInstallRepo.LoadBaseInfoByKey("nginx")
if err != nil {
return err
}
nginxConfFile := fmt.Sprintf("%s/nginx/%s/conf/conf.d/%s.conf", constant.AppInstallDir, nginxInfo.Name, website.PrimaryDomain)
if err := copyConf(nginxConfFile, fmt.Sprintf("%s/%s.conf", tmpDir, website.PrimaryDomain)); err != nil {
return err
}
if website.Type == "deployment" {
if err := mysqlOpration(&website, "backup", tmpDir); err != nil {
return err
}
app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
if err != nil {
return err
}
websiteDir := fmt.Sprintf("%s/%s/%s", constant.AppInstallDir, app.App.Key, app.Name)
if err := handleTar(websiteDir, tmpDir, fmt.Sprintf("%s.web.tar.gz", website.PrimaryDomain), ""); err != nil {
return err
@ -612,6 +563,85 @@ func handleWebsiteBackup(backupType, baseDir, backupDir, domain, backupName stri
return nil
}
func handleWebsiteRecover(website *model.WebSite, fileDir string) error {
nginxInfo, err := appInstallRepo.LoadBaseInfoByKey("nginx")
if err != nil {
return err
}
nginxConfFile := fmt.Sprintf("%s/nginx/%s/conf/conf.d/%s.conf", constant.AppInstallDir, nginxInfo.Name, website.PrimaryDomain)
if err := copyConf(fmt.Sprintf("%s/%s.conf", fileDir, website.PrimaryDomain), nginxConfFile); err != nil {
return err
}
if website.Type == "deployment" {
if err := mysqlOpration(website, "recover", fileDir); err != nil {
return err
}
app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID))
if err != nil {
return err
}
appDir := fmt.Sprintf("%s/%s", constant.AppInstallDir, app.App.Key)
if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", fileDir, website.PrimaryDomain), appDir); err != nil {
return err
}
if _, err := compose.Restart(fmt.Sprintf("%s/%s/docker-compose.yml", appDir, app.Name)); err != nil {
return err
}
} else {
appDir := fmt.Sprintf("%s/nginx/%s/www", constant.AppInstallDir, nginxInfo.Name)
if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", fileDir, website.PrimaryDomain), appDir); err != nil {
return err
}
}
cmd := exec.Command("docker", "exec", "-i", nginxInfo.ContainerName, "nginx", "-s", "reload")
stdout, err := cmd.CombinedOutput()
if err != nil {
return errors.New(string(stdout))
}
_ = os.RemoveAll(fileDir)
return nil
}
func mysqlOpration(website *model.WebSite, operation, filePath string) error {
mysqlInfo, err := appInstallRepo.LoadBaseInfoByKey("mysql")
if err != nil {
return err
}
resource, err := appInstallResourceRepo.GetFirst(appInstallResourceRepo.WithAppInstallId(website.AppInstallID))
if err != nil {
return err
}
db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId))
if err != nil {
return err
}
if operation == "backup" {
dbFile := fmt.Sprintf("%s/%s.sql", filePath, website.PrimaryDomain)
outfile, _ := os.OpenFile(dbFile, os.O_RDWR|os.O_CREATE, 0755)
defer outfile.Close()
cmd := exec.Command("docker", "exec", mysqlInfo.ContainerName, "mysqldump", "-uroot", "-p"+mysqlInfo.Password, db.Name)
cmd.Stdout = outfile
_ = cmd.Run()
_ = cmd.Wait()
return nil
}
cmd := exec.Command("docker", "exec", "-i", mysqlInfo.ContainerName, "mysql", "-uroot", "-p"+mysqlInfo.Password, db.Name)
sqlfile, err := os.Open(fmt.Sprintf("%s/%s.sql", filePath, website.PrimaryDomain))
if err != nil {
return err
}
defer sqlfile.Close()
cmd.Stdin = sqlfile
stdout, err := cmd.CombinedOutput()
if err != nil {
return errors.New(string(stdout))
}
return nil
}
func saveWebsiteJson(website *model.WebSite, tmpDir string) error {
var WebSiteInfo WebSiteInfo
WebSiteInfo.WebsiteType = website.Type
@ -629,19 +659,20 @@ func saveWebsiteJson(website *model.WebSite, tmpDir string) error {
return nil
}
func saveNginxConf(nginxName, websiteDomain, tmpDir string) error {
nginxConfFile := fmt.Sprintf("%s/nginx/%s/conf/conf.d/%s.conf", constant.AppInstallDir, nginxName, websiteDomain)
src, err := os.OpenFile(nginxConfFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775)
func copyConf(srcPath, dstPath string) error {
if _, err := os.Stat(srcPath); err != nil {
return err
}
src, err := os.OpenFile(srcPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0775)
if err != nil {
return err
}
defer src.Close()
out, err := os.Create(fmt.Sprintf("%s/%s.conf", tmpDir, websiteDomain))
out, err := os.Create(dstPath)
if err != nil {
return err
}
defer out.Close()
_, _ = io.Copy(out, src)
return nil
}

View File

@ -131,7 +131,7 @@ var AddTableBackupAccount = &gormigrate.Migration{
}
item := &model.BackupAccount{
Type: "LOCAL",
Vars: "{\"dir\":\"/opt/1Panel/backup\"}",
Vars: "{\"dir\":\"/opt/1Panel/data/backup\"}",
}
if err := tx.Create(item).Error; err != nil {
return err

View File

@ -19,6 +19,7 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) {
groupRouter.GET("/options", baseApi.GetWebsiteOptions)
groupRouter.POST("/backup/:domain", baseApi.BackupWebsite)
groupRouter.POST("/recover", baseApi.RecoverWebsite)
groupRouter.POST("/recover/byupload", baseApi.RecoverWebsiteByUpload)
groupRouter.POST("/update", baseApi.UpdateWebSite)
groupRouter.GET("/:id", baseApi.GetWebSite)
groupRouter.GET("/:id/nginx", baseApi.GetWebSiteNginx)

View File

@ -43,6 +43,12 @@ export namespace WebSite {
type: string;
backupName: string;
}
export interface WebsiteRecoverByUpload {
websiteName: string;
type: string;
fileDir: string;
fileName: string;
}
export interface WebSiteDel {
id: number;

View File

@ -17,6 +17,9 @@ export const BackupWebsite = (id: number) => {
export const RecoverWebsite = (req: WebSite.WebSiteRecover) => {
return http.post(`/websites/recover`, req);
};
export const RecoverWebsiteByUpload = (req: WebSite.WebsiteRecoverByUpload) => {
return http.post(`/websites/recover/byupload`, req);
};
export const UpdateWebsite = (req: WebSite.WebSiteUpdateReq) => {
return http.post<any>(`/websites/update`, req);

View File

@ -695,6 +695,9 @@ export default {
author: 'author',
source: 'source',
sync: 'sync',
supportUpType: '.tar.gz files are supported only',
zipFormat:
'.tar.gz compressed package structure: test.tar.gz compressed package must contain the website.json file',
appName: 'App Name',
status: 'status',
container: 'Container',

View File

@ -739,6 +739,8 @@ export default {
type: '类型',
static: '静态网站',
deployment: '反向代理',
supportUpType: '仅支持 tar.gz 文件',
zipFormat: 'tar.gz 压缩包结构test.tar.gz 压缩包内必需包含 website.json 文件',
proxy: '反向代理',
alias: '代号',
remark: '备注',

View File

@ -6,7 +6,13 @@
<span>{{ $t('database.backup') }} - {{ websiteName }}</span>
</div>
</template>
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" @search="search" :data="data">
<ComplexTable
v-loading="loading"
:pagination-config="paginationConfig"
v-model:selects="selects"
@search="search"
:data="data"
>
<template #toolbar>
<el-button type="primary" @click="onBackup()">
{{ $t('database.backup') }}
@ -43,6 +49,7 @@ import { Backup } from '@/api/interface/backup';
import { BackupWebsite, RecoverWebsite } from '@/api/modules/website';
const selects = ref<any>([]);
const loading = ref(false);
const data = ref();
const paginationConfig = reactive({
@ -88,14 +95,28 @@ const onRecover = async (row: Backup.RecordInfo) => {
type: websiteType.value,
backupName: row.fileDir + '/' + row.fileName,
};
await RecoverWebsite(params);
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
loading.value = true;
await RecoverWebsite(params)
.then(() => {
loading.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.finally(() => {
loading.value = false;
});
};
const onBackup = async () => {
await BackupWebsite(websiteName.value);
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
search();
loading.value = true;
await BackupWebsite(websiteName.value)
.then(() => {
loading.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
search();
})
.finally(() => {
loading.value = false;
});
};
const onDownload = async (row: Backup.RecordInfo) => {

View File

@ -138,8 +138,8 @@ const buttons = [
label: i18n.global.t('database.loadBackup'),
click: (row: WebSite.WebSite) => {
let params = {
mysqlName: 'test',
dbName: row.primaryDomain,
websiteName: row.primaryDomain,
websiteType: row.type,
};
uploadRef.value!.acceptParams(params);
},

View File

@ -1,64 +1,66 @@
<template>
<div>
<div :v-loading="loading">
<el-dialog v-model="upVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="70%">
<template #header>
<div class="card-header">
<span>{{ $t('commons.button.import') }}</span>
</div>
</template>
<el-upload
ref="uploadRef"
:on-change="fileOnChange"
:before-upload="beforeAvatarUpload"
class="upload-demo"
:auto-upload="false"
>
<template #trigger>
<el-button type="primary" plain>{{ $t('database.selectFile') }}</el-button>
</template>
<el-button style="margin-left: 10px" icon="Upload" @click="onSubmit">
{{ $t('commons.button.upload') }}
</el-button>
</el-upload>
<div style="margin-left: 10px">
<span class="input-help">{{ $t('database.supportUpType') }}</span>
<span class="input-help">
{{ $t('database.zipFormat') }}
</span>
</div>
<el-divider />
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data">
<template #toolbar>
<el-button
style="margin-left: 10px"
type="danger"
plain
:disabled="selects.length === 0"
@click="onBatchDelete(null)"
>
{{ $t('commons.button.delete') }}
<div v-loading="loading">
<el-upload
ref="uploadRef"
:on-change="fileOnChange"
:before-upload="beforeAvatarUpload"
class="upload-demo"
:auto-upload="false"
>
<template #trigger>
<el-button type="primary" plain>{{ $t('database.selectFile') }}</el-button>
</template>
<el-button style="margin-left: 10px" icon="Upload" @click="onSubmit">
{{ $t('commons.button.upload') }}
</el-button>
</template>
<el-table-column type="selection" fix />
<el-table-column :label="$t('commons.table.name')" show-overflow-tooltip prop="name" />
<el-table-column :label="$t('file.size')" prop="size">
<template #default="{ row }">
{{ computeSize(row.size) }}
</el-upload>
<div style="margin-left: 10px">
<span class="input-help">{{ $t('website.supportUpType') }}</span>
<span class="input-help">
{{ $t('website.zipFormat') }}
</span>
</div>
<el-divider />
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data">
<template #toolbar>
<el-button
style="margin-left: 10px"
type="danger"
plain
:disabled="selects.length === 0"
@click="onBatchDelete(null)"
>
{{ $t('commons.button.delete') }}
</el-button>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.createdAt')" min-width="80" fix>
<template #default="{ row }">
{{ dateFromat(0, 0, row.modTime) }}
</template>
</el-table-column>
<fu-table-operations
width="300px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
<el-table-column type="selection" fix />
<el-table-column :label="$t('commons.table.name')" show-overflow-tooltip prop="name" />
<el-table-column :label="$t('file.size')" prop="size">
<template #default="{ row }">
{{ computeSize(row.size) }}
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.createdAt')" min-width="80" fix>
<template #default="{ row }">
{{ dateFromat(0, 0, row.modTime) }}
</template>
</el-table-column>
<fu-table-operations
width="300px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
</div>
</el-dialog>
</div>
</template>
@ -68,14 +70,15 @@ import ComplexTable from '@/components/complex-table/index.vue';
import { reactive, ref } from 'vue';
import { computeSize, dateFromat } from '@/utils/util';
import { useDeleteData } from '@/hooks/use-delete-data';
import { recoverByUpload } from '@/api/modules/database';
import i18n from '@/lang';
import { ElMessage, UploadFile, UploadFiles, UploadInstance, UploadProps } from 'element-plus';
import { File } from '@/api/interface/file';
import { BatchDeleteFile, GetFilesList, UploadFileData } from '@/api/modules/files';
import { RecoverWebsiteByUpload } from '@/api/modules/website';
const selects = ref<any>([]);
const baseDir = '/opt/1Panel/data/uploads/website/';
const baseDir = ref();
const loading = ref(false);
const data = ref();
const paginationConfig = reactive({
@ -85,16 +88,18 @@ const paginationConfig = reactive({
});
const upVisiable = ref(false);
const mysqlName = ref();
const dbName = ref();
const websiteName = ref();
const websiteType = ref();
interface DialogProps {
mysqlName: string;
dbName: string;
websiteName: string;
websiteType: string;
}
const acceptParams = (params: DialogProps): void => {
mysqlName.value = params.mysqlName;
dbName.value = params.dbName;
websiteName.value = params.websiteName;
websiteType.value = params.websiteType;
upVisiable.value = true;
baseDir.value = '/opt/1Panel/data/uploads/website/' + websiteName.value;
search();
};
@ -102,7 +107,7 @@ const search = async () => {
let params = {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
path: baseDir,
path: baseDir.value,
expand: true,
};
const res = await GetFilesList(params);
@ -112,30 +117,29 @@ const search = async () => {
const onRecover = async (row: File.File) => {
let params = {
mysqlName: mysqlName.value,
dbName: dbName.value,
fileDir: baseDir,
websiteName: websiteName.value,
type: websiteType.value,
fileDir: baseDir.value,
fileName: row.name,
};
await recoverByUpload(params);
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
loading.value = true;
await RecoverWebsiteByUpload(params)
.then(() => {
loading.value = false;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
})
.finally(() => {
loading.value = false;
});
};
const uploaderFiles = ref<UploadFiles>([]);
const uploadRef = ref<UploadInstance>();
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
if (
rawFile.name.endsWith('.sql') ||
rawFile.name.endsWith('.gz') ||
rawFile.name.endsWith('.zip') ||
rawFile.name.endsWith('.tgz')
) {
if (rawFile.name.endsWith('.tar.gz')) {
ElMessage.error(i18n.global.t('database.unSupportType'));
return false;
} else if (rawFile.size / 1024 / 1024 > 10) {
ElMessage.error(i18n.global.t('database.unSupportSize'));
return false;
}
return true;
};
@ -156,21 +160,27 @@ const onSubmit = () => {
if (uploaderFiles.value[0]!.raw != undefined) {
formData.append('file', uploaderFiles.value[0]!.raw);
}
formData.append('path', baseDir);
UploadFileData(formData, {}).then(() => {
ElMessage.success(i18n.global.t('file.uploadSuccess'));
handleClose();
search();
});
formData.append('path', baseDir.value + '/');
loading.value = true;
UploadFileData(formData, {})
.then(() => {
loading.value = false;
ElMessage.success(i18n.global.t('file.uploadSuccess'));
handleClose();
search();
})
.finally(() => {
loading.value = false;
});
};
const onBatchDelete = async (row: File.File | null) => {
let files: Array<string> = [];
if (row) {
files.push(baseDir + row.name);
files.push(baseDir.value + '/' + row.name);
} else {
selects.value.forEach((item: File.File) => {
files.push(baseDir + item.name);
files.push(baseDir.value + '/' + item.name);
});
}
await useDeleteData(BatchDeleteFile, { isDir: false, paths: files }, 'commons.msg.delete', true);