Browse Source

feat: 增加忽略应用列表和取消忽略功能 (#1566)

增加忽略应用列表和取消忽略功能
pull/1572/head
zhengkunwang223 1 year ago committed by GitHub
parent
commit
10427ddd65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      backend/app/api/v1/app.go
  2. 4
      backend/app/dto/request/app.go
  3. 7
      backend/app/dto/response/app.go
  4. 8
      backend/app/repo/app_detail.go
  5. 22
      backend/app/service/app.go
  6. 2
      backend/app/service/app_install.go
  7. 1
      backend/router/ro_app.go
  8. 483
      cmd/server/docs/docs.go
  9. 412
      cmd/server/docs/swagger.json
  10. 386
      cmd/server/docs/swagger.yaml
  11. 7
      frontend/src/api/interface/app.ts
  12. 4
      frontend/src/api/modules/app.ts
  13. 5
      frontend/src/lang/modules/en.ts
  14. 5
      frontend/src/lang/modules/tw.ts
  15. 5
      frontend/src/lang/modules/zh.ts
  16. 85
      frontend/src/views/app-store/installed/ignore/index.vue
  17. 17
      frontend/src/views/app-store/installed/index.vue
  18. 6
      go.mod
  19. 6
      go.sum

16
backend/app/api/v1/app.go

@ -130,6 +130,22 @@ func (b *BaseApi) GetAppDetailByID(c *gin.Context) {
helper.SuccessWithData(c, appDetailDTO)
}
// @Tags App
// @Summary Get Ignore App
// @Description 获取忽略的应用版本
// @Accept json
// @Success 200 {object} response.IgnoredApp
// @Security ApiKeyAuth
// @Router /apps/ingored [get]
func (b *BaseApi) GetIgnoredApp(c *gin.Context) {
res, err := appService.GetIgnoredApp()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, res)
}
// @Tags App
// @Summary Install app
// @Description 安装应用

4
backend/app/dto/request/app.go

@ -67,8 +67,8 @@ type AppInstalledUpdate struct {
}
type AppInstalledIgnoreUpgrade struct {
InstallId uint `json:"installId" validate:"required"`
DetailId uint `json:"detailId" validate:"required"`
DetailID uint `json:"detailID" validate:"required"`
Operate string `json:"operate" validate:"required,oneof=cancel ignore"`
}
type PortUpdate struct {

7
backend/app/dto/response/app.go

@ -48,6 +48,13 @@ type AppDetailDTO struct {
Image string `json:"image"`
}
type IgnoredApp struct {
Icon string `json:"icon"`
Name string `json:"name"`
Version string `json:"version"`
DetailID uint `json:"detailID"`
}
type AppInstalledDTO struct {
model.AppInstall
Total int `json:"total"`

8
backend/app/repo/app_detail.go

@ -13,6 +13,7 @@ type AppDetailRepo struct {
type IAppDetailRepo interface {
WithVersion(version string) DBOption
WithAppId(id uint) DBOption
WithIgnored() DBOption
GetFirst(opts ...DBOption) (model.AppDetail, error)
Update(ctx context.Context, detail model.AppDetail) error
BatchCreate(ctx context.Context, details []model.AppDetail) error
@ -31,12 +32,19 @@ func (a AppDetailRepo) WithVersion(version string) DBOption {
return g.Where("version = ?", version)
}
}
func (a AppDetailRepo) WithAppId(id uint) DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("app_id = ?", id)
}
}
func (a AppDetailRepo) WithIgnored() DBOption {
return func(g *gorm.DB) *gorm.DB {
return g.Where("ignore_upgrade = 1")
}
}
func (a AppDetailRepo) GetFirst(opts ...DBOption) (model.AppDetail, error) {
var detail model.AppDetail
err := getDb(opts...).Model(&model.AppDetail{}).Find(&detail).Error

22
backend/app/service/app.go

@ -39,6 +39,7 @@ type IAppService interface {
GetAppUpdate() (*response.AppUpdateRes, error)
GetAppDetailByID(id uint) (*response.AppDetailDTO, error)
SyncAppListFromLocal()
GetIgnoredApp() ([]response.IgnoredApp, error)
}
func NewIAppService() IAppService {
@ -232,6 +233,27 @@ func (a AppService) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) {
return res, nil
}
func (a AppService) GetIgnoredApp() ([]response.IgnoredApp, error) {
var res []response.IgnoredApp
details, _ := appDetailRepo.GetBy(appDetailRepo.WithIgnored())
if len(details) == 0 {
return res, nil
}
for _, detail := range details {
app, err := appRepo.GetFirst(commonRepo.WithByID(detail.AppId))
if err != nil {
return nil, err
}
res = append(res, response.IgnoredApp{
Name: app.Name,
Version: detail.Version,
DetailID: detail.ID,
Icon: app.Icon,
})
}
return res, nil
}
func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (appInstall *model.AppInstall, err error) {
if err = docker.CreateDefaultDockerNetwork(); err != nil {
err = buserr.WithDetail(constant.Err1PanelNetworkFailed, err.Error(), nil)

2
backend/app/service/app_install.go

@ -359,7 +359,7 @@ func (a *AppInstallService) IgnoreUpgrade(req request.AppInstalledIgnoreUpgrade)
if err != nil {
return err
}
appDetail.IgnoreUpgrade = true
appDetail.IgnoreUpgrade = req.Operate == "ignore"
return appDetailRepo.Update(context.Background(), appDetail)
}

1
backend/router/ro_app.go

@ -37,5 +37,6 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) {
appRouter.GET("/installed/params/:appInstallId", baseApi.GetParams)
appRouter.POST("/installed/params/update", baseApi.UpdateInstalled)
appRouter.POST("/installed/ignore", baseApi.IgnoreUpgrade)
appRouter.GET("/ignored/detail", baseApi.GetIgnoredApp)
}
}

483
cmd/server/docs/docs.go

File diff suppressed because it is too large Load Diff

412
cmd/server/docs/swagger.json

File diff suppressed because it is too large Load Diff

386
cmd/server/docs/swagger.yaml

File diff suppressed because it is too large Load Diff

7
frontend/src/api/interface/app.ts

@ -187,4 +187,11 @@ export namespace App {
allowPort: boolean;
dockerCompose: string;
}
export interface IgnoredApp {
name: string;
detailID: number;
version: string;
icon: string;
}
}

