diff --git a/backend/app/dto/request/runtime.go b/backend/app/dto/request/runtime.go index 187937dc9..56f89939d 100644 --- a/backend/app/dto/request/runtime.go +++ b/backend/app/dto/request/runtime.go @@ -17,6 +17,7 @@ type RuntimeCreate struct { Image string `json:"image"` Type string `json:"type"` Version string `json:"version"` + Source string `json:"source"` } type RuntimeDelete struct { @@ -30,4 +31,5 @@ type RuntimeUpdate struct { Image string `json:"image"` Version string `json:"version"` Rebuild bool `json:"rebuild"` + Source string `json:"source"` } diff --git a/backend/app/dto/response/runtime.go b/backend/app/dto/response/runtime.go index b6674d284..3c0a652e2 100644 --- a/backend/app/dto/response/runtime.go +++ b/backend/app/dto/response/runtime.go @@ -6,4 +6,5 @@ type RuntimeRes struct { model.Runtime AppParams []AppParam `json:"appParams"` AppID uint `json:"appId"` + Source string `json:"source"` } diff --git a/backend/app/service/runtime.go b/backend/app/service/runtime.go index 411a97f8e..7d0ad3def 100644 --- a/backend/app/service/runtime.go +++ b/backend/app/service/runtime.go @@ -94,7 +94,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) { return } } - composeContent, envContent, forms, err := handleParams(create.Image, create.Type, newNameDir, create.Params) + composeContent, envContent, forms, err := handleParams(create.Image, create.Type, newNameDir, create.Source, create.Params) if err != nil { return } @@ -197,6 +197,9 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeRes, error) { if err != nil { return nil, err } + if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok { + res.Source = v + } for _, form := range appForm.FormFields { if v, ok := envs[form.EnvKey]; ok { appParam := response.AppParam{ @@ -252,7 +255,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error { return buserr.New(constant.ErrImageExist) } runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name) - composeContent, envContent, _, err := handleParams(req.Image, runtime.Type, runtimeDir, req.Params) + composeContent, envContent, _, err := handleParams(req.Image, runtime.Type, runtimeDir, req.Source, req.Params) if err != nil { return err } diff --git a/backend/app/service/runtime_utils.go b/backend/app/service/runtime_utils.go index a36988cf3..da81b4103 100644 --- a/backend/app/service/runtime_utils.go +++ b/backend/app/service/runtime_utils.go @@ -89,7 +89,7 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) { _ = runtimeRepo.Save(runtime) } -func handleParams(image, runtimeType, runtimeDir string, params map[string]interface{}) (composeContent []byte, envContent []byte, forms []byte, err error) { +func handleParams(image, runtimeType, runtimeDir, source string, params map[string]interface{}) (composeContent []byte, envContent []byte, forms []byte, err error) { fileOp := files.NewFileOp() composeContent, err = fileOp.GetContent(path.Join(runtimeDir, "docker-compose.yml")) if err != nil { @@ -114,6 +114,7 @@ func handleParams(image, runtimeType, runtimeDir string, params map[string]inter params["PHP_EXTENSIONS"] = strings.Join(strArray, ",") } } + params["CONTAINER_PACKAGE_URL"] = source } newMap := make(map[string]string) handleMap(params, newMap) diff --git a/frontend/src/api/interface/runtime.ts b/frontend/src/api/interface/runtime.ts index f78aa431b..d951a2fc7 100644 --- a/frontend/src/api/interface/runtime.ts +++ b/frontend/src/api/interface/runtime.ts @@ -23,6 +23,7 @@ export namespace Runtime { export interface RuntimeDTO extends Runtime { appParams: App.InstallParams[]; appId: number; + source?: string; } export interface RuntimeCreate { @@ -36,6 +37,7 @@ export namespace Runtime { appId?: number; version?: string; rebuild?: boolean; + source?: string; } export interface RuntimeUpdate { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index f81f26802..58bbff8bc 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -1658,6 +1658,15 @@ const message = { phpPluginHelper: 'View PHP extension list ', rebuild: 'Rebuild PHP App', + source: 'PHP extension source', + ustc: 'University of Science and Technology of China', + netease: 'Netease', + aliyun: 'Alibaba Cloud', + default: 'default', + tsinghua: 'Tsinghua University', + xtomhk: 'XTOM Mirror Station (Hong Kong)', + xtom: 'XTOM Mirror Station (Global)', + phpsourceHelper: 'Choose the appropriate source according to your network environment', }, process: { pid: 'Process ID', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 048fa7ee6..7877c7126 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -1569,6 +1569,15 @@ const message = { phpPluginHelper: "查看 PHP 擴展列表 ", rebuild: '重建 PHP 應用', + source: 'PHP 擴展源', + ustc: '中國科學技術大學', + netease: '網易', + aliyun: '阿里雲', + default: '默認', + tsinghua: '清華大學', + xtomhk: 'XTOM 鏡像站(香港)', + xtom: 'XTOM 鏡像站(全球)', + phpsourceHelper: '根據你的網絡環境選擇合適的源', }, process: { pid: '進程ID', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 5a7fe6ab4..9af138269 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1569,6 +1569,15 @@ const message = { phpPluginHelper: "查看 PHP 扩展列表 ", rebuild: '重建 PHP 应用', + source: 'PHP 扩展源', + ustc: '中国科学技术大学', + netease: '网易', + aliyun: '阿里云', + default: '默认', + tsinghua: '清华大学', + xtomhk: 'XTOM 镜像站(香港)', + xtom: 'XTOM 镜像站(全球)', + phpsourceHelper: '根据你的网络环境选择合适的源', }, process: { pid: '进程ID', diff --git a/frontend/src/views/website/runtime/create/index.vue b/frontend/src/views/website/runtime/create/index.vue index b92f1738c..957e7129c 100644 --- a/frontend/src/views/website/runtime/create/index.vue +++ b/frontend/src/views/website/runtime/create/index.vue @@ -63,44 +63,60 @@ - - -
- - - - - - - - {{ $t('runtime.extendHelper') }} - -
-
-
-
+
+ + + + + + + + + {{ $t('runtime.phpsourceHelper') }} + + + + + - - {{ $t('runtime.rebuild') }} - + - {{ $t('runtime.rebuildHelper') }} + {{ $t('runtime.extendHelper') }} +
+
+ + + {{ $t('runtime.rebuild') }} + + + + + {{ $t('runtime.rebuildHelper') }} +
+
+
+
@@ -160,23 +176,59 @@ const appReq = reactive({ page: 1, pageSize: 20, }); -const runtime = ref({ +const initData = (type: string) => ({ name: '', appDetailId: undefined, image: '', params: {}, - type: 'php', + type: type, resource: 'appstore', rebuild: false, + source: 'mirrors.ustc.edu.cn', }); + +let runtime = reactive(initData('php')); + const rules = ref({ name: [Rules.appName], resource: [Rules.requiredInput], appId: [Rules.requiredSelect], version: [Rules.requiredInput, Rules.paramCommon], image: [Rules.requiredInput, Rules.imageName], + source: [Rules.requiredSelect], }); +const phpSources = [ + { + label: i18n.global.t('runtime.ustc'), + value: 'mirrors.ustc.edu.cn', + }, + { + label: i18n.global.t('runtime.netease'), + value: 'mirrors.163.com', + }, + { + label: i18n.global.t('runtime.aliyun'), + value: 'mirrors.aliyun.com', + }, + { + label: i18n.global.t('runtime.tsinghua'), + value: 'mirrors.tuna.tsinghua.edu.cn', + }, + { + label: i18n.global.t('runtime.xtomhk'), + value: 'mirrors.xtom.com.hk', + }, + { + label: i18n.global.t('runtime.xtom'), + value: 'mirrors.xtom.com', + }, + { + label: i18n.global.t('runtime.default'), + value: 'dl-cdn.alpinelinux.org', + }, +]; + const em = defineEmits(['close']); const handleClose = () => { @@ -186,12 +238,12 @@ const handleClose = () => { const changeResource = (resource: string) => { if (resource === 'local') { - runtime.value.appDetailId = undefined; - runtime.value.version = ''; - runtime.value.params = {}; - runtime.value.image = ''; + runtime.appDetailId = undefined; + runtime.version = ''; + runtime.params = {}; + runtime.image = ''; } else { - runtime.value.version = ''; + runtime.version = ''; searchApp(null); } }; @@ -201,7 +253,7 @@ const searchApp = (appId: number) => { apps.value = res.data.items || []; if (res.data && res.data.items && res.data.items.length > 0) { if (appId == null) { - runtime.value.appId = res.data.items[0].id; + runtime.appId = res.data.items[0].id; getApp(res.data.items[0].key, mode.value); } else { res.data.items.forEach((item) => { @@ -227,10 +279,10 @@ const changeApp = (appId: number) => { const changeVersion = () => { loading.value = true; initParam.value = false; - GetAppDetail(runtime.value.appId, runtime.value.version, 'runtime') + GetAppDetail(runtime.appId, runtime.version, 'runtime') .then((res) => { - runtime.value.appDetailId = res.data.id; - runtime.value.image = res.data.image + ':' + runtime.value.version; + runtime.appDetailId = res.data.id; + runtime.image = res.data.image + ':' + runtime.version; appParams.value = res.data.params; initParam.value = true; }) @@ -243,7 +295,7 @@ const getApp = (appkey: string, mode: string) => { GetApp(appkey).then((res) => { appVersions.value = res.data.versions || []; if (res.data.versions.length > 0) { - runtime.value.version = res.data.versions[0]; + runtime.version = res.data.versions[0]; if (mode === 'create') { changeVersion(); } else { @@ -261,7 +313,7 @@ const submit = async (formEl: FormInstance | undefined) => { } if (mode.value == 'create') { loading.value = true; - CreateRuntime(runtime.value) + CreateRuntime(runtime) .then(() => { MsgSuccess(i18n.global.t('commons.msg.createSuccess')); handleClose(); @@ -271,7 +323,7 @@ const submit = async (formEl: FormInstance | undefined) => { }); } else { loading.value = true; - UpdateRuntime(runtime.value) + UpdateRuntime(runtime) .then(() => { MsgSuccess(i18n.global.t('commons.msg.updateSuccess')); handleClose(); @@ -287,7 +339,7 @@ const getRuntime = async (id: number) => { try { const res = await GetRuntime(id); const data = res.data; - runtime.value = { + Object.assign(runtime, { id: data.id, name: data.name, appDetailId: data.appDetailId, @@ -298,7 +350,8 @@ const getRuntime = async (id: number) => { appId: data.appId, version: data.version, rebuild: true, - }; + source: data.source, + }); editParams.value = data.appParams; if (mode.value == 'create') { searchApp(data.appId); @@ -312,16 +365,10 @@ const acceptParams = async (props: OperateRrops) => { mode.value = props.mode; initParam.value = false; if (props.mode === 'create') { - runtime.value = { - name: '', - appDetailId: undefined, - image: '', - params: {}, - type: props.type, - resource: 'appstore', - }; + Object.assign(runtime, initData(props.type)); searchApp(null); } else { + searchApp(null); getRuntime(props.id); } open.value = true;