diff --git a/backend/app/dto/request/app.go b/backend/app/dto/request/app.go index ee3cabd30..1e9b292fa 100644 --- a/backend/app/dto/request/app.go +++ b/backend/app/dto/request/app.go @@ -28,6 +28,8 @@ type AppContainerConfig struct { MemoryUnit string `json:"memoryUnit"` ContainerName string `json:"containerName"` AllowPort bool `json:"allowPort"` + EditCompose bool `json:"editCompose"` + DockerCompose string `json:"dockerCompose"` } type AppInstalledSearch struct { diff --git a/backend/app/model/app_detail.go b/backend/app/model/app_detail.go index e2a8269e4..9a4d8c6db 100644 --- a/backend/app/model/app_detail.go +++ b/backend/app/model/app_detail.go @@ -5,7 +5,7 @@ type AppDetail struct { AppId uint `json:"appId" gorm:"type:integer;not null"` Version string `json:"version" gorm:"type:varchar(64);not null"` Params string `json:"-" gorm:"type:longtext;"` - DockerCompose string `json:"-" gorm:"type:longtext;"` + DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` Status string `json:"status" gorm:"type:varchar(64);not null"` LastVersion string `json:"lastVersion" gorm:"type:varchar(64);"` LastModified int `json:"lastModified" gorm:"type:integer;"` diff --git a/backend/app/service/app.go b/backend/app/service/app.go index e488c8b47..a24cbe527 100644 --- a/backend/app/service/app.go +++ b/backend/app/service/app.go @@ -268,8 +268,14 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) ( App: app, } composeMap := make(map[string]interface{}) - if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil { - return + if req.EditCompose { + if err = yaml.Unmarshal([]byte(req.DockerCompose), &composeMap); err != nil { + return + } + } else { + if err = yaml.Unmarshal([]byte(appDetail.DockerCompose), &composeMap); err != nil { + return + } } value, ok := composeMap["services"] diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index a73c054c8..9bf8bbe35 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -1120,6 +1120,9 @@ const message = { 'The application does not release the external access port by default, you can choose to release it in the advanced settings', upgradeStart: 'Start upgrading! Please refresh the page later', toFolder: 'Open the installation directory', + editCompose: 'Edit compose file', + editComposeHelper: 'Editing the compose file may cause the software installation to fail', + composeNullErr: 'compose cannot be empty', }, website: { website: 'Website', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 29de2a55d..b7357d8d2 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1113,6 +1113,9 @@ const message = { appInstallWarn: '应用默认不放开外部访问端口,可以在高级设置中选择放开', upgradeStart: '开始升级!请稍后刷新页面', toFolder: '打开安装目录', + editCompose: '编辑 compose 文件', + editComposeHelper: '编辑 compose 文件可能导致软件安装失败', + composeNullErr: 'compose 不能为空', }, website: { website: '网站', diff --git a/frontend/src/views/app-store/detail/index.vue b/frontend/src/views/app-store/detail/index.vue index f0bb1b3aa..e46c9f5e2 100644 --- a/frontend/src/views/app-store/detail/index.vue +++ b/frontend/src/views/app-store/detail/index.vue @@ -150,6 +150,7 @@ const openInstall = () => { params: appDetail.value.params, appDetailId: appDetail.value.id, app: app.value, + compose: appDetail.value.dockerCompose, }; if (app.value.type === 'php') { router.push({ path: '/websites/runtime/php' }); diff --git a/frontend/src/views/app-store/detail/install/index.vue b/frontend/src/views/app-store/detail/install/index.vue index 6f89039de..8b5c3af6f 100644 --- a/frontend/src/views/app-store/detail/install/index.vue +++ b/frontend/src/views/app-store/detail/install/index.vue @@ -7,9 +7,8 @@ :before-close="handleClose" > - @@ -66,6 +65,25 @@ {{ $t('app.allowPortHelper') }} + + + {{ $t('app.editComposeHelper') }} + +
+ +
@@ -92,18 +110,26 @@ import { reactive, ref } from 'vue'; import { useRouter } from 'vue-router'; import Params from '../params/index.vue'; import Header from '@/components/drawer-header/index.vue'; +import { Codemirror } from 'vue-codemirror'; +import { javascript } from '@codemirror/lang-javascript'; +import { oneDark } from '@codemirror/theme-one-dark'; +import i18n from '@/lang'; +import { MsgError } from '@/utils/message'; +const extensions = [javascript(), oneDark]; const router = useRouter(); interface InstallRrops { appDetailId: number; params?: App.AppParams; app: any; + compose: string; } const installData = ref({ appDetailId: 0, app: {}, + compose: '', }); const open = ref(false); const rules = ref({ @@ -126,6 +152,8 @@ const initData = () => ({ memoryUnit: 'MB', containerName: '', allowPort: false, + editCompose: false, + dockerCompose: '', }); const req = reactive(initData()); @@ -140,6 +168,7 @@ const resetForm = () => { paramForm.value.resetFields(); } Object.assign(req, initData()); + req.dockerCompose = installData.value.compose; }; const acceptParams = (props: InstallRrops): void => { @@ -154,6 +183,10 @@ const submit = async (formEl: FormInstance | undefined) => { if (!valid) { return; } + if (req.editCompose && req.dockerCompose == '') { + MsgError(i18n.global.t('app.composeNullErr')); + return; + } req.appDetailId = installData.value.appDetailId; loading.value = true; InstallApp(req)