4
frontend/src/api/modules/app.ts

@ -93,3 +93,7 @@ export const UpdateAppInstallParams = (req: any) => {
export const IgnoreUpgrade = (req: any) => {
return http.post<any>(`apps/installed/ignore`, req);
};
export const GetIgnoredApp = () => {
return http.get<App.IgnoredApp>(`apps/ignored/detail`);
};

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

@ -44,7 +44,7 @@ const message = {
refresh: 'Refresh',
get: 'Get',
upgrade: 'Upgrade',
ignoreUpgrade: 'Ignore upgrade',
ignore: 'Ignore upgrade',
copy: 'Copy',
random: 'Random',
},
@ -1198,6 +1198,9 @@ const message = {
'Currently, if the port external access is not checked, it will not be able to access through the external network IP: port. Do you want to continue?',
restoreWarn:
'The restore operation will delete the current data of the application and restart it. This operation cannot be rolled back, continue?',
showIgnore: 'View ignore application',
cancelIgnore: 'Cancel ignore',
ignoreList: 'ignore list',
},
website: {
website: 'Website',

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

@ -44,7 +44,7 @@ const message = {
refresh: '刷新',
get: '獲取',
upgrade: '升級',
ignoreUpgrade: '忽略升級',
ignore: '忽略升級',
copy: '復製',
random: '隨機密碼',
},
@ -1139,6 +1139,9 @@ const message = {
upgradeHelper: '異常應用需要先同步到正常狀態',
installWarn: '當前未勾選端口外部訪問將無法通過外網IP:端口訪問是否繼續 ',
restoreWarn: '恢復操作將刪除該應用當前數據並重啟此操作不可回滾是否繼續?',
showIgnore: '查看忽略應用',
cancelIgnore: '取消忽略',
ignoreList: '忽略列表',
},
website: {
website: '網站',

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

@ -44,7 +44,7 @@ const message = {
refresh: '刷新',
get: '获取',
upgrade: '升级',
ignoreUpgrade: '忽略升级',
ignore: '忽略升级',
copy: '复制',
random: '随机密码',
},
@ -1145,6 +1145,9 @@ const message = {
upgradeHelper: '异常应用需要先同步到正常状态',
installWarn: '当前未勾选端口外部访问将无法通过外网IP:端口访问是否继续',
restoreWarn: '恢复操作将删除该应用当前数据并重启此操作不可回滚是否继续?',
showIgnore: '查看忽略应用',
cancelIgnore: '取消忽略',
ignoreList: '忽略列表',
},
website: {
website: '网站',

85
frontend/src/views/app-store/installed/ignore/index.vue

@ -0,0 +1,85 @@
<template>
<el-drawer :close-on-click-modal="false" v-model="open" size="30%">
<template #header>
<Header :header="$t('app.ignoreList')" :back="handleClose"></Header>
</template>
<el-row :gutter="5">
<el-col v-for="(app, index) in apps" :key="index">
<el-card class="app-margin">
<el-row :gutter="20">
<el-col :span="6">
<el-avatar shape="square" :size="60" :src="'data:image/png;base64,' + app.icon" />
</el-col>
<el-col :span="12">
<span>{{ app.name }}</span>
<div class="app-margin">
<el-tag>{{ app.version }}</el-tag>
</div>
</el-col>
<el-col :span="6">
<el-button type="primary" link @click="cancelIngore(app.detailID)">
{{ $t('app.cancelIgnore') }}
</el-button>
</el-col>
</el-row>
</el-card>
</el-col>
</el-row>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
</span>
</template>
</el-drawer>
</template>
<script lang="ts" setup>
import { GetIgnoredApp, IgnoreUpgrade } from '@/api/modules/app';
import { ref } from 'vue';
import Header from '@/components/drawer-header/index.vue';
import { MsgSuccess } from '@/utils/message';
import i18n from '@/lang';
const open = ref(false);
const loading = ref(false);
const apps = ref();
const em = defineEmits(['close']);
const handleClose = () => {
open.value = false;
em('close', open);
};
const acceptParams = () => {
open.value = true;
getApps();
};
const getApps = async () => {
try {
const res = await GetIgnoredApp();
apps.value = res.data;
} catch (error) {}
};
const cancelIngore = async (id: number) => {
loading.value = true;
await IgnoreUpgrade({ detailID: id, operate: 'cancel' })
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
})
.finally(() => {
getApps();
loading.value = false;
});
};
defineExpose({
acceptParams,
});
</script>
<style scoped>
.app-margin {
margin-top: 10px;
}
</style>

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

@ -46,6 +46,9 @@
<el-button @click="sync" type="primary" link v-if="mode === 'installed' && data != null">
{{ $t('app.sync') }}
</el-button>
<el-button @click="openIngore" type="primary" link v-if="mode === 'upgrade'">
{{ $t('app.showIgnore') }}
</el-button>
</template>
<template #main>
@ -164,10 +167,10 @@
plain
round
size="small"
@click="openOperate(installed, 'ignoreUpgrade')"
@click="openOperate(installed, 'ignore')"
v-if="mode === 'upgrade'"
>
{{ $t('commons.button.ignoreUpgrade') }}
{{ $t('commons.button.ignore') }}
</el-button>
<el-button
class="h-button"
@ -239,8 +242,8 @@
<AppDelete ref="deleteRef" @close="search" />
<AppParams ref="appParamRef" />
<AppUpgrade ref="upgradeRef" @close="search" />
<PortJumpDialog ref="dialogPortJumpRef" />
<AppIgnore ref="ignoreRef" @close="search" />
</template>
<script lang="ts" setup>
@ -261,6 +264,7 @@ import AppResources from './check/index.vue';
import AppDelete from './delete/index.vue';
import AppParams from './detail/index.vue';
import AppUpgrade from './upgrade/index.vue';
import AppIgnore from './ignore/index.vue';
import { App } from '@/api/interface/app';
import Status from '@/components/status/index.vue';
import { getAge } from '@/utils/util';
@ -289,6 +293,7 @@ const checkRef = ref();
const deleteRef = ref();
const appParamRef = ref();
const upgradeRef = ref();
const ignoreRef = ref();
const dialogPortJumpRef = ref();
const tags = ref<App.Tag[]>([]);
const activeTag = ref('all');
@ -348,7 +353,7 @@ const goDashboard = async (port: any) => {
const openOperate = (row: any, op: string) => {
operateReq.installId = row.id;
operateReq.operate = op;
if (op == 'upgrade' || op == 'ignoreUpgrade') {
if (op == 'upgrade' || op == 'ignore') {
upgradeRef.value.acceptParams(row.id, row.name, op);
} else if (op == 'delete') {
AppInstalledDeleteCheck(row.id).then(async (res) => {
@ -364,6 +369,10 @@ const openOperate = (row: any, op: string) => {
}
};
const openIngore = () => {
ignoreRef.value.acceptParams();
};
const operate = async () => {
open.value = false;
loading.value = true;

6
go.mod

@ -47,7 +47,7 @@ require (
github.com/subosito/gotenv v1.4.1
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a
github.com/swaggo/gin-swagger v1.5.3
github.com/swaggo/swag v1.8.4
github.com/swaggo/swag v1.16.1
github.com/tencentyun/cos-go-sdk-v5 v0.7.41
github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f
golang.org/x/crypto v0.9.0
@ -245,11 +245,11 @@ require (
go4.org v0.0.0-20200411211856-f5505b9728dd // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/image v0.5.0 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/term v0.8.0 // indirect
golang.org/x/time v0.1.0 // indirect
golang.org/x/tools v0.6.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.53.0 // indirect

6
go.sum

@ -845,6 +845,8 @@ github.com/swaggo/gin-swagger v1.5.3/go.mod h1:3XJKSfHjDMB5dBo/0rrTXidPmgLeqsX89
github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ=
github.com/swaggo/swag v1.8.4 h1:oGB351qH1JqUqK1tsMYEE5qTBbPk394BhsZxmUfebcI=
github.com/swaggo/swag v1.8.4/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg=
github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg=
github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=
@ -1011,6 +1013,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1202,6 +1206,8 @@ golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

Loading…
Cancel
Save