Browse Source

feat: 增加强制删除 openresty 功能 (#2030)

pull/2039/head
zhengkunwang 1 year ago committed by GitHub
parent
commit
f9bf6b69fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      backend/app/repo/website.go
  2. 5
      backend/app/repo/website_domain.go
  3. 4
      backend/app/service/app_utils.go
  4. 2
      frontend/src/lang/modules/en.ts
  5. 1
      frontend/src/lang/modules/tw.ts
  6. 1
      frontend/src/lang/modules/zh.ts
  7. 95
      frontend/src/views/app-store/installed/check/index.vue
  8. 4
      frontend/src/views/app-store/installed/index.vue

5
backend/app/repo/website.go

@ -26,6 +26,7 @@ type IWebsiteRepo interface {
SaveWithoutCtx(app *model.Website) error
DeleteBy(ctx context.Context, opts ...DBOption) error
Create(ctx context.Context, app *model.Website) error
DeleteAll(ctx context.Context) error
}
func NewIWebsiteRepo() IWebsiteRepo {
@ -131,3 +132,7 @@ func (w *WebsiteRepo) SaveWithoutCtx(website *model.Website) error {
func (w *WebsiteRepo) DeleteBy(ctx context.Context, opts ...DBOption) error {
return getTx(ctx, opts...).Delete(&model.Website{}).Error
}
func (w *WebsiteRepo) DeleteAll(ctx context.Context) error {
return getTx(ctx).Where("1 = 1 ").Delete(&model.Website{}).Error
}

5
backend/app/repo/website_domain.go

@ -21,6 +21,7 @@ type IWebsiteDomainRepo interface {
Create(ctx context.Context, app *model.WebsiteDomain) error
Save(ctx context.Context, app *model.WebsiteDomain) error
DeleteBy(ctx context.Context, opts ...DBOption) error
DeleteAll(ctx context.Context) error
}
func NewIWebsiteDomainRepo() IWebsiteDomainRepo {
@ -85,3 +86,7 @@ func (w WebsiteDomainRepo) Save(ctx context.Context, app *model.WebsiteDomain) e
func (w WebsiteDomainRepo) DeleteBy(ctx context.Context, opts ...DBOption) error {
return getTx(ctx, opts...).Delete(&model.WebsiteDomain{}).Error
}
func (w WebsiteDomainRepo) DeleteAll(ctx context.Context) error {
return getTx(ctx).Where("1 = 1 ").Delete(&model.WebsiteDomain{}).Error
}

4
backend/app/service/app_utils.go

@ -197,6 +197,10 @@ func deleteAppInstall(install model.AppInstall, deleteBackup bool, forceDelete b
if err := deleteLink(ctx, &install, deleteDB, forceDelete); err != nil && !forceDelete {
return err
}
if install.App.Key == constant.AppOpenresty {
_ = websiteRepo.DeleteAll(ctx)
_ = websiteDomainRepo.DeleteAll(ctx)
}
_ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("app"), commonRepo.WithByName(install.App.Key), backupRepo.WithByDetailName(install.Name))
_ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(install.App.Key))
if install.App.Key == constant.AppMysql {

2
frontend/src/lang/modules/en.ts

@ -1238,6 +1238,8 @@ const message = {
backupApp: 'Backup application before upgrade',
backupAppHelper: 'If the upgrade fails, you can use the application backup to roll back',
delete: 'Delete',
openrestyDeleteHelper:
'Forcibly deleting OpenResty will delete all websites, please confirm the risk before operation',
},
website: {
website: 'Website',

1
frontend/src/lang/modules/tw.ts

@ -1179,6 +1179,7 @@ const message = {
backupApp: '升級前備份應用',
backupAppHelper: '升級失敗可以使用應用備份回滾',
delete: '刪除',
openrestyDeleteHelper: '強制刪除 OpenResty 會刪除所有的網站請確認風險後操作',
},
website: {
website: '網站',

1
frontend/src/lang/modules/zh.ts

@ -1179,6 +1179,7 @@ const message = {
backupApp: '升级前备份应用',
backupAppHelper: '升级失败可以使用应用备份回滚',
delete: '删除',
openrestyDeleteHelper: '强制删除 OpenResty 会删除所有的网站请确认风险之后操作',
},
website: {
website: '网站',

95
frontend/src/views/app-store/installed/check/index.vue

@ -1,46 +1,80 @@
<template>
<el-dialog v-model="open" :title="$t('app.checkTitle')" width="50%" :close-on-click-modal="false">
<el-row>
<el-alert
type="warning"
:description="$t('app.deleteHelper', [$t('app.app')])"
center
show-icon
:closable="false"
/>
<el-col :span="20" :offset="2" v-if="open">
<el-alert
type="warning"
:description="$t('app.deleteHelper', [$t('app.app')])"
center
show-icon
:closable="false"
/>
<br />
<el-descriptions border :column="1">
<el-descriptions-item v-for="(item, key) in map" :key="key">
<template #label>
<a href="javascript:void(0);" @click="toPage(item[0])">{{ $t('app.' + item[0]) }}</a>
</template>
<span style="word-break: break-all">
<span class="resources">
{{ map.get(item[0]).toString() }}
</span>
</el-descriptions-item>
</el-descriptions>
<div class="center" v-if="installData.key === 'openresty'">
<el-checkbox v-model="forceDelete" label="true">{{ $t('app.forceDelete') }}</el-checkbox>
<el-alert
v-if="forceDelete"
type="error"
effect="dark"
:description="$t('app.openrestyDeleteHelper')"
center
:closable="false"
/>
</div>
</el-col>
</el-row>
<template #footer v-if="forceDelete">
<span class="dialog-footer">
<el-button @click="open = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button type="primary" @click="onConfirm">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { App } from '@/api/interface/app';
import { InstalledOp } from '@/api/modules/app';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
interface InstallRrops {
interface CheckRrops {
items: App.AppInstallResource[];
installID: Number;
key: string;
}
const installData = ref<InstallRrops>({
const installData = ref<CheckRrops>({
items: [],
installID: 0,
key: '',
});
let open = ref(false);
let map = new Map();
const open = ref(false);
const map = new Map();
const forceDelete = ref(false);
const em = defineEmits(['close']);
const acceptParams = (props: InstallRrops) => {
const acceptParams = (props: CheckRrops) => {
map.clear();
forceDelete.value = false;
installData.value.installID = props.installID;
installData.value.key = props.key;
installData.value.items = [];
installData.value.items = props.items;
installData.value.items.forEach((item) => {
@ -67,7 +101,42 @@ const toPage = (key: string) => {
}
};
const onConfirm = () => {
ElMessageBox.confirm(
i18n.global.t('app.operatorHelper', [i18n.global.t('app.delete')]),
i18n.global.t('app.delete'),
{
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
type: 'info',
},
).then(() => {
const deleteReq = {
operate: 'delete',
installId: Number(installData.value.installID),
deleteBackup: true,
forceDelete: true,
deleteDB: true,
};
InstalledOp(deleteReq).then(() => {
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
open.value = false;
em('close', open);
});
});
};
defineExpose({
acceptParams,
});
</script>
<style scoped>
.resources {
word-break: break-all;
}
.center {
text-align: center;
}
</style>

4
frontend/src/views/app-store/installed/index.vue

@ -255,7 +255,7 @@
</LayoutContent>
<Backups ref="backupRef" @close="search" />
<Uploads ref="uploadRef" />
<AppResources ref="checkRef" />
<AppResources ref="checkRef" @close="search" />
<AppDelete ref="deleteRef" @close="search" />
<AppParams ref="appParamRef" />
<AppUpgrade ref="upgradeRef" @close="search" />
@ -379,7 +379,7 @@ const openOperate = (row: any, op: string) => {
AppInstalledDeleteCheck(row.id).then(async (res) => {
const items = res.data;
if (res.data && res.data.length > 0) {
checkRef.value.acceptParams({ items: items });
checkRef.value.acceptParams({ items: items, key: row.app.key, installID: row.id });
} else {
deleteRef.value.acceptParams(row);
}

Loading…
Cancel
Save