1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-03-17 03:04:46 +08:00

feat: 增加已安装应用的详情页

This commit is contained in:
zhengkunwang223 2023-01-03 14:57:13 +08:00 committed by zhengkunwang223
parent a22794b03c
commit 6d290f6a73
12 changed files with 134 additions and 67 deletions

View File

@ -25,7 +25,6 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
helper.SuccessWithData(c, dto.PageResult{ helper.SuccessWithData(c, dto.PageResult{
Items: list, Items: list,
Total: total, Total: total,
@ -36,7 +35,6 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
helper.SuccessWithData(c, list) helper.SuccessWithData(c, list)
} }
} }
@ -89,7 +87,6 @@ func (b *BaseApi) DeleteCheck(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
return return
} }
checkData, err := appInstallService.DeleteCheck(appInstallId) checkData, err := appInstallService.DeleteCheck(appInstallId)
if err != nil { if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@ -117,7 +114,6 @@ func (b *BaseApi) SearchInstalledBackup(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
helper.SuccessWithData(c, dto.PageResult{ helper.SuccessWithData(c, dto.PageResult{
Items: list, Items: list,
Total: total, Total: total,
@ -134,7 +130,6 @@ func (b *BaseApi) OperateInstalled(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
helper.SuccessWithData(c, nil) helper.SuccessWithData(c, nil)
} }
@ -158,7 +153,6 @@ func (b *BaseApi) GetServices(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
helper.SuccessWithData(c, services) helper.SuccessWithData(c, services)
} }
@ -168,13 +162,11 @@ func (b *BaseApi) GetUpdateVersions(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
return return
} }
versions, err := appInstallService.GetUpdateVersions(appInstallId) versions, err := appInstallService.GetUpdateVersions(appInstallId)
if err != nil { if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
helper.SuccessWithData(c, versions) helper.SuccessWithData(c, versions)
} }
@ -188,12 +180,10 @@ func (b *BaseApi) ChangeAppPort(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return return
} }
if err := appInstallService.ChangeAppPort(req); err != nil { if err := appInstallService.ChangeAppPort(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
helper.SuccessWithData(c, nil) helper.SuccessWithData(c, nil)
} }
@ -203,7 +193,6 @@ func (b *BaseApi) GetDefaultConfig(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
return return
} }
content, err := appInstallService.GetDefaultConfigByKey(key) content, err := appInstallService.GetDefaultConfigByKey(key)
if err != nil { if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
@ -212,3 +201,17 @@ func (b *BaseApi) GetDefaultConfig(c *gin.Context) {
helper.SuccessWithData(c, content) helper.SuccessWithData(c, content)
} }
func (b *BaseApi) GetParams(c *gin.Context) {
appInstallId, err := helper.GetIntParamByKey(c, "appInstallId")
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
return
}
content, err := appInstallService.GetParams(appInstallId)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, content)
}

View File

