mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2024-11-24 11:09:16 +08:00
fix: 删除应用增加提示
This commit is contained in:
parent
098b735c7a
commit
c61e2cb191
@ -53,6 +53,22 @@ func (b *BaseApi) CheckAppInstalled(c *gin.Context) {
|
||||
helper.SuccessWithData(c, checkData)
|
||||
}
|
||||
|
||||
func (b *BaseApi) DeleteCheck(c *gin.Context) {
|
||||
|
||||
appInstallId, err := helper.GetIntParamByKey(c, "appInstallId")
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
|
||||
return
|
||||
}
|
||||
|
||||
checkData, err := appInstallService.DeleteCheck(appInstallId)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, checkData)
|
||||
}
|
||||
|
||||
func (b *BaseApi) SyncInstalled(c *gin.Context) {
|
||||
if err := appInstallService.SyncAll(); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
|
@ -177,3 +177,8 @@ type AppFormFields struct {
|
||||
Default string `json:"default"`
|
||||
EnvKey string `json:"env_variable"`
|
||||
}
|
||||
|
||||
type AppResource struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
@ -17,6 +17,12 @@ func (a AppInstallResourceRpo) WithAppInstallId(appInstallId uint) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (a AppInstallResourceRpo) WithLinkId(linkId uint) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("link_id = ?", linkId)
|
||||
}
|
||||
}
|
||||
|
||||
func (a AppInstallResourceRpo) GetBy(opts ...DBOption) ([]model.AppInstallResource, error) {
|
||||
db := global.DB.Model(&model.AppInstallResource{})
|
||||
var resources []model.AppInstallResource
|
||||
|
@ -295,6 +295,58 @@ func (a AppInstallService) ChangeAppPort(req dto.PortUpdate) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AppInstallService) DeleteCheck(installId uint) ([]dto.AppResource, error) {
|
||||
var res []dto.AppResource
|
||||
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app, err := appRepo.GetFirst(commonRepo.WithByID(appInstall.AppId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if app.Type == "website" {
|
||||
websites, _ := websiteRepo.GetBy(websiteRepo.WithAppInstallId(appInstall.ID))
|
||||
for _, website := range websites {
|
||||
res = append(res, dto.AppResource{
|
||||
Type: "website",
|
||||
Name: website.PrimaryDomain,
|
||||
})
|
||||
}
|
||||
}
|
||||
if app.Key == "nginx" {
|
||||
websites, _ := websiteRepo.GetBy()
|
||||
for _, website := range websites {
|
||||
res = append(res, dto.AppResource{
|
||||
Type: "website",
|
||||
Name: website.PrimaryDomain,
|
||||
})
|
||||
}
|
||||
}
|
||||
if app.Type == "runtime" {
|
||||
resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithLinkId(appInstall.ID))
|
||||
for _, resource := range resources {
|
||||
linkInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(resource.AppInstallId))
|
||||
res = append(res, dto.AppResource{
|
||||
Type: "app",
|
||||
Name: linkInstall.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if app.Key == "mysql" {
|
||||
databases, _ := mysqlRepo.List()
|
||||
for _, database := range databases {
|
||||
res = append(res, dto.AppResource{
|
||||
Type: "database",
|
||||
Name: database.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func syncById(installId uint) error {
|
||||
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId))
|
||||
if err != nil {
|
||||
|
@ -175,6 +175,10 @@ func deleteAppInstall(ctx context.Context, install model.AppInstall) error {
|
||||
if err := deleteLink(ctx, &install); err != nil {
|
||||
return err
|
||||
}
|
||||
backups, _ := appInstallBackupRepo.GetBy(appInstallBackupRepo.WithAppInstallID(install.ID))
|
||||
for _, backup := range backups {
|
||||
_ = op.DeleteDir(backup.Path)
|
||||
}
|
||||
if err := appInstallBackupRepo.Delete(ctx, appInstallBackupRepo.WithAppInstallID(install.ID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) {
|
||||
appRouter.POST("/install", baseApi.InstallApp)
|
||||
appRouter.GET("/installed/:appInstallId/versions", baseApi.GetUpdateVersions)
|
||||
appRouter.GET("/installed/check/:key", baseApi.CheckAppInstalled)
|
||||
appRouter.GET("/installed/delete/check/:appInstallId", baseApi.DeleteCheck)
|
||||
appRouter.POST("/installed", baseApi.SearchAppInstalled)
|
||||
appRouter.POST("/installed/op", baseApi.OperateInstalled)
|
||||
appRouter.POST("/installed/sync", baseApi.SyncInstalled)
|
||||
|
@ -98,6 +98,11 @@ export namespace App {
|
||||
containerName: string;
|
||||
}
|
||||
|
||||
export interface AppInstallResource {
|
||||
type: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface AppInstalledOp {
|
||||
installId: number;
|
||||
operate: string;
|
||||
|
@ -34,6 +34,10 @@ export const CheckAppInstalled = (key: string) => {
|
||||
return http.get<App.CheckInstalled>(`apps/installed/check/${key}`);
|
||||
};
|
||||
|
||||
export const AppInstalledDeleteCheck = (appInstallId: number) => {
|
||||
return http.get<App.AppInstallResource[]>(`apps/installed/delete/check/${appInstallId}`);
|
||||
};
|
||||
|
||||
export const GetAppInstalled = (search: App.AppInstalledSearch) => {
|
||||
return http.post<App.AppInstalled[]>('apps/installed', search);
|
||||
};
|
||||
|
@ -3,31 +3,31 @@
|
||||
<div class="app-content" v-if="data.isExist">
|
||||
<el-card class="app-card" v-loading="loading">
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1">
|
||||
<el-col :lg="2" :xl="1">
|
||||
<div>
|
||||
<el-tag effect="dark" type="success">{{ data.app }}</el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="2">
|
||||
<el-col :lg="4" :xl="2">
|
||||
<div>
|
||||
{{ $t('app.version') }}:
|
||||
<el-tag type="info">{{ data.version }}</el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="2">
|
||||
<el-col :lg="4" :xl="2">
|
||||
<div>
|
||||
{{ $t('commons.table.status') }}:
|
||||
<el-tag type="success">{{ data.status }}</el-tag>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="2">
|
||||
<el-col :lg="8" :xl="4">
|
||||
<div>
|
||||
{{ $t('website.lastBackupAt') }}:
|
||||
<el-tag v-if="data.lastBackupAt != ''" type="info">{{ data.lastBackupAt }}</el-tag>
|
||||
<span else>{{ $t('website.null') }}</span>
|
||||
<span v-else>{{ $t('website.null') }}</span>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="6">
|
||||
<el-col :lg="4" :xl="6">
|
||||
<el-button type="primary" link @click="onOperate('restart')">{{ $t('app.restart') }}</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button type="primary" link @click="setting">{{ $t('commons.button.set') }}</el-button>
|
||||
|
@ -733,6 +733,10 @@ export default {
|
||||
gotoInstalled: '去安装',
|
||||
search: '搜索',
|
||||
limitHelper: '该应用已安装,不支持重复安装',
|
||||
deleteHelper: '应用已经关联以下资源,无法删除',
|
||||
checkTitle: '提示',
|
||||
website: '网站',
|
||||
database: '数据库',
|
||||
},
|
||||
website: {
|
||||
website: '网站',
|
||||
|
54
frontend/src/views/app-store/installed/check/index.vue
Normal file
54
frontend/src/views/app-store/installed/check/index.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="open"
|
||||
:title="$t('app.checkTitle')"
|
||||
width="50%"
|
||||
:close-on-click-modal="false"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<el-row>
|
||||
<el-alert type="warning" :description="$t('app.deleteHelper')" center show-icon :closable="false" />
|
||||
<el-col :span="12" :offset="6">
|
||||
<br />
|
||||
<el-descriptions border :column="1">
|
||||
<el-descriptions-item v-for="(item, key) in map" :key="key" :label="$t('app.' + item[0])">
|
||||
{{ map.get(item[0]).toString() }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { App } from '@/api/interface/app';
|
||||
import { ref } from 'vue';
|
||||
|
||||
interface InstallRrops {
|
||||
items: App.AppInstallResource[];
|
||||
}
|
||||
const installData = ref<InstallRrops>({
|
||||
items: [],
|
||||
});
|
||||
let open = ref(false);
|
||||
let map = new Map();
|
||||
|
||||
const acceptParams = (props: InstallRrops) => {
|
||||
map.clear();
|
||||
installData.value.items = [];
|
||||
installData.value.items = props.items;
|
||||
installData.value.items.forEach((item) => {
|
||||
if (map.has(item.type)) {
|
||||
const array = map.get(item.type);
|
||||
array.push(item.name);
|
||||
map.set(item.type, array);
|
||||
} else {
|
||||
map.set(item.type, [item.name]);
|
||||
}
|
||||
});
|
||||
open.value = true;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
@ -104,17 +104,25 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
<Backups ref="backupRef" @close="search"></Backups>
|
||||
<AppResources ref="checkRef"></AppResources>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { SearchAppInstalled, InstalledOp, SyncInstalledApp, GetAppUpdateVersions } from '@/api/modules/app';
|
||||
import {
|
||||
SearchAppInstalled,
|
||||
InstalledOp,
|
||||
SyncInstalledApp,
|
||||
GetAppUpdateVersions,
|
||||
AppInstalledDeleteCheck,
|
||||
} from '@/api/modules/app';
|
||||
import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||
import ComplexTable from '@/components/complex-table/index.vue';
|
||||
import { dateFromat } from '@/utils/util';
|
||||
import i18n from '@/lang';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import Backups from './backups.vue';
|
||||
import AppResources from './check/index.vue';
|
||||
import { App } from '@/api/interface/app';
|
||||
|
||||
let data = ref<any>();
|
||||
@ -133,6 +141,7 @@ let operateReq = reactive({
|
||||
});
|
||||
let versions = ref<App.VersionDetail[]>();
|
||||
const backupRef = ref();
|
||||
const checkRef = ref();
|
||||
let searchName = ref('');
|
||||
|
||||
const sync = () => {
|
||||
@ -171,6 +180,15 @@ const openOperate = (row: any, op: string) => {
|
||||
}
|
||||
open.value = true;
|
||||
});
|
||||
} else if (op == 'delete') {
|
||||
AppInstalledDeleteCheck(row.id).then((res) => {
|
||||
const items = res.data;
|
||||
if (res.data && res.data.length > 0) {
|
||||
checkRef.value.acceptParams({ items: items });
|
||||
} else {
|
||||
onOperate(op);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
onOperate(op);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user