mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 16:29:17 +08:00
feat: 已安装应用增加打开安装目录功能 (#1100)
This commit is contained in:
parent
7c56ed7b16
commit
ce19107c95
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
|
"github.com/1Panel-dev/1Panel/backend/i18n"
|
||||||
"github.com/gin-gonic/gin"
|
"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"}
|
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"应用商店同步","formatEN":"App store synchronization"}
|
||||||
func (b *BaseApi) SyncApp(c *gin.Context) {
|
func (b *BaseApi) SyncApp(c *gin.Context) {
|
||||||
go appService.SyncAppListFromLocal()
|
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() {
|
go func() {
|
||||||
global.LOG.Infof("sync app list start ...")
|
global.LOG.Infof("sync app list start ...")
|
||||||
if err := appService.SyncAppListFromRemote(); err != nil {
|
if err := appService.SyncAppListFromRemote(); err != nil {
|
||||||
|
@ -56,6 +56,7 @@ type AppInstalledDTO struct {
|
|||||||
AppName string `json:"appName"`
|
AppName string `json:"appName"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
CanUpdate bool `json:"canUpdate"`
|
CanUpdate bool `json:"canUpdate"`
|
||||||
|
Path string `json:"path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DatabaseConn struct {
|
type DatabaseConn struct {
|
||||||
|
@ -385,7 +385,6 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
|
|||||||
res.CanUpdate = true
|
res.CanUpdate = true
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
res.CanUpdate = true
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,7 +664,6 @@ func (a AppService) SyncAppListFromRemote() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !updateRes.CanUpdate {
|
if !updateRes.CanUpdate {
|
||||||
//global.LOG.Infof("The latest version is [%s] The app store is already up to date", updateRes.Version)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
@ -836,6 +834,11 @@ func (a AppService) SyncAppListFromRemote() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(deleteDetails) > 0 {
|
||||||
|
if err := appDetailRepo.BatchDelete(ctx, addDetails); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, u := range updateDetails {
|
for _, u := range updateDetails {
|
||||||
if err := appDetailRepo.Update(ctx, u); err != nil {
|
if err := appDetailRepo.Update(ctx, u); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -646,6 +646,7 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool) ([]respons
|
|||||||
}
|
}
|
||||||
installDTO := response.AppInstalledDTO{
|
installDTO := response.AppInstalledDTO{
|
||||||
AppInstall: installed,
|
AppInstall: installed,
|
||||||
|
Path: installed.GetPath(),
|
||||||
}
|
}
|
||||||
app, err := appRepo.GetFirst(commonRepo.WithByID(installed.AppId))
|
app, err := appRepo.GetFirst(commonRepo.WithByID(installed.AppId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -46,6 +46,13 @@ func GetErrMsg(key string, maps map[string]interface{}) string {
|
|||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetMsgByKey(key string) string {
|
||||||
|
content := ginI18n.MustGetMessage(&i18n.LocalizeConfig{
|
||||||
|
MessageID: key,
|
||||||
|
})
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
//go:embed lang/*
|
//go:embed lang/*
|
||||||
var fs embed.FS
|
var fs embed.FS
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ ErrRepoNotValid: "Remote repository verification failed!"
|
|||||||
ErrNameIsExist: "Name is already exist"
|
ErrNameIsExist: "Name is already exist"
|
||||||
ErrDemoEnvironment: "Demo server, prohibit this operation!"
|
ErrDemoEnvironment: "Demo server, prohibit this operation!"
|
||||||
ErrCmdTimeout: "Command execution timed out!"
|
ErrCmdTimeout: "Command execution timed out!"
|
||||||
ErrInitUser: "The user initialization has been completed by the system. Please do not repeat the operation!"
|
|
||||||
|
|
||||||
#app
|
#app
|
||||||
ErrPortInUsed: "{{ .detail }} port already in use"
|
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 }}'
|
Err1PanelNetworkFailed: 'Default container network creation failed! {{ .detail }}'
|
||||||
ErrFileParse: 'Application docker-compose file parsing failed!'
|
ErrFileParse: 'Application docker-compose file parsing failed!'
|
||||||
ErrInstallDirNotFound: 'installation directory does not exist'
|
ErrInstallDirNotFound: 'installation directory does not exist'
|
||||||
|
AppStoreIsUpToDate: 'The app store is already up to date!'
|
||||||
|
|
||||||
#file
|
#file
|
||||||
ErrFileCanNotRead: "File can not read"
|
ErrFileCanNotRead: "File can not read"
|
||||||
@ -46,8 +46,6 @@ ErrDomainIsExist: "Domain is already exist"
|
|||||||
ErrAliasIsExist: "Alias is already exist"
|
ErrAliasIsExist: "Alias is already exist"
|
||||||
ErrAppDelete: 'Other Website use this App'
|
ErrAppDelete: 'Other Website use this App'
|
||||||
ErrGroupIsUsed: 'The group is in use and cannot be deleted'
|
ErrGroupIsUsed: 'The group is in use and cannot be deleted'
|
||||||
ErrUsernameIsExist: 'Username is already exist'
|
|
||||||
ErrUsernameIsNotExist: 'Username is not exist'
|
|
||||||
|
|
||||||
#ssl
|
#ssl
|
||||||
ErrSSLCannotDelete: "The certificate is being used by the website and cannot be removed"
|
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
|
#container
|
||||||
ErrInUsed: "{{ .detail }} is in use and cannot be deleted"
|
ErrInUsed: "{{ .detail }} is in use and cannot be deleted"
|
||||||
ErrObjectInUsed: "This object is in use and cannot be deleted"
|
ErrObjectInUsed: "This object is in use and cannot be deleted"
|
||||||
ErrPortRules: "Invalid port specification"
|
|
||||||
|
|
||||||
#runtime
|
#runtime
|
||||||
ErrDirNotFound: "The build folder does not exist! Please check file integrity!"
|
ErrDirNotFound: "The build folder does not exist! Please check file integrity!"
|
||||||
|
@ -17,7 +17,6 @@ ErrRepoNotValid: "远程仓库校验失败!"
|
|||||||
ErrNameIsExist: "名称已存在"
|
ErrNameIsExist: "名称已存在"
|
||||||
ErrDemoEnvironment: "演示服务器,禁止此操作!"
|
ErrDemoEnvironment: "演示服务器,禁止此操作!"
|
||||||
ErrCmdTimeout: "命令执行超时!"
|
ErrCmdTimeout: "命令执行超时!"
|
||||||
ErrInitUser: "系统已完成用户初始化,请勿重复操作!"
|
|
||||||
|
|
||||||
#app
|
#app
|
||||||
ErrPortInUsed: "{{ .detail }} 端口已被占用!"
|
ErrPortInUsed: "{{ .detail }} 端口已被占用!"
|
||||||
@ -31,6 +30,7 @@ ErrUpdateBuWebsite: '应用更新成功,但是网站配置文件修改失败
|
|||||||
Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}'
|
Err1PanelNetworkFailed: '默认容器网络创建失败!{{ .detail }}'
|
||||||
ErrFileParse: '应用 docker-compose 文件解析失败!'
|
ErrFileParse: '应用 docker-compose 文件解析失败!'
|
||||||
ErrInstallDirNotFound: '安装目录不存在'
|
ErrInstallDirNotFound: '安装目录不存在'
|
||||||
|
AppStoreIsUpToDate: '应用商店已经是最新版本'
|
||||||
|
|
||||||
#file
|
#file
|
||||||
ErrFileCanNotRead: "此文件不支持预览"
|
ErrFileCanNotRead: "此文件不支持预览"
|
||||||
@ -46,8 +46,6 @@ ErrDomainIsExist: "域名已存在"
|
|||||||
ErrAliasIsExist: "代号已存在"
|
ErrAliasIsExist: "代号已存在"
|
||||||
ErrAppDelete: '其他网站使用此应用,无法删除'
|
ErrAppDelete: '其他网站使用此应用,无法删除'
|
||||||
ErrGroupIsUsed: '分组正在使用中,无法删除'
|
ErrGroupIsUsed: '分组正在使用中,无法删除'
|
||||||
ErrUsernameIsExist: '用户名已存在'
|
|
||||||
ErrUsernameIsNotExist: '用户不存在'
|
|
||||||
|
|
||||||
#ssl
|
#ssl
|
||||||
ErrSSLCannotDelete: "证书正在被网站使用,无法删除"
|
ErrSSLCannotDelete: "证书正在被网站使用,无法删除"
|
||||||
@ -66,7 +64,6 @@ ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后
|
|||||||
#container
|
#container
|
||||||
ErrInUsed: "{{ .detail }} 正被使用,无法删除"
|
ErrInUsed: "{{ .detail }} 正被使用,无法删除"
|
||||||
ErrObjectInUsed: "该对象正被使用,无法删除"
|
ErrObjectInUsed: "该对象正被使用,无法删除"
|
||||||
ErrPortRules: "无效的端口规格"
|
|
||||||
|
|
||||||
#runtime
|
#runtime
|
||||||
ErrDirNotFound: "build 文件夹不存在!请检查文件完整性!"
|
ErrDirNotFound: "build 文件夹不存在!请检查文件完整性!"
|
||||||
|
@ -112,6 +112,7 @@ export namespace App {
|
|||||||
message: string;
|
message: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
canUpdate: boolean;
|
canUpdate: boolean;
|
||||||
|
path: string;
|
||||||
app: App;
|
app: App;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
frontend/src/global/business.ts
Normal file
15
frontend/src/global/business.ts
Normal file
@ -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 } });
|
||||||
|
}
|
@ -1113,6 +1113,7 @@ const message = {
|
|||||||
appInstallWarn:
|
appInstallWarn:
|
||||||
'The application does not release the external access port by default, you can choose to release it in the advanced settings',
|
'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',
|
upgradeStart: 'Start upgrading! Please refresh the page later',
|
||||||
|
toFolder: 'Open the installation directory',
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
website: 'Website',
|
website: 'Website',
|
||||||
|
@ -1106,6 +1106,7 @@ const message = {
|
|||||||
allowPortHelper: '允许外部端口访问会放开防火墙端口,php运行环境请勿放开',
|
allowPortHelper: '允许外部端口访问会放开防火墙端口,php运行环境请勿放开',
|
||||||
appInstallWarn: '应用默认不放开外部访问端口,可以在高级设置中选择放开',
|
appInstallWarn: '应用默认不放开外部访问端口,可以在高级设置中选择放开',
|
||||||
upgradeStart: '开始升级!请稍后刷新页面',
|
upgradeStart: '开始升级!请稍后刷新页面',
|
||||||
|
toFolder: '打开安装目录',
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
website: '网站',
|
website: '网站',
|
||||||
|
@ -154,8 +154,12 @@ const getAppDetail = (key: string) => {
|
|||||||
const sync = () => {
|
const sync = () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
SyncApp()
|
SyncApp()
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
MsgSuccess(i18n.global.t('app.syncStart'));
|
if (res.message != '') {
|
||||||
|
MsgSuccess(res.message);
|
||||||
|
} else {
|
||||||
|
MsgSuccess(i18n.global.t('app.syncStart'));
|
||||||
|
}
|
||||||
canUpdate.value = false;
|
canUpdate.value = false;
|
||||||
search(req);
|
search(req);
|
||||||
})
|
})
|
||||||
|
@ -111,12 +111,11 @@ const props = withDefaults(defineProps<OperateProps>(), {
|
|||||||
// id: 0,
|
// id: 0,
|
||||||
appKey: '',
|
appKey: '',
|
||||||
});
|
});
|
||||||
let app = ref<any>({});
|
const app = ref<any>({});
|
||||||
let appDetail = ref<any>({});
|
const appDetail = ref<any>({});
|
||||||
let version = ref('');
|
const version = ref('');
|
||||||
let loadingDetail = ref(false);
|
const loadingDetail = ref(false);
|
||||||
let loadingApp = ref(false);
|
const loadingApp = ref(false);
|
||||||
// let appKey = ref();
|
|
||||||
const installRef = ref();
|
const installRef = ref();
|
||||||
|
|
||||||
const getApp = async () => {
|
const getApp = async () => {
|
||||||
@ -150,6 +149,7 @@ const openInstall = () => {
|
|||||||
let params = {
|
let params = {
|
||||||
params: appDetail.value.params,
|
params: appDetail.value.params,
|
||||||
appDetailId: appDetail.value.id,
|
appDetailId: appDetail.value.id,
|
||||||
|
app: app.value,
|
||||||
};
|
};
|
||||||
if (app.value.type === 'php') {
|
if (app.value.type === 'php') {
|
||||||
router.push({ path: '/websites/runtime/php' });
|
router.push({ path: '/websites/runtime/php' });
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
<span class="input-help">{{ $t('container.limitHelper') }}</span>
|
<span class="input-help">{{ $t('container.limitHelper') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="allowPort">
|
<el-form-item prop="allowPort" v-if="canEditPort(installData.app)">
|
||||||
<el-checkbox v-model="req.allowPort" :label="$t('app.allowPort')" size="large" />
|
<el-checkbox v-model="req.allowPort" :label="$t('app.allowPort')" size="large" />
|
||||||
<span class="input-help">{{ $t('app.allowPortHelper') }}</span>
|
<span class="input-help">{{ $t('app.allowPortHelper') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -86,6 +86,7 @@
|
|||||||
import { App } from '@/api/interface/app';
|
import { App } from '@/api/interface/app';
|
||||||
import { InstallApp } from '@/api/modules/app';
|
import { InstallApp } from '@/api/modules/app';
|
||||||
import { Rules, checkNumberRange } from '@/global/form-rules';
|
import { Rules, checkNumberRange } from '@/global/form-rules';
|
||||||
|
import { canEditPort } from '@/global/business';
|
||||||
import { FormInstance, FormRules } from 'element-plus';
|
import { FormInstance, FormRules } from 'element-plus';
|
||||||
import { reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
@ -97,10 +98,12 @@ const router = useRouter();
|
|||||||
interface InstallRrops {
|
interface InstallRrops {
|
||||||
appDetailId: number;
|
appDetailId: number;
|
||||||
params?: App.AppParams;
|
params?: App.AppParams;
|
||||||
|
app: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const installData = ref<InstallRrops>({
|
const installData = ref<InstallRrops>({
|
||||||
appDetailId: 0,
|
appDetailId: 0,
|
||||||
|
app: {},
|
||||||
});
|
});
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const rules = ref<FormRules>({
|
const rules = ref<FormRules>({
|
||||||
@ -112,9 +115,7 @@ const rules = ref<FormRules>({
|
|||||||
});
|
});
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const paramForm = ref<FormInstance>();
|
const paramForm = ref<FormInstance>();
|
||||||
|
|
||||||
const form = ref<{ [key: string]: any }>({});
|
const form = ref<{ [key: string]: any }>({});
|
||||||
|
|
||||||
const initData = () => ({
|
const initData = () => ({
|
||||||
appDetailId: 0,
|
appDetailId: 0,
|
||||||
params: form.value,
|
params: form.value,
|
||||||
@ -126,7 +127,6 @@ const initData = () => ({
|
|||||||
containerName: '',
|
containerName: '',
|
||||||
allowPort: false,
|
allowPort: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const req = reactive(initData());
|
const req = reactive(initData());
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<el-drawer :close-on-click-modal="false" v-model="open" size="40%">
|
<el-drawer :close-on-click-modal="false" v-model="open" size="40%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<Header :header="$t('app.param')" :back="handleClose">
|
<Header :header="$t('app.param')" :back="handleClose">
|
||||||
<template #buttons v-if="canEdit">
|
<template #buttons>
|
||||||
<el-button type="primary" plain @click="editParam" :disabled="loading">
|
<el-button type="primary" plain @click="editParam" :disabled="loading">
|
||||||
{{ edit ? $t('app.detail') : $t('commons.button.edit') }}
|
{{ edit ? $t('app.detail') : $t('commons.button.edit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -75,7 +75,7 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
<span class="input-help">{{ $t('container.limitHelper') }}</span>
|
<span class="input-help">{{ $t('container.limitHelper') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="allowPort">
|
<el-form-item prop="allowPort" v-if="canEditPort(paramData.app)">
|
||||||
<el-checkbox v-model="paramModel.allowPort" :label="$t('app.allowPort')" size="large" />
|
<el-checkbox v-model="paramModel.allowPort" :label="$t('app.allowPort')" size="large" />
|
||||||
<span class="input-help">{{ $t('app.allowPortHelper') }}</span>
|
<span class="input-help">{{ $t('app.allowPortHelper') }}</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -103,12 +103,15 @@ import { FormInstance } from 'element-plus';
|
|||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
|
import { canEditPort } from '@/global/business';
|
||||||
|
|
||||||
interface ParamProps {
|
interface ParamProps {
|
||||||
id: Number;
|
id: Number;
|
||||||
|
app: any;
|
||||||
}
|
}
|
||||||
const paramData = ref<ParamProps>({
|
const paramData = ref<ParamProps>({
|
||||||
id: 0,
|
id: 0,
|
||||||
|
app: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface EditForm extends App.InstallParams {
|
interface EditForm extends App.InstallParams {
|
||||||
@ -127,13 +130,12 @@ const rules = reactive({
|
|||||||
params: {},
|
params: {},
|
||||||
});
|
});
|
||||||
const submitModel = ref<any>({});
|
const submitModel = ref<any>({});
|
||||||
const canEdit = ref(false);
|
|
||||||
|
|
||||||
const acceptParams = async (props: ParamProps) => {
|
const acceptParams = async (props: ParamProps) => {
|
||||||
canEdit.value = true;
|
|
||||||
submitModel.value.installId = props.id;
|
submitModel.value.installId = props.id;
|
||||||
params.value = [];
|
params.value = [];
|
||||||
paramData.value.id = props.id;
|
paramData.value.id = props.id;
|
||||||
|
paramData.value.app = props.app;
|
||||||
edit.value = false;
|
edit.value = false;
|
||||||
await get();
|
await get();
|
||||||
open.value = true;
|
open.value = true;
|
||||||
@ -156,9 +158,6 @@ const get = async () => {
|
|||||||
const configParams = res.data.params || [];
|
const configParams = res.data.params || [];
|
||||||
if (configParams && configParams.length > 0) {
|
if (configParams && configParams.length > 0) {
|
||||||
configParams.forEach((d) => {
|
configParams.forEach((d) => {
|
||||||
if (d.edit) {
|
|
||||||
canEdit.value = true;
|
|
||||||
}
|
|
||||||
let value = d.value;
|
let value = d.value;
|
||||||
if (d.type === 'number') {
|
if (d.type === 'number') {
|
||||||
value = Number(value);
|
value = Number(value);
|
||||||
|
@ -97,11 +97,21 @@
|
|||||||
:content="installed.message"
|
:content="installed.message"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button link type="primary">详情</el-button>
|
<el-button link type="primary">
|
||||||
|
{{ $t('app.detail') }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<el-tooltip effect="dark" :content="$t('app.toFolder')" placement="top">
|
||||||
|
<el-button type="primary" link @click="toFolder(installed.path)">
|
||||||
|
<el-icon>
|
||||||
|
<FolderOpened />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
class="h-button"
|
class="h-button"
|
||||||
type="primary"
|
type="primary"
|
||||||
@ -132,7 +142,7 @@
|
|||||||
plain
|
plain
|
||||||
round
|
round
|
||||||
size="small"
|
size="small"
|
||||||
:disabled="installed.status === 'Upgrading'"
|
:disabled="installed.status === 'Running'"
|
||||||
@click="openOperate(installed, 'upgrade')"
|
@click="openOperate(installed, 'upgrade')"
|
||||||
v-if="mode === 'upgrade'"
|
v-if="mode === 'upgrade'"
|
||||||
>
|
>
|
||||||
@ -210,6 +220,7 @@ import Status from '@/components/status/index.vue';
|
|||||||
import { getAge } from '@/utils/util';
|
import { getAge } from '@/utils/util';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
|
import { toFolder } from '@/global/business';
|
||||||
|
|
||||||
const data = ref<any>();
|
const data = ref<any>();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -392,7 +403,7 @@ const buttons = [
|
|||||||
{
|
{
|
||||||
label: i18n.global.t('app.params'),
|
label: i18n.global.t('app.params'),
|
||||||
click: (row: any) => {
|
click: (row: any) => {
|
||||||
openParam(row.id);
|
openParam(row);
|
||||||
},
|
},
|
||||||
disabled: (row: any) => {
|
disabled: (row: any) => {
|
||||||
return row.status === 'DownloadErr' || row.status === 'Upgrading';
|
return row.status === 'DownloadErr' || row.status === 'Upgrading';
|
||||||
@ -418,8 +429,8 @@ const openUploads = (key: string, name: string) => {
|
|||||||
uploadRef.value.acceptParams(params);
|
uploadRef.value.acceptParams(params);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openParam = (installId: number) => {
|
const openParam = (row: any) => {
|
||||||
appParamRef.value.acceptParams({ id: installId });
|
appParamRef.value.acceptParams({ app: row.app, id: row.id });
|
||||||
};
|
};
|
||||||
|
|
||||||
const isAppErr = (row: any) => {
|
const isAppErr = (row: any) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user