@ -62,16 +62,17 @@ type Tag struct {
} }
type AppForm struct { type AppForm struct {
FormFields []AppFormFields `json:"form_fields"` FormFields []AppFormFields `json:"formFields"`
} }
type AppFormFields struct { type AppFormFields struct {
Type string `json:"type"` Type string `json:"type"`
LabelZh string `json:"label_zh"` LabelZh string `json:"labelZh"`
LabelEn string `json:"label_en"` LabelEn string `json:"labelEn"`
Required string `json:"required"` Required bool `json:"required"`
Default string `json:"default"` Default interface{} `json:"default"`
EnvKey string `json:"env_variable"` EnvKey string `json:"envKey"`
Disabled bool `json:"disabled"`
} }
type AppResource struct { type AppResource struct {

View File

@ -52,3 +52,8 @@ type AppService struct {
Value string `json:"value"` Value string `json:"value"`
Config interface{} `json:"config"` Config interface{} `json:"config"`
} }
type AppParam struct {
Label string `json:"label"`
Value interface{} `json:"value"`
}

View File

@ -350,6 +350,45 @@ func (a AppInstallService) GetDefaultConfigByKey(key string) (string, error) {
return string(contentByte), nil return string(contentByte), nil
} }
func (a AppInstallService) GetParams(id uint) ([]response.AppParam, error) {
var (
res []response.AppParam
appForm dto.AppForm
envs = make(map[string]interface{})
)
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(id))
if err != nil {
return nil, err
}
detail, err := appDetailRepo.GetFirst(commonRepo.WithByID(install.AppDetailId))
if err != nil {
return nil, err
}
if err := json.Unmarshal([]byte(detail.Params), &appForm); err != nil {
return nil, err
}
if err := json.Unmarshal([]byte(install.Env), &envs); err != nil {
return nil, err
}
for _, form := range appForm.FormFields {
if v, ok := envs[form.EnvKey]; ok {
if form.Type == "service" {
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithServiceName(v.(string)))
res = append(res, response.AppParam{
Label: form.LabelZh,
Value: appInstall.Name,
})
} else {
res = append(res, response.AppParam{
Label: form.LabelZh,
Value: v,
})
}
}
}
return res, nil
}
func syncById(installId uint) error { func syncById(installId uint) error {
appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId)) appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId))
if err != nil { if err != nil {

View File

@ -33,5 +33,6 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) {
appRouter.POST("/installed/port/change", baseApi.ChangeAppPort) appRouter.POST("/installed/port/change", baseApi.ChangeAppPort)
appRouter.GET("/services/:key", baseApi.GetServices) appRouter.GET("/services/:key", baseApi.GetServices)
appRouter.GET("/installed/conf/:key", baseApi.GetDefaultConfig) appRouter.GET("/installed/conf/:key", baseApi.GetDefaultConfig)
appRouter.GET("/installed/params/:appInstallId", baseApi.GetParams)
} }
} }

View File

@ -142,4 +142,9 @@ export namespace App {
version: string; version: string;
detailId: number; detailId: number;
} }
export interface InstallParams {
label: string;
value: string;
}
} }

View File

