From ce19107c95c5116eee8dcce91d8a8964b6720474 Mon Sep 17 00:00:00 2001 From: zhengkunwang223 <31820853+zhengkunwang223@users.noreply.github.com> Date: Mon, 22 May 2023 17:10:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B7=B2=E5=AE=89=E8=A3=85=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E5=A2=9E=E5=8A=A0=E6=89=93=E5=BC=80=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=8A=9F=E8=83=BD=20(#1100)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/app.go | 10 +++++++++ backend/app/dto/response/app.go | 1 + backend/app/service/app.go | 7 +++++-- backend/app/service/app_utils.go | 1 + backend/i18n/i18n.go | 7 +++++++ backend/i18n/lang/en.yaml | 5 +---- backend/i18n/lang/zh.yaml | 5 +---- frontend/src/api/interface/app.ts | 1 + frontend/src/global/business.ts | 15 +++++++++++++ frontend/src/lang/modules/en.ts | 1 + frontend/src/lang/modules/zh.ts | 1 + frontend/src/views/app-store/apps/index.vue | 8 +++++-- frontend/src/views/app-store/detail/index.vue | 12 +++++------ .../views/app-store/detail/install/index.vue | 8 +++---- .../app-store/installed/detail/index.vue | 13 ++++++------ .../src/views/app-store/installed/index.vue | 21 ++++++++++++++----- 16 files changed, 82 insertions(+), 34 deletions(-) create mode 100644 frontend/src/global/business.ts diff --git a/backend/app/api/v1/app.go b/backend/app/api/v1/app.go index a23e272b7..e8b49c528 100644 --- a/backend/app/api/v1/app.go +++ b/backend/app/api/v1/app.go @@ -5,6 +5,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto/request" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/global" + "github.com/1Panel-dev/1Panel/backend/i18n" "github.com/gin-gonic/gin" ) @@ -39,6 +40,15 @@ func (b *BaseApi) SearchApp(c *gin.Context) { // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"} func (b *BaseApi) SyncApp(c *gin.Context) { go appService.SyncAppListFromLocal() + res, err := appService.GetAppUpdate() + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + if !res.CanUpdate { + helper.SuccessWithMsg(c, i18n.GetMsgByKey("AppStoreIsUpToDate")) + return + } go func() { global.LOG.Infof("sync app list start ...") if err := appService.SyncAppListFromRemote(); err != nil { diff --git a/backend/app/dto/response/app.go b/backend/app/dto/response/app.go index a848cb6a1..05a24dc03 100644 --- a/backend/app/dto/response/app.go +++ b/backend/app/dto/response/app.go @@ -56,6 +56,7 @@ type AppInstalledDTO struct { AppName string `json:"appName"` Icon string `json:"icon"` CanUpdate bool `json:"canUpdate"` + Path string `json:"path"` } type DatabaseConn struct { diff --git a/backend/app/service/app.go b/backend/app/service/app.go index 8c3ee7915..e488c8b47 100644 --- a/backend/app/service/app.go +++ b/backend/app/service/app.go @@ -385,7 +385,6 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) { res.CanUpdate = true return res, err } - res.CanUpdate = true return res, nil } @@ -665,7 +664,6 @@ func (a AppService) SyncAppListFromRemote() error { return err } if !updateRes.CanUpdate { - //global.LOG.Infof("The latest version is [%s] The app store is already up to date", updateRes.Version) return nil } var ( @@ -836,6 +834,11 @@ func (a AppService) SyncAppListFromRemote() error { return err } } + if len(deleteDetails) > 0 { + if err := appDetailRepo.BatchDelete(ctx, addDetails); err != nil { + return err + } + } for _, u := range updateDetails { if err := appDetailRepo.Update(ctx, u); err != nil { return err diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index ce833bcc3..3004ca322 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -646,6 +646,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool) ([]respons } installDTO := response.AppInstalledDTO{ AppInstall: installed, + Path: installed.GetPath(), } app, err := appRepo.GetFirst(commonRepo.WithByID(installed.AppId)) if err != nil { diff --git a/backend/i18n/i18n.go b/backend/i18n/i18n.go index f6f76007f..10e5c6feb 100644 --- a/backend/i18n/i18n.go +++ b/backend/i18n/i18n.go @@ -46,6 +46,13 @@ func GetErrMsg(key string, maps map[string]interface{}) string { return content } +func GetMsgByKey(key string) string { + content := ginI18n.MustGetMessage(&i18n.LocalizeConfig{ + MessageID: key, + }) + return content +} + //go:embed lang/* var fs embed.FS diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index 1218304d6..b01ee7833 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -17,7 +17,6 @@ ErrRepoNotValid: "Remote repository verification failed!" ErrNameIsExist: "Name is already exist" ErrDemoEnvironment: "Demo server, prohibit this operation!" ErrCmdTimeout: "Command execution timed out!" -ErrInitUser: "The user initialization has been completed by the system. Please do not repeat the operation!" #app ErrPortInUsed: "{{ .detail }} port already in use" @@ -31,6 +30,7 @@ ErrUpdateBuWebsite: 'The application was updated successfully, but the modificat Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }}' ErrFileParse: 'Application docker-compose file parsing failed!' ErrInstallDirNotFound: 'installation directory does not exist' +AppStoreIsUpToDate: 'The app store is already up to date!' #file ErrFileCanNotRead: "File can not read" @@ -46,8 +46,6 @@ ErrDomainIsExist: "Domain is already exist" ErrAliasIsExist: "Alias is already exist" ErrAppDelete: 'Other Website use this App' ErrGroupIsUsed: 'The group is in use and cannot be deleted' -ErrUsernameIsExist: 'Username is already exist' -ErrUsernameIsNotExist: 'Username is not exist' #ssl ErrSSLCannotDelete: "The certificate is being used by the website and cannot be removed" @@ -66,7 +64,6 @@ ErrTypeOfRedis: "The recovery file type does not match the current persistence m #container ErrInUsed: "{{ .detail }} is in use and cannot be deleted" ErrObjectInUsed: "This object is in use and cannot be deleted" -ErrPortRules: "Invalid port specification" #runtime ErrDirNotFound: "The build folder does not exist! Please check file integrity!" diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index 734b817f9..86dc3814c 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -17,7 +17,6 @@ ErrRepoNotValid: "远程仓库校验失败!" ErrNameIsExist: "名称已存在" ErrDemoEnvironment: "演示服务器,禁止此操作!" ErrCmdTimeout: "命令执行超时!" -ErrInitUser: "系统已完成用户初始化,请勿重复操作!" #app ErrPortInUsed: "{{ .detail }} 端口已被占用!" @@ -31,6 +30,7 @@ ErrUpdateBuWebsite: '应用更新成功,但是网站配置文件修改失败 Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}' ErrFileParse: '应用 docker-compose 文件解析失败!' ErrInstallDirNotFound: '安装目录不存在' +AppStoreIsUpToDate: '应用商店已经是最新版本' #file ErrFileCanNotRead: "此文件不支持预览" @@ -46,8 +46,6 @@ ErrDomainIsExist: "域名已存在" ErrAliasIsExist: "代号已存在" ErrAppDelete: '其他网站使用此应用,无法删除' ErrGroupIsUsed: '分组正在使用中,无法删除' -ErrUsernameIsExist: '用户名已存在' -ErrUsernameIsNotExist: '用户不存在' #ssl ErrSSLCannotDelete: "证书正在被网站使用,无法删除" @@ -66,7 +64,6 @@ ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后 #container ErrInUsed: "{{ .detail }} 正被使用,无法删除" ErrObjectInUsed: "该对象正被使用,无法删除" -ErrPortRules: "无效的端口规格" #runtime ErrDirNotFound: "build 文件夹不存在!请检查文件完整性!" diff --git a/frontend/src/api/interface/app.ts b/frontend/src/api/interface/app.ts index e1c52d7eb..6eaddaae7 100644 --- a/frontend/src/api/interface/app.ts +++ b/frontend/src/api/interface/app.ts @@ -112,6 +112,7 @@ export namespace App { message: string; icon: string; canUpdate: boolean; + path: string; app: App; } diff --git a/frontend/src/global/business.ts b/frontend/src/global/business.ts new file mode 100644 index 000000000..f126fc705 --- /dev/null +++ b/frontend/src/global/business.ts @@ -0,0 +1,15 @@ +import router from '@/routers'; + +export function canEditPort(app: any): boolean { + if (app.key == 'openresty') { + return false; + } + if (app.type == 'php') { + return false; + } + return true; +} + +export function toFolder(folder: string) { + router.push({ path: '/hosts/files', query: { path: folder } }); +} diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 0540b70b7..bc6c9e889 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -1113,6 +1113,7 @@ const message = { appInstallWarn: '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', }, website: { website: 'Website', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index f62a42da0..9c4bcc748 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1106,6 +1106,7 @@ const message = { allowPortHelper: '允许外部端口访问会放开防火墙端口,php运行环境请勿放开', appInstallWarn: '应用默认不放开外部访问端口,可以在高级设置中选择放开', upgradeStart: '开始升级!请稍后刷新页面', + toFolder: '打开安装目录', }, website: { website: '网站', diff --git a/frontend/src/views/app-store/apps/index.vue b/frontend/src/views/app-store/apps/index.vue index 8a975e031..d2b96bbb3 100644 --- a/frontend/src/views/app-store/apps/index.vue +++ b/frontend/src/views/app-store/apps/index.vue @@ -154,8 +154,12 @@ const getAppDetail = (key: string) => { const sync = () => { loading.value = true; SyncApp() - .then(() => { - MsgSuccess(i18n.global.t('app.syncStart')); + .then((res) => { + if (res.message != '') { + MsgSuccess(res.message); + } else { + MsgSuccess(i18n.global.t('app.syncStart')); + } canUpdate.value = false; search(req); }) diff --git a/frontend/src/views/app-store/detail/index.vue b/frontend/src/views/app-store/detail/index.vue index e05fd221c..f0bb1b3aa 100644 --- a/frontend/src/views/app-store/detail/index.vue +++ b/frontend/src/views/app-store/detail/index.vue @@ -111,12 +111,11 @@ const props = withDefaults(defineProps(), { // id: 0, appKey: '', }); -let app = ref({}); -let appDetail = ref({}); -let version = ref(''); -let loadingDetail = ref(false); -let loadingApp = ref(false); -// let appKey = ref(); +const app = ref({}); +const appDetail = ref({}); +const version = ref(''); +const loadingDetail = ref(false); +const loadingApp = ref(false); const installRef = ref(); const getApp = async () => { @@ -150,6 +149,7 @@ const openInstall = () => { let params = { params: appDetail.value.params, appDetailId: appDetail.value.id, + app: app.value, }; 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 3e9f9b573..6f89039de 100644 --- a/frontend/src/views/app-store/detail/install/index.vue +++ b/frontend/src/views/app-store/detail/install/index.vue @@ -62,7 +62,7 @@ {{ $t('container.limitHelper') }} - + {{ $t('app.allowPortHelper') }} @@ -86,6 +86,7 @@ import { App } from '@/api/interface/app'; import { InstallApp } from '@/api/modules/app'; import { Rules, checkNumberRange } from '@/global/form-rules'; +import { canEditPort } from '@/global/business'; import { FormInstance, FormRules } from 'element-plus'; import { reactive, ref } from 'vue'; import { useRouter } from 'vue-router'; @@ -97,10 +98,12 @@ const router = useRouter(); interface InstallRrops { appDetailId: number; params?: App.AppParams; + app: any; } const installData = ref({ appDetailId: 0, + app: {}, }); const open = ref(false); const rules = ref({ @@ -112,9 +115,7 @@ const rules = ref({ }); const loading = ref(false); const paramForm = ref(); - const form = ref<{ [key: string]: any }>({}); - const initData = () => ({ appDetailId: 0, params: form.value, @@ -126,7 +127,6 @@ const initData = () => ({ containerName: '', allowPort: false, }); - const req = reactive(initData()); const handleClose = () => { diff --git a/frontend/src/views/app-store/installed/detail/index.vue b/frontend/src/views/app-store/installed/detail/index.vue index 94642524e..52de0761a 100644 --- a/frontend/src/views/app-store/installed/detail/index.vue +++ b/frontend/src/views/app-store/installed/detail/index.vue @@ -2,7 +2,7 @@