fix: 容器端口跳转样式调整 (#1533)
This commit is contained in:
		| @@ -144,10 +144,11 @@ func (u *ContainerService) Page(req dto.PageContainer) (int64, interface{}, erro | |||||||
|  |  | ||||||
| 			var ports []string | 			var ports []string | ||||||
| 			for _, port := range item.Ports { | 			for _, port := range item.Ports { | ||||||
| 				if port.IP == "::" || port.PublicPort == 0 { | 				itemPortStr := fmt.Sprintf("%v/%s", port.PrivatePort, port.Type) | ||||||
| 					continue | 				if port.PublicPort != 0 { | ||||||
|  | 					itemPortStr = fmt.Sprintf("%s:%v->%v/%s", port.IP, port.PublicPort, port.PrivatePort, port.Type) | ||||||
| 				} | 				} | ||||||
| 				ports = append(ports, fmt.Sprintf("%v:%v/%s", port.PublicPort, port.PrivatePort, port.Type)) | 				ports = append(ports, itemPortStr) | ||||||
| 			} | 			} | ||||||
| 			cpu, mem := loadCpuAndMem(client, item.ID) | 			cpu, mem := loadCpuAndMem(client, item.ID) | ||||||
| 			backDatas[i] = dto.ContainerInfo{ | 			backDatas[i] = dto.ContainerInfo{ | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								frontend/src/components/port-jump/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								frontend/src/components/port-jump/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | <template> | ||||||
|  |     <div> | ||||||
|  |         <el-dialog | ||||||
|  |             v-model="dialogVisiable" | ||||||
|  |             :title="$t('app.checkTitle')" | ||||||
|  |             width="30%" | ||||||
|  |             :close-on-click-modal="false" | ||||||
|  |             :destroy-on-close="true" | ||||||
|  |         > | ||||||
|  |             <el-alert :closable="false" :title="$t('setting.systemIPWarning')" type="info"> | ||||||
|  |                 <el-link icon="Position" @click="goRouter('/settings/panel')" type="primary"> | ||||||
|  |                     {{ $t('firewall.quickJump') }} | ||||||
|  |                 </el-link> | ||||||
|  |             </el-alert> | ||||||
|  |             <template #footer> | ||||||
|  |                 <span class="dialog-footer"> | ||||||
|  |                     <el-button @click="dialogVisiable = false">{{ $t('commons.button.cancel') }}</el-button> | ||||||
|  |                 </span> | ||||||
|  |             </template> | ||||||
|  |         </el-dialog> | ||||||
|  |     </div> | ||||||
|  | </template> | ||||||
|  | <script lang="ts" setup> | ||||||
|  | import { ref } from 'vue'; | ||||||
|  | import { getSettingInfo } from '@/api/modules/setting'; | ||||||
|  | import i18n from '@/lang'; | ||||||
|  | import { MsgError } from '@/utils/message'; | ||||||
|  | import { useRouter } from 'vue-router'; | ||||||
|  | const router = useRouter(); | ||||||
|  |  | ||||||
|  | const dialogVisiable = ref(); | ||||||
|  |  | ||||||
|  | interface DialogProps { | ||||||
|  |     port: any; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const acceptParams = async (params: DialogProps): Promise<void> => { | ||||||
|  |     if (Number(params.port) === 0) { | ||||||
|  |         MsgError(i18n.global.t('setting.errPort')); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     const res = await getSettingInfo(); | ||||||
|  |     if (!res.data.systemIP) { | ||||||
|  |         dialogVisiable.value = true; | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     window.open(`http://${res.data.systemIP}:${params.port}`, '_blank'); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const goRouter = async (path: string) => { | ||||||
|  |     router.push({ path: path }); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | defineExpose({ acceptParams }); | ||||||
|  | </script> | ||||||
| @@ -468,6 +468,7 @@ const message = { | |||||||
|         cleanSuccessWithSpace: |         cleanSuccessWithSpace: | ||||||
|             'The operation is successful. The number of disks cleared this time is {0}. The disk space freed is {1}!', |             'The operation is successful. The number of disks cleared this time is {0}. The disk space freed is {1}!', | ||||||
|         container: 'Container', |         container: 'Container', | ||||||
|  |         unExposedPort: 'The current port mapping address is 127.0.0.1, which cannot enable external access.', | ||||||
|         upTime: 'UpTime', |         upTime: 'UpTime', | ||||||
|         all: 'All', |         all: 'All', | ||||||
|         fetch: 'Fetch', |         fetch: 'Fetch', | ||||||
| @@ -937,7 +938,7 @@ const message = { | |||||||
|         sessionTimeoutHelper: |         sessionTimeoutHelper: | ||||||
|             'If you do not operate the panel for more than {0} seconds, the panel automatically logs out', |             'If you do not operate the panel for more than {0} seconds, the panel automatically logs out', | ||||||
|         systemIP: 'System IP', |         systemIP: 'System IP', | ||||||
|         systemIPWarning: 'Please set the system IP in the panel settings first.', |         systemIPWarning: 'The server IP is not currently set. Please set it in the control panel first!', | ||||||
|         syncTime: 'Server time', |         syncTime: 'Server time', | ||||||
|         timeZone: 'Time Zone', |         timeZone: 'Time Zone', | ||||||
|         timeZoneChangeHelper: 'Changing the time zone requires restarting the service. Do you want to continue?', |         timeZoneChangeHelper: 'Changing the time zone requires restarting the service. Do you want to continue?', | ||||||
|   | |||||||
| @@ -432,7 +432,8 @@ const message = { | |||||||
|         localIP: '本機 IP', |         localIP: '本機 IP', | ||||||
|     }, |     }, | ||||||
|     container: { |     container: { | ||||||
|         createContainer: '創建容器', |         create: '創建容器', | ||||||
|  |         edit: '編輯容器', | ||||||
|         updateContaienrHelper: '容器編輯需要重建容器,任何未持久化的數據將會丟失,是否繼續?', |         updateContaienrHelper: '容器編輯需要重建容器,任何未持久化的數據將會丟失,是否繼續?', | ||||||
|         containerList: '容器列表', |         containerList: '容器列表', | ||||||
|         operatorHelper: '將對選中容器進行 {0} 操作,是否繼續?', |         operatorHelper: '將對選中容器進行 {0} 操作,是否繼續?', | ||||||
| @@ -459,6 +460,7 @@ const message = { | |||||||
|         cleanSuccess: '操作成功,本次清理數量: {0} 個!', |         cleanSuccess: '操作成功,本次清理數量: {0} 個!', | ||||||
|         cleanSuccessWithSpace: '操作成功,本次清理數量: {0} 個,釋放磁盤空間: {1}!', |         cleanSuccessWithSpace: '操作成功,本次清理數量: {0} 個,釋放磁盤空間: {1}!', | ||||||
|         container: '容器', |         container: '容器', | ||||||
|  |         unExposedPort: '當前端口映射地址為 127.0.0.1,無法實現外部訪問', | ||||||
|         upTime: '運行時長', |         upTime: '運行時長', | ||||||
|         all: '全部', |         all: '全部', | ||||||
|         fetch: '過濾', |         fetch: '過濾', | ||||||
| @@ -621,6 +623,8 @@ const message = { | |||||||
|         startIn: '中開啟', |         startIn: '中開啟', | ||||||
|     }, |     }, | ||||||
|     cronjob: { |     cronjob: { | ||||||
|  |         create: '創建計劃任務', | ||||||
|  |         edit: '編輯計劃任務', | ||||||
|         cronTask: '計劃任務', |         cronTask: '計劃任務', | ||||||
|         changeStatus: '狀態修改', |         changeStatus: '狀態修改', | ||||||
|         disableMsg: '停止計劃任務會導致該任務不再自動執行。是否繼續?', |         disableMsg: '停止計劃任務會導致該任務不再自動執行。是否繼續?', | ||||||
| @@ -898,7 +902,7 @@ const message = { | |||||||
|         sessionTimeoutError: '最小超時時間為 300 秒', |         sessionTimeoutError: '最小超時時間為 300 秒', | ||||||
|         sessionTimeoutHelper: '如果用戶超過 {0} 秒未操作面板,面板將自動退出登錄', |         sessionTimeoutHelper: '如果用戶超過 {0} 秒未操作面板,面板將自動退出登錄', | ||||||
|         systemIP: '服務器 IP', |         systemIP: '服務器 IP', | ||||||
|         systemIPWarning: '請先在面板設置中設置服務器 IP', |         systemIPWarning: '當前未設置服務器 IP,請先在面板設置中設置!', | ||||||
|         syncTime: '服務器時間', |         syncTime: '服務器時間', | ||||||
|         timeZone: '系統時區', |         timeZone: '系統時區', | ||||||
|         timeZoneChangeHelper: '系統時區修改需要重啟服務,是否繼續?', |         timeZoneChangeHelper: '系統時區修改需要重啟服務,是否繼續?', | ||||||
| @@ -1406,6 +1410,8 @@ const message = { | |||||||
|         acmeHelper: 'Acme 賬戶用於申請免費證書', |         acmeHelper: 'Acme 賬戶用於申請免費證書', | ||||||
|     }, |     }, | ||||||
|     firewall: { |     firewall: { | ||||||
|  |         create: '創建規則', | ||||||
|  |         edit: '編輯規則', | ||||||
|         notSupport: '未檢測到系統防火墻(firewalld 或者 ufw),請參考官方文檔進行安裝', |         notSupport: '未檢測到系統防火墻(firewalld 或者 ufw),請參考官方文檔進行安裝', | ||||||
|         ccDeny: 'CC 防護', |         ccDeny: 'CC 防護', | ||||||
|         ipWhiteList: 'IP 白名單', |         ipWhiteList: 'IP 白名單', | ||||||
|   | |||||||
| @@ -432,7 +432,8 @@ const message = { | |||||||
|         localIP: '本机 IP', |         localIP: '本机 IP', | ||||||
|     }, |     }, | ||||||
|     container: { |     container: { | ||||||
|         createContainer: '创建容器', |         create: '创建容器', | ||||||
|  |         edit: '编辑容器', | ||||||
|         updateContaienrHelper: '容器编辑需要重建容器,任何未持久化的数据将会丢失,是否继续?', |         updateContaienrHelper: '容器编辑需要重建容器,任何未持久化的数据将会丢失,是否继续?', | ||||||
|         containerList: '容器列表', |         containerList: '容器列表', | ||||||
|         operatorHelper: '将对选中容器进行 {0} 操作,是否继续?', |         operatorHelper: '将对选中容器进行 {0} 操作,是否继续?', | ||||||
| @@ -459,6 +460,7 @@ const message = { | |||||||
|         cleanSuccess: '操作成功,本次清理数量: {0} 个!', |         cleanSuccess: '操作成功,本次清理数量: {0} 个!', | ||||||
|         cleanSuccessWithSpace: '操作成功,本次清理数量: {0} 个,释放磁盘空间: {1}!', |         cleanSuccessWithSpace: '操作成功,本次清理数量: {0} 个,释放磁盘空间: {1}!', | ||||||
|         container: '容器', |         container: '容器', | ||||||
|  |         unExposedPort: '当前端口映射地址为 127.0.0.1,无法实现外部访问', | ||||||
|         upTime: '运行时长', |         upTime: '运行时长', | ||||||
|         all: '全部', |         all: '全部', | ||||||
|         fetch: '过滤', |         fetch: '过滤', | ||||||
| @@ -621,6 +623,8 @@ const message = { | |||||||
|         startIn: '中开启', |         startIn: '中开启', | ||||||
|     }, |     }, | ||||||
|     cronjob: { |     cronjob: { | ||||||
|  |         create: '创建计划任务', | ||||||
|  |         edit: '编辑计划任务', | ||||||
|         cronTask: '计划任务', |         cronTask: '计划任务', | ||||||
|         changeStatus: '状态修改', |         changeStatus: '状态修改', | ||||||
|         disableMsg: '停止计划任务会导致该任务不再自动执行。是否继续?', |         disableMsg: '停止计划任务会导致该任务不再自动执行。是否继续?', | ||||||
| @@ -904,7 +908,7 @@ const message = { | |||||||
|         sessionTimeoutError: '最小超时时间为 300 秒', |         sessionTimeoutError: '最小超时时间为 300 秒', | ||||||
|         sessionTimeoutHelper: '如果用户超过 {0} 秒未操作面板,面板将自动退出登录', |         sessionTimeoutHelper: '如果用户超过 {0} 秒未操作面板,面板将自动退出登录', | ||||||
|         systemIP: '服务器 IP', |         systemIP: '服务器 IP', | ||||||
|         systemIPWarning: '请先在面板设置中设置服务器 IP', |         systemIPWarning: '当前未设置服务器 IP,请先在面板设置中设置!', | ||||||
|         syncTime: '服务器时间', |         syncTime: '服务器时间', | ||||||
|         timeZone: '系统时区', |         timeZone: '系统时区', | ||||||
|         timeZoneChangeHelper: '系统时区修改需要重启服务,是否继续?', |         timeZoneChangeHelper: '系统时区修改需要重启服务,是否继续?', | ||||||
| @@ -1412,6 +1416,8 @@ const message = { | |||||||
|         acmeHelper: 'Acme 账户用于申请免费证书', |         acmeHelper: 'Acme 账户用于申请免费证书', | ||||||
|     }, |     }, | ||||||
|     firewall: { |     firewall: { | ||||||
|  |         create: '创建规则', | ||||||
|  |         edit: '编辑规则', | ||||||
|         notSupport: '未检测到系统防火墙(firewalld 或者 ufw),请参考官方文档进行安装', |         notSupport: '未检测到系统防火墙(firewalld 或者 ufw),请参考官方文档进行安装', | ||||||
|         ccDeny: 'CC 防护', |         ccDeny: 'CC 防护', | ||||||
|         ipWhiteList: 'IP 白名单', |         ipWhiteList: 'IP 白名单', | ||||||
|   | |||||||
| @@ -1,6 +1,4 @@ | |||||||
| import { getSettingInfo } from '@/api/modules/setting'; |  | ||||||
| import i18n from '@/lang'; | import i18n from '@/lang'; | ||||||
| import { MsgError } from './message'; |  | ||||||
|  |  | ||||||
| export function deepCopy<T>(obj: any): T { | export function deepCopy<T>(obj: any): T { | ||||||
|     let newObj: any; |     let newObj: any; | ||||||
| @@ -258,16 +256,3 @@ export function downloadFile(filePath: string) { | |||||||
|     let url = `${import.meta.env.VITE_API_URL as string}/files/download?`; |     let url = `${import.meta.env.VITE_API_URL as string}/files/download?`; | ||||||
|     window.open(url + 'path=' + filePath, '_blank'); |     window.open(url + 'path=' + filePath, '_blank'); | ||||||
| } | } | ||||||
|  |  | ||||||
| export async function JumpDashboard(port: any) { |  | ||||||
|     if (Number(port) === 0) { |  | ||||||
|         MsgError(i18n.global.t('setting.errPort')); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     const res = await getSettingInfo(); |  | ||||||
|     if (!res.data.systemIP) { |  | ||||||
|         MsgError(i18n.global.t('setting.systemIPWarning')); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     window.open(`http://${res.data.systemIP}:${port}`, '_blank'); |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -193,7 +193,7 @@ | |||||||
|                                             <el-tag |                                             <el-tag | ||||||
|                                                 class="middle-center" |                                                 class="middle-center" | ||||||
|                                                 v-if="installed.httpPort > 0" |                                                 v-if="installed.httpPort > 0" | ||||||
|                                                 @click="JumpDashboard(installed.httpPort)" |                                                 @click="goDashboard(installed.httpPort)" | ||||||
|                                             > |                                             > | ||||||
|                                                 <el-icon class="middle-center"><Position /></el-icon> |                                                 <el-icon class="middle-center"><Position /></el-icon> | ||||||
|                                                 {{ $t('app.busPort') }}:{{ installed.httpPort }} |                                                 {{ $t('app.busPort') }}:{{ installed.httpPort }} | ||||||
| @@ -239,6 +239,8 @@ | |||||||
|     <AppDelete ref="deleteRef" @close="search" /> |     <AppDelete ref="deleteRef" @close="search" /> | ||||||
|     <AppParams ref="appParamRef" /> |     <AppParams ref="appParamRef" /> | ||||||
|     <AppUpgrade ref="upgradeRef" @close="search" /> |     <AppUpgrade ref="upgradeRef" @close="search" /> | ||||||
|  |  | ||||||
|  |     <PortJumpDialog ref="dialogPortJumpRef" /> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| @@ -254,6 +256,7 @@ import i18n from '@/lang'; | |||||||
| import { ElMessageBox } from 'element-plus'; | import { ElMessageBox } from 'element-plus'; | ||||||
| import Backups from '@/components/backup/index.vue'; | import Backups from '@/components/backup/index.vue'; | ||||||
| import Uploads from '@/components/upload/index.vue'; | import Uploads from '@/components/upload/index.vue'; | ||||||
|  | import PortJumpDialog from '@/components/port-jump/index.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 AppParams from './detail/index.vue'; | ||||||
| @@ -264,7 +267,6 @@ 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'; | import { toFolder } from '@/global/business'; | ||||||
| import { JumpDashboard } from '@/utils/util'; |  | ||||||
|  |  | ||||||
| const data = ref<any>(); | const data = ref<any>(); | ||||||
| const loading = ref(false); | const loading = ref(false); | ||||||
| @@ -287,6 +289,7 @@ const checkRef = ref(); | |||||||
| const deleteRef = ref(); | const deleteRef = ref(); | ||||||
| const appParamRef = ref(); | const appParamRef = ref(); | ||||||
| const upgradeRef = ref(); | const upgradeRef = ref(); | ||||||
|  | const dialogPortJumpRef = ref(); | ||||||
| const tags = ref<App.Tag[]>([]); | const tags = ref<App.Tag[]>([]); | ||||||
| const activeTag = ref('all'); | const activeTag = ref('all'); | ||||||
| const searchReq = reactive({ | const searchReq = reactive({ | ||||||
| @@ -338,6 +341,10 @@ const search = () => { | |||||||
|     }); |     }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | const goDashboard = async (port: any) => { | ||||||
|  |     dialogPortJumpRef.value.acceptParams({ port: port }); | ||||||
|  | }; | ||||||
|  |  | ||||||
| const openOperate = (row: any, op: string) => { | const openOperate = (row: any, op: string) => { | ||||||
|     operateReq.installId = row.id; |     operateReq.installId = row.id; | ||||||
|     operateReq.operate = op; |     operateReq.operate = op; | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|                 <el-row> |                 <el-row> | ||||||
|                     <el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16"> |                     <el-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16"> | ||||||
|                         <el-button type="primary" @click="onOpenDialog('create')"> |                         <el-button type="primary" @click="onOpenDialog('create')"> | ||||||
|                             {{ $t('container.createContainer') }} |                             {{ $t('container.create') }} | ||||||
|                         </el-button> |                         </el-button> | ||||||
|                         <el-button type="primary" plain @click="onClean()"> |                         <el-button type="primary" plain @click="onClean()"> | ||||||
|                             {{ $t('container.containerPrune') }} |                             {{ $t('container.containerPrune') }} | ||||||
| @@ -80,18 +80,19 @@ | |||||||
|                             <Status :key="row.state" :status="row.state"></Status> |                             <Status :key="row.state" :status="row.state"></Status> | ||||||
|                         </template> |                         </template> | ||||||
|                     </el-table-column> |                     </el-table-column> | ||||||
|                     <el-table-column :label="$t('container.source')" show-overflow-tooltip min-width="125" fix> |                     <el-table-column :label="$t('container.source')" show-overflow-tooltip min-width="75" fix> | ||||||
|                         <template #default="{ row }"> |                         <template #default="{ row }"> | ||||||
|                             CPU: {{ row.cpuPercent.toFixed(2) }}% {{ $t('monitor.memory') }}: |                             <div>CPU: {{ row.cpuPercent.toFixed(2) }}%</div> | ||||||
|                             {{ row.memoryPercent.toFixed(2) }}% |                             <div>{{ $t('monitor.memory') }}: {{ row.memoryPercent.toFixed(2) }}%</div> | ||||||
|                         </template> |                         </template> | ||||||
|                     </el-table-column> |                     </el-table-column> | ||||||
|                     <el-table-column :label="$t('commons.table.port')" min-width="80" prop="ports" fix> |                     <el-table-column :label="$t('commons.table.port')" min-width="120" prop="ports" fix> | ||||||
|                         <template #default="{ row }"> |                         <template #default="{ row }"> | ||||||
|                             <div v-if="row.ports"> |                             <div v-if="row.ports"> | ||||||
|                                 <div v-for="(item, index) in row.ports" :key="index"> |                                 <div v-for="(item, index) in row.ports" :key="index"> | ||||||
|                                     <div v-if="row.expand || (!row.expand && index < 3)"> |                                     <div v-if="row.expand || (!row.expand && index < 3)"> | ||||||
|                                         <el-button |                                         <el-button | ||||||
|  |                                             v-if="item.indexOf('->') !== -1" | ||||||
|                                             @click="goDashboard(item)" |                                             @click="goDashboard(item)" | ||||||
|                                             class="tagMargin" |                                             class="tagMargin" | ||||||
|                                             icon="Position" |                                             icon="Position" | ||||||
| @@ -101,6 +102,9 @@ | |||||||
|                                         > |                                         > | ||||||
|                                             {{ item }} |                                             {{ item }} | ||||||
|                                         </el-button> |                                         </el-button> | ||||||
|  |                                         <el-button v-else class="tagMargin" type="primary" plain size="small"> | ||||||
|  |                                             {{ item }} | ||||||
|  |                                         </el-button> | ||||||
|                                     </div> |                                     </div> | ||||||
|                                 </div> |                                 </div> | ||||||
|                                 <div v-if="!row.expand && row.ports.length > 3"> |                                 <div v-if="!row.expand && row.ports.length > 3"> | ||||||
| @@ -137,6 +141,8 @@ | |||||||
|         <UpgraeDialog @search="search" ref="dialogUpgradeRef" /> |         <UpgraeDialog @search="search" ref="dialogUpgradeRef" /> | ||||||
|         <MonitorDialog ref="dialogMonitorRef" /> |         <MonitorDialog ref="dialogMonitorRef" /> | ||||||
|         <TerminalDialog ref="dialogTerminalRef" /> |         <TerminalDialog ref="dialogTerminalRef" /> | ||||||
|  |  | ||||||
|  |         <PortJumpDialog ref="dialogPortJumpRef" /> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @@ -150,6 +156,7 @@ import MonitorDialog from '@/views/container/container/monitor/index.vue'; | |||||||
| import ContainerLogDialog from '@/views/container/container/log/index.vue'; | import ContainerLogDialog from '@/views/container/container/log/index.vue'; | ||||||
| import TerminalDialog from '@/views/container/container/terminal/index.vue'; | import TerminalDialog from '@/views/container/container/terminal/index.vue'; | ||||||
| import CodemirrorDialog from '@/components/codemirror-dialog/index.vue'; | import CodemirrorDialog from '@/components/codemirror-dialog/index.vue'; | ||||||
|  | import PortJumpDialog from '@/components/port-jump/index.vue'; | ||||||
| import Status from '@/components/status/index.vue'; | import Status from '@/components/status/index.vue'; | ||||||
| import { reactive, onMounted, ref } from 'vue'; | import { reactive, onMounted, ref } from 'vue'; | ||||||
| import { | import { | ||||||
| @@ -164,8 +171,8 @@ import { Container } from '@/api/interface/container'; | |||||||
| import { ElMessageBox } from 'element-plus'; | import { ElMessageBox } from 'element-plus'; | ||||||
| import i18n from '@/lang'; | import i18n from '@/lang'; | ||||||
| import router from '@/routers'; | import router from '@/routers'; | ||||||
| import { MsgSuccess } from '@/utils/message'; | import { MsgSuccess, MsgWarning } from '@/utils/message'; | ||||||
| import { JumpDashboard, computeSize } from '@/utils/util'; | import { computeSize } from '@/utils/util'; | ||||||
|  |  | ||||||
| const loading = ref(); | const loading = ref(); | ||||||
| const data = ref(); | const data = ref(); | ||||||
| @@ -177,6 +184,7 @@ const paginationConfig = reactive({ | |||||||
| }); | }); | ||||||
| const searchName = ref(); | const searchName = ref(); | ||||||
| const dialogUpgradeRef = ref(); | const dialogUpgradeRef = ref(); | ||||||
|  | const dialogPortJumpRef = ref(); | ||||||
|  |  | ||||||
| const dockerStatus = ref('Running'); | const dockerStatus = ref('Running'); | ||||||
| const loadStatus = async () => { | const loadStatus = async () => { | ||||||
| @@ -196,11 +204,16 @@ const loadStatus = async () => { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| const goDashboard = async (port: any) => { | const goDashboard = async (port: any) => { | ||||||
|     if (!port || port.indexOf(':') === -1) { |     if (port.indexOf('127.0.0.1') !== -1) { | ||||||
|  |         MsgWarning(i18n.global.t('container.unExposedPort')); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     let portEx = port.split(':')[0]; |     if (!port || port.indexOf(':') === -1 || port.indexOf('->') === -1) { | ||||||
|     JumpDashboard(portEx); |         MsgWarning(i18n.global.t('commons.msg.errPort')); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     let portEx = port.match(/:(\d+)/)[1]; | ||||||
|  |     dialogPortJumpRef.value.acceptParams({ port: portEx }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const goSetting = async () => { | const goSetting = async () => { | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <template> | <template> | ||||||
|     <el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%"> |     <el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%"> | ||||||
|         <template #header> |         <template #header> | ||||||
|             <DrawerHeader :header="$t('container.createContainer')" :back="handleClose" /> |             <DrawerHeader :header="title" :back="handleClose" /> | ||||||
|         </template> |         </template> | ||||||
|         <el-form |         <el-form | ||||||
|             ref="formRef" |             ref="formRef" | ||||||
| @@ -242,7 +242,7 @@ const dialogData = ref<DialogProps>({ | |||||||
| }); | }); | ||||||
| const acceptParams = (params: DialogProps): void => { | const acceptParams = (params: DialogProps): void => { | ||||||
|     dialogData.value = params; |     dialogData.value = params; | ||||||
|     title.value = i18n.global.t('commons.button.' + dialogData.value.title); |     title.value = i18n.global.t('container.' + dialogData.value.title); | ||||||
|     if (params.title === 'edit') { |     if (params.title === 'edit') { | ||||||
|         dialogData.value.rowData.memoryItem = Number((dialogData.value.rowData.memory / 1024 / 1024).toFixed(2)); |         dialogData.value.rowData.memoryItem = Number((dialogData.value.rowData.memory / 1024 / 1024).toFixed(2)); | ||||||
|         let itemCmd = ''; |         let itemCmd = ''; | ||||||
| @@ -277,7 +277,7 @@ const handleClose = () => { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| const rules = reactive({ | const rules = reactive({ | ||||||
|     cpuShares: [Rules.number, checkNumberRange(2, 262144)], |     cpuShares: [Rules.number, checkNumberRange(0, 262144)], | ||||||
|     name: [Rules.requiredInput, Rules.name], |     name: [Rules.requiredInput, Rules.name], | ||||||
|     image: [Rules.requiredSelect], |     image: [Rules.requiredSelect], | ||||||
|     nanoCPUs: [Rules.number], |     nanoCPUs: [Rules.number], | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <template> | <template> | ||||||
|     <el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%"> |     <el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%"> | ||||||
|         <template #header> |         <template #header> | ||||||
|             <DrawerHeader :header="$t('cronjob.cronTask')" :resource="dialogData.rowData?.name" :back="handleClose" /> |             <DrawerHeader :header="title" :resource="dialogData.rowData?.name" :back="handleClose" /> | ||||||
|         </template> |         </template> | ||||||
|         <el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules"> |         <el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules"> | ||||||
|             <el-row type="flex" justify="center"> |             <el-row type="flex" justify="center"> | ||||||
| @@ -238,7 +238,7 @@ const acceptParams = (params: DialogProps): void => { | |||||||
|     if (dialogData.value.title === 'create') { |     if (dialogData.value.title === 'create') { | ||||||
|         changeType(); |         changeType(); | ||||||
|     } |     } | ||||||
|     title.value = i18n.global.t('commons.button.' + dialogData.value.title); |     title.value = i18n.global.t('cronjob.' + dialogData.value.title); | ||||||
|     if (dialogData.value?.rowData?.exclusionRules) { |     if (dialogData.value?.rowData?.exclusionRules) { | ||||||
|         dialogData.value.rowData.exclusionRules = dialogData.value.rowData.exclusionRules.replaceAll(',', '\n'); |         dialogData.value.rowData.exclusionRules = dialogData.value.rowData.exclusionRules.replaceAll(',', '\n'); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -141,6 +141,8 @@ | |||||||
|  |  | ||||||
|         <AppResources ref="checkRef"></AppResources> |         <AppResources ref="checkRef"></AppResources> | ||||||
|         <DeleteDialog ref="deleteRef" @search="search" /> |         <DeleteDialog ref="deleteRef" @search="search" /> | ||||||
|  |  | ||||||
|  |         <PortJumpDialog ref="dialogPortJumpRef" /> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @@ -155,7 +157,8 @@ import Setting from '@/views/database/mysql/setting/index.vue'; | |||||||
| import AppStatus from '@/components/app-status/index.vue'; | import AppStatus from '@/components/app-status/index.vue'; | ||||||
| import Backups from '@/components/backup/index.vue'; | import Backups from '@/components/backup/index.vue'; | ||||||
| import UploadDialog from '@/components/upload/index.vue'; | import UploadDialog from '@/components/upload/index.vue'; | ||||||
| import { JumpDashboard, dateFormat } from '@/utils/util'; | import PortJumpDialog from '@/components/port-jump/index.vue'; | ||||||
|  | import { dateFormat } from '@/utils/util'; | ||||||
| import { reactive, ref } from 'vue'; | import { reactive, ref } from 'vue'; | ||||||
| import { deleteCheckMysqlDB, loadRemoteAccess, searchMysqlDBs, updateMysqlDescription } from '@/api/modules/database'; | import { deleteCheckMysqlDB, loadRemoteAccess, searchMysqlDBs, updateMysqlDescription } from '@/api/modules/database'; | ||||||
| import i18n from '@/lang'; | import i18n from '@/lang'; | ||||||
| @@ -179,6 +182,8 @@ const deleteRef = ref(); | |||||||
| const phpadminPort = ref(); | const phpadminPort = ref(); | ||||||
| const phpVisiable = ref(false); | const phpVisiable = ref(false); | ||||||
|  |  | ||||||
|  | const dialogPortJumpRef = ref(); | ||||||
|  |  | ||||||
| const data = ref(); | const data = ref(); | ||||||
| const paginationConfig = reactive({ | const paginationConfig = reactive({ | ||||||
|     currentPage: 1, |     currentPage: 1, | ||||||
| @@ -264,7 +269,7 @@ const goDashboard = async () => { | |||||||
|         phpVisiable.value = true; |         phpVisiable.value = true; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     JumpDashboard(phpadminPort.value); |     dialogPortJumpRef.value.acceptParams({ port: phpadminPort.value }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const getAppDetail = (key: string) => { | const getAppDetail = (key: string) => { | ||||||
|   | |||||||
| @@ -53,6 +53,8 @@ | |||||||
|                 </span> |                 </span> | ||||||
|             </template> |             </template> | ||||||
|         </el-dialog> |         </el-dialog> | ||||||
|  |  | ||||||
|  |         <PortJumpDialog ref="dialogPortJumpRef" /> | ||||||
|     </div> |     </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @@ -61,13 +63,11 @@ import Setting from '@/views/database/redis/setting/index.vue'; | |||||||
| import Password from '@/views/database/redis/password/index.vue'; | import Password from '@/views/database/redis/password/index.vue'; | ||||||
| import Terminal from '@/components/terminal/index.vue'; | import Terminal from '@/components/terminal/index.vue'; | ||||||
| import AppStatus from '@/components/app-status/index.vue'; | import AppStatus from '@/components/app-status/index.vue'; | ||||||
|  | import PortJumpDialog from '@/components/port-jump/index.vue'; | ||||||
| import { nextTick, onBeforeUnmount, ref } from 'vue'; | import { nextTick, onBeforeUnmount, ref } from 'vue'; | ||||||
| import { App } from '@/api/interface/app'; | import { App } from '@/api/interface/app'; | ||||||
| import { GetAppPort } from '@/api/modules/app'; | import { GetAppPort } from '@/api/modules/app'; | ||||||
| import router from '@/routers'; | import router from '@/routers'; | ||||||
| import { MsgError } from '@/utils/message'; |  | ||||||
| import { getSettingInfo } from '@/api/modules/setting'; |  | ||||||
| import i18n from '@/lang'; |  | ||||||
|  |  | ||||||
| const loading = ref(false); | const loading = ref(false); | ||||||
| const maskShow = ref(true); | const maskShow = ref(true); | ||||||
| @@ -83,6 +83,8 @@ const terminalShow = ref(false); | |||||||
| const redisCommandPort = ref(); | const redisCommandPort = ref(); | ||||||
| const commandVisiable = ref(false); | const commandVisiable = ref(false); | ||||||
|  |  | ||||||
|  | const dialogPortJumpRef = ref(); | ||||||
|  |  | ||||||
| const isRefresh = ref(); | const isRefresh = ref(); | ||||||
|  |  | ||||||
| const onSetting = async () => { | const onSetting = async () => { | ||||||
| @@ -97,12 +99,7 @@ const goDashboard = async () => { | |||||||
|         commandVisiable.value = true; |         commandVisiable.value = true; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     const res = await getSettingInfo(); |     dialogPortJumpRef.value.acceptParams({ port: redisCommandPort.value }); | ||||||
|     if (!res.data.systemIP) { |  | ||||||
|         MsgError(i18n.global.t('setting.systemIPWarning')); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     window.open(`http://${res.data.systemIP}:${redisCommandPort.value}`, '_blank'); |  | ||||||
| }; | }; | ||||||
| const getAppDetail = (key: string) => { | const getAppDetail = (key: string) => { | ||||||
|     router.push({ name: 'AppDetail', params: { appKey: key } }); |     router.push({ name: 'AppDetail', params: { appKey: key } }); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <template> | <template> | ||||||
|     <el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%"> |     <el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%"> | ||||||
|         <template #header> |         <template #header> | ||||||
|             <DrawerHeader :header="$t('firewall.ipRule')" :back="handleClose" /> |             <DrawerHeader :header="title" :back="handleClose" /> | ||||||
|         </template> |         </template> | ||||||
|         <div v-loading="loading"> |         <div v-loading="loading"> | ||||||
|             <el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules"> |             <el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules"> | ||||||
| @@ -68,7 +68,7 @@ const acceptParams = (params: DialogProps): void => { | |||||||
|     if (dialogData.value.title === 'edit') { |     if (dialogData.value.title === 'edit') { | ||||||
|         oldRule.value = deepCopy(params.rowData); |         oldRule.value = deepCopy(params.rowData); | ||||||
|     } |     } | ||||||
|     title.value = i18n.global.t('commons.button.' + dialogData.value.title); |     title.value = i18n.global.t('firewall.' + dialogData.value.title); | ||||||
|     drawerVisiable.value = true; |     drawerVisiable.value = true; | ||||||
| }; | }; | ||||||
| const emit = defineEmits<{ (e: 'search'): void }>(); | const emit = defineEmits<{ (e: 'search'): void }>(); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <template> | <template> | ||||||
|     <el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%"> |     <el-drawer v-model="drawerVisiable" :destroy-on-close="true" :close-on-click-modal="false" size="50%"> | ||||||
|         <template #header> |         <template #header> | ||||||
|             <DrawerHeader :header="$t('firewall.portRule')" :back="handleClose" /> |             <DrawerHeader :header="title" :back="handleClose" /> | ||||||
|         </template> |         </template> | ||||||
|         <div v-loading="loading"> |         <div v-loading="loading"> | ||||||
|             <el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules"> |             <el-form ref="formRef" label-position="top" :model="dialogData.rowData" :rules="rules"> | ||||||
| @@ -98,7 +98,7 @@ const acceptParams = (params: DialogProps): void => { | |||||||
|         } |         } | ||||||
|         oldRule.value = deepCopy(params.rowData); |         oldRule.value = deepCopy(params.rowData); | ||||||
|     } |     } | ||||||
|     title.value = i18n.global.t('commons.button.' + dialogData.value.title); |     title.value = i18n.global.t('firewall.' + dialogData.value.title); | ||||||
|     drawerVisiable.value = true; |     drawerVisiable.value = true; | ||||||
| }; | }; | ||||||
| const emit = defineEmits<{ (e: 'search'): void }>(); | const emit = defineEmits<{ (e: 'search'): void }>(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ssongliu
					ssongliu