@ -77,3 +77,7 @@ export const GetAppUpdateVersions = (id: number) => {
export const GetAppDefaultConfig = (key: string) => { export const GetAppDefaultConfig = (key: string) => {
return http.get<string>(`apps/installed/conf/${key}`); return http.get<string>(`apps/installed/conf/${key}`);
}; };
export const GetAppInstallParams = (id: number) => {
return http.get<App.InstallParams[]>(`apps/installed/params/${id}`);
};

View File

@ -811,6 +811,7 @@ export default {
deleteBackupHelper: '同时删除应用备份', deleteBackupHelper: '同时删除应用备份',
noService: '{0}', noService: '{0}',
toInstall: '去安装', toInstall: '去安装',
param: '参数配置',
}, },
website: { website: {
website: '网站', website: '网站',

View File

@ -1,11 +1,5 @@
<template> <template>
<el-dialog <el-dialog v-model="open" :title="$t('app.checkTitle')" width="50%" :close-on-click-modal="false">
v-model="open"
:title="$t('app.checkTitle')"
width="50%"
:close-on-click-modal="false"
:destroy-on-close="true"
>
<el-row> <el-row>
<el-alert <el-alert
type="warning" type="warning"

View File

@ -0,0 +1,45 @@
<template>
<el-dialog v-model="open" :title="$t('app.param')" width="30%" :close-on-click-modal="false">
<el-descriptions border :column="1">
<el-descriptions-item v-for="(param, key) in params" :label="param.label" :key="key">
{{ param.value }}
</el-descriptions-item>
</el-descriptions>
</el-dialog>
</template>
<script lang="ts" setup>
import { App } from '@/api/interface/app';
import { GetAppInstallParams } from '@/api/modules/app';
import { ref } from 'vue';
interface ParamProps {
id: Number;
}
const paramData = ref<ParamProps>({
id: 0,
});
let open = ref(false);
let loading = ref(false);
const params = ref<App.InstallParams[]>();
const acceptParams = (props: ParamProps) => {
params.value = [];
paramData.value.id = props.id;
get();
open.value = true;
};
const get = async () => {
try {
loading.value = true;
const res = await GetAppInstallParams(Number(paramData.value.id));
params.value = res.data;
} catch (error) {
} finally {
loading.value = false;
}
};
defineExpose({ acceptParams });
</script>

View File

@ -18,7 +18,9 @@
</template> </template>
<el-table-column :label="$t('app.name')" prop="name" min-width="150px" show-overflow-tooltip> <el-table-column :label="$t('app.name')" prop="name" min-width="150px" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
{{ row.name }} <el-link :underline="false" @click="openParam(row.id)" type="primary">
{{ row.name }}
</el-link>
<el-tag round effect="dark" v-if="row.canUpdate">{{ $t('app.canUpdate') }}</el-tag> <el-tag round effect="dark" v-if="row.canUpdate">{{ $t('app.canUpdate') }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
@ -32,6 +34,7 @@
</el-link> </el-link>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('app.status')"> <el-table-column :label="$t('app.status')">
<template #default="{ row }"> <template #default="{ row }">
<el-popover <el-popover
@ -101,6 +104,7 @@
<Backups ref="backupRef" @close="search"></Backups> <Backups ref="backupRef" @close="search"></Backups>
<AppResources ref="checkRef"></AppResources> <AppResources ref="checkRef"></AppResources>
<AppDelete ref="deleteRef" @close="search"></AppDelete> <AppDelete ref="deleteRef" @close="search"></AppDelete>
<AppParams ref="appParamRef"></AppParams>
</el-card> </el-card>
</template> </template>
@ -120,8 +124,8 @@ import { ElMessage, ElMessageBox } from 'element-plus';
import Backups from './backups.vue'; import Backups from './backups.vue';
import AppResources from './check/index.vue'; import AppResources from './check/index.vue';
import AppDelete from './delete/index.vue'; import AppDelete from './delete/index.vue';
import AppParams from './detail/index.vue';
import { App } from '@/api/interface/app'; import { App } from '@/api/interface/app';
// import { useDeleteData } from '@/hooks/use-delete-data';
import Status from '@/components/status/index.vue'; import Status from '@/components/status/index.vue';
let data = ref<any>(); let data = ref<any>();
@ -142,6 +146,7 @@ let versions = ref<App.VersionDetail[]>();
const backupRef = ref(); const backupRef = ref();
const checkRef = ref(); const checkRef = ref();
const deleteRef = ref(); const deleteRef = ref();
const appParamRef = ref();
let searchName = ref(''); let searchName = ref('');
const sync = () => { const sync = () => {
@ -187,9 +192,6 @@ const openOperate = (row: any, op: string) => {
checkRef.value.acceptParams({ items: items }); checkRef.value.acceptParams({ items: items });
} else { } else {
deleteRef.value.acceptParams(row); deleteRef.value.acceptParams(row);
// await useDeleteData(InstalledOp, operateReq, 'app.deleteWarn');
// search();
} }
}); });
} else { } else {
@ -281,6 +283,10 @@ const openBackups = (installId: number, installName: string) => {
backupRef.value.acceptParams(params); backupRef.value.acceptParams(params);
}; };
const openParam = (installId: number) => {
appParamRef.value.acceptParams({ id: installId });
};
onMounted(() => { onMounted(() => {
search(); search();
timer = setInterval(() => { timer = setInterval(() => {

View File

@ -98,43 +98,6 @@ const copyText = async (msg) => {
} }
}; };
// const copyText = async (text: string) => {
// try {
// try {
// await navigator.clipboard.writeText(text);
// ElMessage.success(i18n.global.t('commons.msg.copySuccess'));
// return await Promise.resolve();
// } catch (err) {
// return await Promise.reject(err);
// }
// } catch (e) {
// let input = document.createElement('input');
// input.style.position = 'fixed';
// input.style.top = '-10000px';
// input.style.zIndex = '-999';
// document.body.appendChild(input);
// console.log('input', input);
// input.value = text;
// input.focus();
// input.select();
// try {
// let result = document.execCommand('copy');
// document.body.removeChild(input);
// if (!result) {
// ElMessage.error(i18n.global.t('commons.msg.copyfailed'));
// return Promise.reject();
// } else {
// ElMessage.success(i18n.global.t('commons.msg.copySuccess'));
// return Promise.resolve();
// }
// } catch (e) {
// document.body.removeChild(input);
// ElMessage.error(i18n.global.t('commons.msg.copyfailed'));
// return Promise.reject();
// }
// }
// };
defineExpose({ defineExpose({
acceptParams, acceptParams,
}); });