mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-09 23:17:21 +08:00
feat: 应用商店设置增加默认访问地址 (#6250)
Some checks failed
sync2gitee / repo-sync (push) Failing after -8m19s
Some checks failed
sync2gitee / repo-sync (push) Failing after -8m19s
This commit is contained in:
parent
53cfb2e755
commit
7b9456453c
17 changed files with 325 additions and 36 deletions
|
@ -209,3 +209,39 @@ func (b *BaseApi) GetAppListUpdate(c *gin.Context) {
|
||||||
}
|
}
|
||||||
helper.SuccessWithData(c, res)
|
helper.SuccessWithData(c, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Tags App
|
||||||
|
// @Summary Update appstore config
|
||||||
|
// @Description 更新应用商店配置
|
||||||
|
// @Accept json
|
||||||
|
// @Param request body request.AppstoreUpdate true "request"
|
||||||
|
// @Success 200
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Router /apps/store/update [post]
|
||||||
|
func (b *BaseApi) UpdateAppstoreConfig(c *gin.Context) {
|
||||||
|
var req request.AppstoreUpdate
|
||||||
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := appService.UpdateAppstoreConfig(req)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithOutData(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Tags App
|
||||||
|
// @Summary Get appstore config
|
||||||
|
// @Description 获取应用商店配置
|
||||||
|
// @Success 200 {object} response.AppstoreConfig
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Router /apps/store/config [get]
|
||||||
|
func (b *BaseApi) GetAppstoreConfig(c *gin.Context) {
|
||||||
|
res, err := appService.GetAppstoreConfig()
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, res)
|
||||||
|
}
|
||||||
|
|
|
@ -125,3 +125,7 @@ type AppUpdateVersion struct {
|
||||||
AppInstallID uint `json:"appInstallID" validate:"required"`
|
AppInstallID uint `json:"appInstallID" validate:"required"`
|
||||||
UpdateVersion string `json:"updateVersion"`
|
UpdateVersion string `json:"updateVersion"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AppstoreUpdate struct {
|
||||||
|
DefaultDomain string `json:"defaultDomain"`
|
||||||
|
}
|
||||||
|
|
|
@ -159,3 +159,7 @@ type AppConfig struct {
|
||||||
Params []AppParam `json:"params"`
|
Params []AppParam `json:"params"`
|
||||||
request.AppContainerConfig
|
request.AppContainerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AppstoreConfig struct {
|
||||||
|
DefaultDomain string `json:"defaultDomain"`
|
||||||
|
}
|
||||||
|
|
|
@ -45,6 +45,9 @@ type IAppService interface {
|
||||||
GetAppDetailByID(id uint) (*response.AppDetailDTO, error)
|
GetAppDetailByID(id uint) (*response.AppDetailDTO, error)
|
||||||
SyncAppListFromLocal(taskID string)
|
SyncAppListFromLocal(taskID string)
|
||||||
GetIgnoredApp() ([]response.IgnoredApp, error)
|
GetIgnoredApp() ([]response.IgnoredApp, error)
|
||||||
|
|
||||||
|
GetAppstoreConfig() (*response.AppstoreConfig, error)
|
||||||
|
UpdateAppstoreConfig(req request.AppstoreUpdate) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIAppService() IAppService {
|
func NewIAppService() IAppService {
|
||||||
|
@ -1067,3 +1070,15 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a AppService) UpdateAppstoreConfig(req request.AppstoreUpdate) error {
|
||||||
|
settingService := NewISettingService()
|
||||||
|
return settingService.Update("AppDefaultDomain", req.DefaultDomain)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AppService) GetAppstoreConfig() (*response.AppstoreConfig, error) {
|
||||||
|
defaultDomain, _ := settingRepo.Get(settingRepo.WithByKey("AppDefaultDomain"))
|
||||||
|
res := &response.AppstoreConfig{}
|
||||||
|
res.DefaultDomain = defaultDomain.Value
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
|
@ -46,14 +46,16 @@ func (u *SettingService) Update(key, value string) error {
|
||||||
case "AppStoreLastModified":
|
case "AppStoreLastModified":
|
||||||
exist, _ := settingRepo.Get(settingRepo.WithByKey("AppStoreLastModified"))
|
exist, _ := settingRepo.Get(settingRepo.WithByKey("AppStoreLastModified"))
|
||||||
if exist.ID == 0 {
|
if exist.ID == 0 {
|
||||||
_ = settingRepo.Create("AppStoreLastModified", value)
|
return settingRepo.Create("AppStoreLastModified", value)
|
||||||
return nil
|
}
|
||||||
|
case "AppDefaultDomain":
|
||||||
|
exist, _ := settingRepo.Get(settingRepo.WithByKey("AppDefaultDomain"))
|
||||||
|
if exist.ID == 0 {
|
||||||
|
return settingRepo.Create("AppDefaultDomain", value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := settingRepo.Update(key, value); err != nil {
|
if err := settingRepo.Update(key, value); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,5 +39,7 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
|
||||||
appRouter.GET("/ignored/detail", baseApi.GetIgnoredApp)
|
appRouter.GET("/ignored/detail", baseApi.GetIgnoredApp)
|
||||||
appRouter.POST("/installed/update/versions", baseApi.GetUpdateVersions)
|
appRouter.POST("/installed/update/versions", baseApi.GetUpdateVersions)
|
||||||
appRouter.POST("/installed/config/update", baseApi.UpdateAppConfig)
|
appRouter.POST("/installed/config/update", baseApi.UpdateAppConfig)
|
||||||
|
appRouter.POST("/store/update", baseApi.UpdateAppstoreConfig)
|
||||||
|
appRouter.GET("/store/config", baseApi.GetAppstoreConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,4 +263,8 @@ export namespace App {
|
||||||
installID: number;
|
installID: number;
|
||||||
webUI: string;
|
webUI: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AppStoreConfig {
|
||||||
|
defaultDomain: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,3 +110,11 @@ export const GetIgnoredApp = () => {
|
||||||
export const UpdateInstallConfig = (req: App.AppConfigUpdate) => {
|
export const UpdateInstallConfig = (req: App.AppConfigUpdate) => {
|
||||||
return http.post(`apps/installed/config/update`, req);
|
return http.post(`apps/installed/config/update`, req);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const GetAppStoreConfig = () => {
|
||||||
|
return http.get<App.AppStoreConfig>(`apps/store/config`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UpdateAppStoreConfig = (req: App.AppStoreConfig) => {
|
||||||
|
return http.post(`apps/store/update`, req);
|
||||||
|
};
|
||||||
|
|
|
@ -92,6 +92,23 @@ const checkIpV4V6OrDomain = (rule: any, value: any, callback: any) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checkDomainOrIP = (rule: any, value: any, callback: any) => {
|
||||||
|
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||||
|
const ipv6Regex =
|
||||||
|
/^(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
|
||||||
|
const domainRegex = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/i;
|
||||||
|
|
||||||
|
if (ipv4Regex.test(value) || ipv6Regex.test(value) || domainRegex.test(value)) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
callback(new Error(i18n.global.t('commons.rule.domain')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const checkHost = (rule: any, value: any, callback: any) => {
|
const checkHost = (rule: any, value: any, callback: any) => {
|
||||||
if (value === '' || typeof value === 'undefined' || value == null) {
|
if (value === '' || typeof value === 'undefined' || value == null) {
|
||||||
callback(new Error(i18n.global.t('commons.rule.requiredInput')));
|
callback(new Error(i18n.global.t('commons.rule.requiredInput')));
|
||||||
|
@ -577,6 +594,7 @@ interface CommonRule {
|
||||||
filePermission: FormItemRule;
|
filePermission: FormItemRule;
|
||||||
phpExtensions: FormItemRule;
|
phpExtensions: FormItemRule;
|
||||||
supervisorName: FormItemRule;
|
supervisorName: FormItemRule;
|
||||||
|
domainOrIP: FormItemRule;
|
||||||
|
|
||||||
paramCommon: FormItemRule;
|
paramCommon: FormItemRule;
|
||||||
paramComplexity: FormItemRule;
|
paramComplexity: FormItemRule;
|
||||||
|
@ -806,4 +824,8 @@ export const Rules: CommonRule = {
|
||||||
validator: checkIpv4,
|
validator: checkIpv4,
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
|
domainOrIP: {
|
||||||
|
validator: checkDomainOrIP,
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1885,6 +1885,11 @@ const message = {
|
||||||
'Please ensure the machine has an NVIDIA GPU and that NVIDIA drivers and the NVIDIA Docker Container Toolkit are installed',
|
'Please ensure the machine has an NVIDIA GPU and that NVIDIA drivers and the NVIDIA Docker Container Toolkit are installed',
|
||||||
webUI: 'Web Access Address',
|
webUI: 'Web Access Address',
|
||||||
webUIPlaceholder: 'For example: http://example.com:8080/login',
|
webUIPlaceholder: 'For example: http://example.com:8080/login',
|
||||||
|
defaultWebDomain: 'Default Access Address',
|
||||||
|
defaultWebDomainHepler:
|
||||||
|
'The default access is used for application port forwarding. For example, if the application port is 8080, the forwarding address would be http(s)://default-access-address:8080',
|
||||||
|
webUIConfig: 'Please add the access address in the application parameters or the app store settings',
|
||||||
|
toLink: 'Open',
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
website: 'Website',
|
website: 'Website',
|
||||||
|
|
|
@ -1750,6 +1750,11 @@ const message = {
|
||||||
gpuConfigHelper: '請確保機器有 NVIDIA GPU 並且安裝 NVIDIA 驅動 和 NVIDIA docker Container Toolkit',
|
gpuConfigHelper: '請確保機器有 NVIDIA GPU 並且安裝 NVIDIA 驅動 和 NVIDIA docker Container Toolkit',
|
||||||
webUI: 'Web 訪問地址',
|
webUI: 'Web 訪問地址',
|
||||||
webUIPlaceholder: '例如:http://example.com:8080/login',
|
webUIPlaceholder: '例如:http://example.com:8080/login',
|
||||||
|
defaultWebDomain: '默認訪問地址',
|
||||||
|
defaultWebDomainHepler:
|
||||||
|
'默認訪問用於應用端口跳轉,例如應用端口為 8080 則跳轉地址為 http(s)://默認訪問地址:8080',
|
||||||
|
webUIConfig: '請在應用參數或者應用商店設置處添加訪問地址',
|
||||||
|
toLink: '連結',
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
website: '網站',
|
website: '網站',
|
||||||
|
|
|
@ -1751,6 +1751,10 @@ const message = {
|
||||||
gpuConfigHelper: '请确保机器有 NVIDIA GPU 并且安装 NVIDIA 驱动 和 NVIDIA docker Container Toolkit',
|
gpuConfigHelper: '请确保机器有 NVIDIA GPU 并且安装 NVIDIA 驱动 和 NVIDIA docker Container Toolkit',
|
||||||
webUI: 'Web 访问地址',
|
webUI: 'Web 访问地址',
|
||||||
webUIPlaceholder: '例如:http://example.com:8080/login',
|
webUIPlaceholder: '例如:http://example.com:8080/login',
|
||||||
|
defaultWebDomain: '默认访问地址',
|
||||||
|
defaultWebDomainHepler: '默认访问用于应用端口跳转,例如应用端口为 8080 则跳转地址为http(s)://默认访问地址:8080',
|
||||||
|
webUIConfig: '请在应用参数或者应用商店设置处添加访问地址',
|
||||||
|
toLink: '跳转',
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
website: '网站',
|
website: '网站',
|
||||||
|
|
|
@ -50,6 +50,17 @@ const appStoreRouter = {
|
||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'setting',
|
||||||
|
name: 'AppStoreSetting',
|
||||||
|
component: () => import('@/views/app-store/setting/index.vue'),
|
||||||
|
props: true,
|
||||||
|
hidden: true,
|
||||||
|
meta: {
|
||||||
|
activeMenu: '/apps',
|
||||||
|
requiresAuth: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -29,6 +29,10 @@ const buttons = [
|
||||||
path: '/apps/upgrade',
|
path: '/apps/upgrade',
|
||||||
count: 0,
|
count: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.set'),
|
||||||
|
path: '/apps/setting',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const search = () => {
|
const search = () => {
|
||||||
|
|
|
@ -7,27 +7,29 @@
|
||||||
</template>
|
</template>
|
||||||
<div v-if="!edit">
|
<div v-if="!edit">
|
||||||
<el-descriptions border :column="1">
|
<el-descriptions border :column="1">
|
||||||
|
<el-descriptions-item :label="$t('app.webUI')">
|
||||||
|
<span v-if="!openConfig">
|
||||||
|
{{ appConfigUpdate.webUI }}
|
||||||
|
<el-button type="primary" @click="openConfig = true">
|
||||||
|
{{ $t('commons.button.edit') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
<el-input v-else v-model="appConfigUpdate.webUI" :placeholder="$t('app.webUIPlaceholder')">
|
||||||
|
<template #append>
|
||||||
|
<el-button type="primary" @click="updateAppConfig">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-descriptions-item>
|
||||||
<el-descriptions-item v-for="(param, key) in params" :label="getLabel(param)" :key="key">
|
<el-descriptions-item v-for="(param, key) in params" :label="getLabel(param)" :key="key">
|
||||||
<span>{{ param.showValue && param.showValue != '' ? param.showValue : param.value }}</span>
|
<span>{{ param.showValue && param.showValue != '' ? param.showValue : param.value }}</span>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
</el-descriptions>
|
</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>
|
||||||
<div v-else v-loading="loading">
|
<div v-else v-loading="loading">
|
||||||
<el-alert :title="$t('app.updateHelper')" type="warning" :closable="false" class="common-prompt" />
|
<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 @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">
|
<div v-for="(p, index) in params" :key="index">
|
||||||
<el-form-item :prop="p.key" :label="getLabel(p)">
|
<el-form-item :prop="p.key" :label="getLabel(p)">
|
||||||
<el-input
|
<el-input
|
||||||
|
@ -150,6 +152,7 @@ const appConfigUpdate = ref<App.AppConfigUpdate>({
|
||||||
installID: 0,
|
installID: 0,
|
||||||
webUI: '',
|
webUI: '',
|
||||||
});
|
});
|
||||||
|
const openConfig = ref(false);
|
||||||
|
|
||||||
const acceptParams = async (props: ParamProps) => {
|
const acceptParams = async (props: ParamProps) => {
|
||||||
submitModel.value.installId = props.id;
|
submitModel.value.installId = props.id;
|
||||||
|
@ -159,6 +162,7 @@ const acceptParams = async (props: ParamProps) => {
|
||||||
edit.value = false;
|
edit.value = false;
|
||||||
await get();
|
await get();
|
||||||
open.value = true;
|
open.value = true;
|
||||||
|
openConfig.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
|
|
@ -175,23 +175,6 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</span>
|
</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
|
<el-button
|
||||||
class="h-button"
|
class="h-button"
|
||||||
plain
|
plain
|
||||||
|
@ -254,7 +237,6 @@
|
||||||
v-if="installed.httpPort > 0"
|
v-if="installed.httpPort > 0"
|
||||||
@click="goDashboard(installed.httpPort, 'http')"
|
@click="goDashboard(installed.httpPort, 'http')"
|
||||||
class="tagMargin"
|
class="tagMargin"
|
||||||
icon="Position"
|
|
||||||
plain
|
plain
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
|
@ -265,13 +247,60 @@
|
||||||
v-if="installed.httpsPort > 0"
|
v-if="installed.httpsPort > 0"
|
||||||
@click="goDashboard(installed.httpsPort, 'https')"
|
@click="goDashboard(installed.httpsPort, 'https')"
|
||||||
class="tagMargin"
|
class="tagMargin"
|
||||||
icon="Position"
|
|
||||||
plain
|
plain
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
{{ $t('app.busPort') }}:{{ installed.httpsPort }}
|
{{ $t('app.busPort') }}:{{ installed.httpsPort }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
|
<el-popover
|
||||||
|
placement="top-start"
|
||||||
|
trigger="hover"
|
||||||
|
v-if="installed.appType == 'website'"
|
||||||
|
:width="260"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-button plain icon="Promotion" size="small">
|
||||||
|
{{ $t('app.toLink') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr v-if="defaultLink != ''">
|
||||||
|
<td>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
link
|
||||||
|
@click="
|
||||||
|
toLink(
|
||||||
|
defaultLink +
|
||||||
|
':' +
|
||||||
|
installed.httpPort,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ defaultLink + ':' + installed.httpPort }}
|
||||||
|
</el-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="installed.webUI != ''">
|
||||||
|
<td>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
link
|
||||||
|
@click="toLink(installed.webUI)"
|
||||||
|
>
|
||||||
|
{{ installed.webUI }}
|
||||||
|
</el-button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<span v-if="defaultLink == '' && installed.webUI == ''">
|
||||||
|
{{ $t('app.webUIConfig') }}
|
||||||
|
</span>
|
||||||
|
</el-popover>
|
||||||
|
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<span>
|
<span>
|
||||||
{{ $t('app.alreadyRun') }}:
|
{{ $t('app.alreadyRun') }}:
|
||||||
|
@ -339,6 +368,7 @@ import {
|
||||||
SyncInstalledApp,
|
SyncInstalledApp,
|
||||||
AppInstalledDeleteCheck,
|
AppInstalledDeleteCheck,
|
||||||
GetAppTags,
|
GetAppTags,
|
||||||
|
GetAppStoreConfig,
|
||||||
} from '@/api/modules/app';
|
} from '@/api/modules/app';
|
||||||
import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
|
@ -401,6 +431,8 @@ const activeName = ref(i18n.global.t('app.installed'));
|
||||||
const mode = ref('installed');
|
const mode = ref('installed');
|
||||||
const moreTag = ref('');
|
const moreTag = ref('');
|
||||||
const language = getLanguage();
|
const language = getLanguage();
|
||||||
|
const defaultLink = ref('');
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
modifiers: [
|
modifiers: [
|
||||||
{
|
{
|
||||||
|
@ -670,7 +702,17 @@ const toLink = (link: string) => {
|
||||||
window.open(link, '_blank');
|
window.open(link, '_blank');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAppstoreConfig = async () => {
|
||||||
|
try {
|
||||||
|
const res = await GetAppStoreConfig();
|
||||||
|
if (res.data.defaultDomain != '') {
|
||||||
|
defaultLink.value = res.data.defaultDomain;
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
getAppstoreConfig();
|
||||||
const path = router.currentRoute.value.path;
|
const path = router.currentRoute.value.path;
|
||||||
if (path == '/apps/upgrade') {
|
if (path == '/apps/upgrade') {
|
||||||
activeName.value = i18n.global.t('app.canUpgrade');
|
activeName.value = i18n.global.t('app.canUpgrade');
|
||||||
|
|
117
frontend/src/views/app-store/setting/index.vue
Normal file
117
frontend/src/views/app-store/setting/index.vue
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
<template>
|
||||||
|
<LayoutContent :title="$t('commons.button.set')">
|
||||||
|
<template #main>
|
||||||
|
<el-form
|
||||||
|
:model="config"
|
||||||
|
label-position="left"
|
||||||
|
label-width="150px"
|
||||||
|
class="ml-2.5"
|
||||||
|
v-loading="loading"
|
||||||
|
:rules="rules"
|
||||||
|
ref="configForm"
|
||||||
|
>
|
||||||
|
<el-row>
|
||||||
|
<el-col :xs="24" :sm="20" :md="15" :lg="12" :xl="12">
|
||||||
|
<el-form-item :label="$t('app.defaultWebDomain')" prop="defaultDomain">
|
||||||
|
<el-input v-model="config.defaultDomain">
|
||||||
|
<template #prepend>
|
||||||
|
<el-select v-model="protocol" placeholder="Select" class="p-w-100">
|
||||||
|
<el-option label="HTTP" value="http://" />
|
||||||
|
<el-option label="HTTPS" value="https://" />
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<span class="input-help">{{ $t('app.defaultWebDomainHepler') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :disabled="loading" @click="submit()">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
</LayoutContent>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { GetAppStoreConfig, UpdateAppStoreConfig } from '@/api/modules/app';
|
||||||
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import { MsgSuccess } from '@/utils/message';
|
||||||
|
import { FormRules } from 'element-plus';
|
||||||
|
|
||||||
|
const rules = ref<FormRules>({
|
||||||
|
defaultDomain: [Rules.domainOrIP],
|
||||||
|
});
|
||||||
|
const config = ref({
|
||||||
|
defaultDomain: '',
|
||||||
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
const configForm = ref();
|
||||||
|
const protocol = ref('http://');
|
||||||
|
|
||||||
|
function getUrl(url: string) {
|
||||||
|
const regex = /^(https?:\/\/)(.*)/;
|
||||||
|
|
||||||
|
const match = url.match(regex);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const protocol = match[1];
|
||||||
|
const remainder = match[2];
|
||||||
|
return {
|
||||||
|
protocol: protocol,
|
||||||
|
remainder: remainder,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const search = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await GetAppStoreConfig();
|
||||||
|
if (res.data.defaultDomain != '') {
|
||||||
|
const url = getUrl(res.data.defaultDomain);
|
||||||
|
if (url) {
|
||||||
|
config.value.defaultDomain = url.remainder;
|
||||||
|
protocol.value = url.protocol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
if (!configForm.value) return;
|
||||||
|
await configForm.value.validate(async (valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
let defaultDomain = '';
|
||||||
|
if (config.value.defaultDomain) {
|
||||||
|
defaultDomain = protocol.value + config.value.defaultDomain;
|
||||||
|
}
|
||||||
|
const req = {
|
||||||
|
defaultDomain: defaultDomain,
|
||||||
|
};
|
||||||
|
await UpdateAppStoreConfig(req);
|
||||||
|
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||||
|
} catch (error) {
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
search();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
search();
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
Add table
Reference in a new issue