mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-14 01:34:47 +08:00
feat: 应用增加 Web 访问地址 (#6248)
This commit is contained in:
parent
4ac5ff7cf0
commit
53cfb2e755
@ -325,3 +325,24 @@ func (b *BaseApi) IgnoreUpgrade(c *gin.Context) {
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
||||
// @Tags App
|
||||
// @Summary Update app config
|
||||
// @Description 更新应用配置
|
||||
// @Accept json
|
||||
// @Param request body request.AppConfigUpdate true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /apps/installed/config/update [post]
|
||||
// @x-panel-log {"bodyKeys":["installID","webUI"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"应用配置更新 [installID]","formatEN":"Application config update [installID]"}
|
||||
func (b *BaseApi) UpdateAppConfig(c *gin.Context) {
|
||||
var req request.AppConfigUpdate
|
||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||
return
|
||||
}
|
||||
if err := appInstallService.UpdateAppConfig(req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithOutData(c)
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ type AppContainerConfig struct {
|
||||
HostMode bool `json:"hostMode"`
|
||||
PullImage bool `json:"pullImage"`
|
||||
GpuConfig bool `json:"gpuConfig"`
|
||||
WebUI string `json:"webUI"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type AppInstalledSearch struct {
|
||||
@ -103,6 +105,11 @@ type AppInstalledUpdate struct {
|
||||
AppContainerConfig
|
||||
}
|
||||
|
||||
type AppConfigUpdate struct {
|
||||
InstallID uint `json:"installID" validate:"required"`
|
||||
WebUI string `json:"webUI"`
|
||||
}
|
||||
|
||||
type AppInstalledIgnoreUpgrade struct {
|
||||
DetailID uint `json:"detailID" validate:"required"`
|
||||
Operate string `json:"operate" validate:"required,oneof=cancel ignore"`
|
||||
|
@ -120,6 +120,7 @@ type AppInstallDTO struct {
|
||||
AppType string `json:"appType"`
|
||||
AppStatus string `json:"appStatus"`
|
||||
DockerCompose string `json:"dockerCompose"`
|
||||
WebUI string `json:"webUI"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
App AppDetail `json:"app"`
|
||||
}
|
||||
|
@ -21,8 +21,9 @@ type AppInstall struct {
|
||||
Message string `json:"message"`
|
||||
ContainerName string `json:"containerName" gorm:"not null"`
|
||||
ServiceName string `json:"serviceName" gorm:"not null"`
|
||||
HttpPort int `json:"httpPort" gorm:"not null"`
|
||||
HttpsPort int `json:"httpsPort" gorm:"not null"`
|
||||
HttpPort int `json:"httpPort"`
|
||||
HttpsPort int `json:"httpsPort"`
|
||||
WebUI string `json:"webUI"`
|
||||
App App `json:"app" gorm:"-:migration"`
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,7 @@ type IAppInstallService interface {
|
||||
GetDefaultConfigByKey(key, name string) (string, error)
|
||||
DeleteCheck(installId uint) ([]dto.AppResource, error)
|
||||
|
||||
UpdateAppConfig(req request.AppConfigUpdate) error
|
||||
GetInstallList() ([]dto.AppInstallInfo, error)
|
||||
}
|
||||
|
||||
@ -304,6 +305,18 @@ func (a *AppInstallService) Operate(req request.AppInstalledOperate) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AppInstallService) UpdateAppConfig(req request.AppConfigUpdate) error {
|
||||
installed, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
installed.WebUI = ""
|
||||
if req.WebUI != "" {
|
||||
installed.WebUI = req.WebUI
|
||||
}
|
||||
return appInstallRepo.Save(context.Background(), &installed)
|
||||
}
|
||||
|
||||
func (a *AppInstallService) Update(req request.AppInstalledUpdate) error {
|
||||
installed, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallId))
|
||||
if err != nil {
|
||||
@ -767,6 +780,8 @@ func (a *AppInstallService) GetParams(id uint) (*response.AppConfig, error) {
|
||||
}
|
||||
res.AppContainerConfig = config
|
||||
res.HostMode = isHostModel(install.DockerCompose)
|
||||
res.WebUI = install.WebUI
|
||||
res.Type = install.App.Type
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
|
@ -1363,6 +1363,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
|
||||
AppType: installed.App.Type,
|
||||
Path: installed.GetPath(),
|
||||
CreatedAt: installed.CreatedAt,
|
||||
WebUI: installed.WebUI,
|
||||
App: response.AppDetail{
|
||||
Github: installed.App.Github,
|
||||
Website: installed.App.Website,
|
||||
|
@ -20,6 +20,7 @@ func Init() {
|
||||
migrations.UpdateWebsiteDomain,
|
||||
migrations.UpdateApp,
|
||||
migrations.AddTaskDB,
|
||||
migrations.UpdateAppInstall,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
@ -251,3 +251,11 @@ var UpdateApp = &gormigrate.Migration{
|
||||
&model.App{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateAppInstall = &gormigrate.Migration{
|
||||
ID: "20240828-update-app-install",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(
|
||||
&model.AppInstall{})
|
||||
},
|
||||
}
|
||||
|
@ -38,5 +38,6 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
appRouter.POST("/installed/ignore", baseApi.IgnoreUpgrade)
|
||||
appRouter.GET("/ignored/detail", baseApi.GetIgnoredApp)
|
||||
appRouter.POST("/installed/update/versions", baseApi.GetUpdateVersions)
|
||||
appRouter.POST("/installed/config/update", baseApi.UpdateAppConfig)
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +239,8 @@ export namespace App {
|
||||
allowPort: boolean;
|
||||
dockerCompose: string;
|
||||
hostMode?: boolean;
|
||||
type: string;
|
||||
webUI: string;
|
||||
}
|
||||
|
||||
export interface IgnoredApp {
|
||||
@ -256,4 +258,9 @@ export namespace App {
|
||||
export interface AppStoreSync {
|
||||
taskID: string;
|
||||
}
|
||||
|
||||
export interface AppConfigUpdate {
|
||||
installID: number;
|
||||
webUI: string;
|
||||
}
|
||||
}
|
||||
|
@ -106,3 +106,7 @@ export const IgnoreUpgrade = (req: any) => {
|
||||
export const GetIgnoredApp = () => {
|
||||
return http.get<App.IgnoredApp>(`apps/ignored/detail`);
|
||||
};
|
||||
|
||||
export const UpdateInstallConfig = (req: App.AppConfigUpdate) => {
|
||||
return http.post(`apps/installed/config/update`, req);
|
||||
};
|
||||
|
@ -1883,6 +1883,8 @@ const message = {
|
||||
gpuConfig: 'Enable GPU Support',
|
||||
gpuConfigHelper:
|
||||
'Please ensure the machine has an NVIDIA GPU and that NVIDIA drivers and the NVIDIA Docker Container Toolkit are installed',
|
||||
webUI: 'Web Access Address',
|
||||
webUIPlaceholder: 'For example: http://example.com:8080/login',
|
||||
},
|
||||
website: {
|
||||
website: 'Website',
|
||||
|
@ -1748,6 +1748,8 @@ const message = {
|
||||
memoryRequiredHelper: '目前應用記憶體需求 {0}',
|
||||
gpuConfig: '開啟 GPU 支援',
|
||||
gpuConfigHelper: '請確保機器有 NVIDIA GPU 並且安裝 NVIDIA 驅動 和 NVIDIA docker Container Toolkit',
|
||||
webUI: 'Web 訪問地址',
|
||||
webUIPlaceholder: '例如:http://example.com:8080/login',
|
||||
},
|
||||
website: {
|
||||
website: '網站',
|
||||
|
@ -1749,6 +1749,8 @@ const message = {
|
||||
memoryRequiredHelper: '当前应用内存需求 {0}',
|
||||
gpuConfig: '开启 GPU 支持',
|
||||
gpuConfigHelper: '请确保机器有 NVIDIA GPU 并且安装 NVIDIA 驱动 和 NVIDIA docker Container Toolkit',
|
||||
webUI: 'Web 访问地址',
|
||||
webUIPlaceholder: '例如:http://example.com:8080/login',
|
||||
},
|
||||
website: {
|
||||
website: '网站',
|
||||
|
@ -5,15 +5,29 @@
|
||||
{{ edit ? $t('app.detail') : $t('commons.button.edit') }}
|
||||
</el-button>
|
||||
</template>
|
||||
<el-descriptions border :column="1" v-if="!edit">
|
||||
<div v-if="!edit">
|
||||
<el-descriptions border :column="1">
|
||||
<el-descriptions-item v-for="(param, key) in params" :label="getLabel(param)" :key="key">
|
||||
<span>{{ param.showValue && param.showValue != '' ? param.showValue : param.value }}</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-form label-position="top" class="mt-2">
|
||||
<el-form-item v-if="appType == 'website'" :label="$t('app.webUI')">
|
||||
<el-input v-model="appConfigUpdate.webUI" :placeholder="$t('app.webUIPlaceholder')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :disabled="loading" @click="updateAppConfig">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div v-else v-loading="loading">
|
||||
<el-alert :title="$t('app.updateHelper')" type="warning" :closable="false" class="common-prompt" />
|
||||
<el-form @submit.prevent ref="paramForm" :model="paramModel" label-position="top" :rules="rules">
|
||||
<el-form-item v-if="appType == 'website'" :label="$t('app.webUI')">
|
||||
<el-input v-model="appConfigUpdate.webUI" :placeholder="$t('app.webUIPlaceholder')"></el-input>
|
||||
</el-form-item>
|
||||
<div v-for="(p, index) in params" :key="index">
|
||||
<el-form-item :prop="p.key" :label="getLabel(p)">
|
||||
<el-input
|
||||
@ -93,7 +107,7 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { App } from '@/api/interface/app';
|
||||
import { GetAppInstallParams, UpdateAppInstallParams } from '@/api/modules/app';
|
||||
import { GetAppInstallParams, UpdateAppInstallParams, UpdateInstallConfig } from '@/api/modules/app';
|
||||
import { reactive, ref } from 'vue';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { Rules, checkNumberRange } from '@/global/form-rules';
|
||||
@ -128,7 +142,14 @@ const rules = reactive({
|
||||
memoryLimit: [Rules.requiredInput, checkNumberRange(0, 9999999999)],
|
||||
containerName: [Rules.containerName],
|
||||
});
|
||||
const submitModel = ref<any>({});
|
||||
const submitModel = ref<any>({
|
||||
webUI: '',
|
||||
});
|
||||
const appType = ref('');
|
||||
const appConfigUpdate = ref<App.AppConfigUpdate>({
|
||||
installID: 0,
|
||||
webUI: '',
|
||||
});
|
||||
|
||||
const acceptParams = async (props: ParamProps) => {
|
||||
submitModel.value.installId = props.id;
|
||||
@ -188,6 +209,8 @@ const get = async () => {
|
||||
paramModel.value.advanced = false;
|
||||
paramModel.value.dockerCompose = res.data.dockerCompose;
|
||||
paramModel.value.isHostMode = res.data.hostMode;
|
||||
appConfigUpdate.value.webUI = res.data.webUI;
|
||||
appType.value = res.data.type;
|
||||
} catch (error) {
|
||||
} finally {
|
||||
loading.value = false;
|
||||
@ -240,6 +263,17 @@ const submit = async (formEl: FormInstance) => {
|
||||
});
|
||||
};
|
||||
|
||||
const updateAppConfig = async () => {
|
||||
try {
|
||||
await UpdateInstallConfig({
|
||||
installID: Number(paramData.value.id),
|
||||
webUI: appConfigUpdate.value.webUI,
|
||||
});
|
||||
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||
handleClose();
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
defineExpose({ acceptParams });
|
||||
</script>
|
||||
|
||||
|
@ -175,6 +175,22 @@
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
<span class="ml-1">
|
||||
<el-tooltip
|
||||
v-if="installed.webUI !== ''"
|
||||
effect="dark"
|
||||
:content="installed.webUI"
|
||||
placement="top"
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="toLink(installed.webUI)"
|
||||
>
|
||||
<el-icon><Promotion /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</span>
|
||||
|
||||
<el-button
|
||||
class="h-button"
|
||||
@ -650,6 +666,10 @@ const openLog = (row: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
const toLink = (link: string) => {
|
||||
window.open(link, '_blank');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const path = router.currentRoute.value.path;
|
||||
if (path == '/apps/upgrade') {
|
||||
|
Loading…
x
Reference in New Issue
Block a user