1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 14:08:06 +08:00

feat: Increase version restrictions for node switching (#7631)

This commit is contained in:
ssongliu 2025-01-03 16:52:08 +08:00 committed by GitHub
parent c7936e656b
commit 6122aa3a3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 88 additions and 11 deletions

View File

@ -3,7 +3,7 @@ package configs
type System struct {
Mode string `mapstructure:"mode"`
Port string `mapstructure:"version"`
Port string `mapstructure:"port"`
Version string `mapstructure:"version"`
BaseDir string `mapstructure:"base_dir"`
EncryptKey string `mapstructure:"encrypt_key"`

View File

@ -31,6 +31,7 @@ require (
github.com/minio/minio-go/v7 v7.0.74
github.com/nicksnyder/go-i18n/v2 v2.4.0
github.com/opencontainers/image-spec v1.1.0
github.com/oschwald/maxminddb-golang v1.13.1
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.6
@ -171,7 +172,6 @@ require (
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/oschwald/maxminddb-golang v1.13.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect

View File

@ -227,5 +227,6 @@ export namespace Setting {
id: number;
addr: string;
status: string;
version: string;
}
}

View File

@ -1743,6 +1743,10 @@ const message = {
upgradeNow: 'Upgrade now',
source: 'Download source',
hasNewVersion: 'New version Available',
versionHigher:
'Detected that node {0} version is higher than the main node, switching is not supported at this time. Please upgrade the main node system version and try again!',
versionLower:
'Detected that node {0} version is lower than the main node, switching is not supported at this time. Please upgrade the system version of this node and try again!',
about: 'About',
project: 'Project Address',

View File

@ -1548,6 +1548,8 @@ const message = {
upgradeNow: '立即更新',
source: '下載源',
hasNewVersion: '有新版本',
versionHigher: '檢測到節點 {0} 版本高於主節點暫不支持切換請先升級主節點系統版本後重試',
versionLower: '檢測到節點 {0} 版本低於主節點暫不支持切換請先升級該節點系統版本後重試',
safe: '安全',
bindInfo: '監聽地址',

View File

@ -1546,6 +1546,8 @@ const message = {
upgradeNow: '立即更新',
source: '下载源',
hasNewVersion: '有新版本',
versionHigher: '检测到节点 {0} 版本高于主节点暂不支持切换请先升级主节点系统版本后重试',
versionLower: '检测到节点 {0} 版本低于主节点暂不支持切换请先升级该节点系统版本后重试',
safe: '安全',
bindInfo: '监听地址',

View File

@ -8,10 +8,8 @@
>
<Logo :isCollapse="isCollapse" />
<div class="el-dropdown-link flex justify-between items-center">
<el-button type="text" @click="openChangeNode" @mouseenter="openChangeNode">
<span>
<el-button link class="ml-4" @click="openChangeNode" @mouseenter="openChangeNode">
{{ loadCurrentName() }}
</span>
</el-button>
<div>
<el-dropdown
@ -25,11 +23,12 @@
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="local">
<SvgIcon class="ico" iconName="p-host" />
<el-button link icon="CircleCheck" type="success" />
{{ $t('terminal.local') }}
</el-dropdown-item>
<el-dropdown-item v-for="item in nodes" :key="item.name" :command="item.name">
<SvgIcon class="ico" iconName="p-host" />
<el-button v-if="item.status === 'Healthy'" link icon="CircleCheck" type="success" />
<el-button v-else link icon="Warning" type="danger" />
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
@ -74,16 +73,18 @@ import { logOutApi } from '@/api/modules/auth';
import i18n from '@/lang';
import { DropdownInstance, ElMessageBox } from 'element-plus';
import { GlobalStore, MenuStore } from '@/store';
import { MsgSuccess } from '@/utils/message';
import { MsgError, MsgSuccess } from '@/utils/message';
import { isString } from '@vueuse/core';
import { getSettingInfo, listNodeOptions } from '@/api/modules/setting';
import { countExecutingTask } from '@/api/modules/log';
import { compareVersion } from '@/utils/version';
const route = useRoute();
const menuStore = MenuStore();
const globalStore = GlobalStore();
const nodes = ref([]);
const nodeChangeRef = ref<DropdownInstance>();
const version = ref();
defineProps({
menuRouter: {
type: Boolean,
@ -172,8 +173,32 @@ const loadNodes = async () => {
});
};
const changeNode = (command: string) => {
if (globalStore.currentNode === command) {
return;
}
if (command == 'local') {
globalStore.currentNode = command || 'local';
location.reload();
return;
}
for (const item of nodes.value) {
if (item.name == command) {
if (version.value == item.version) {
globalStore.currentNode = command || 'local';
location.reload();
return;
}
let compareItem = compareVersion(item.version, version.value);
if (compareItem) {
MsgError(i18n.global.t('setting.versionHigher', [command]));
return;
}
if (!compareItem) {
MsgError(i18n.global.t('setting.versionLower', [command]));
return;
}
}
}
};
function extractLabels(node: Node, result: string[]): void {
@ -195,6 +220,7 @@ function getCheckedLabels(json: Node): string[] {
const search = async () => {
const res = await getSettingInfo();
version.value = res.data.systemVersion;
const json: Node = JSON.parse(res.data.xpackHideMenu);
if (json.isCheck === false) {
json.children.forEach((child: any) => {

View File

@ -0,0 +1,42 @@
export function compareVersion(version1: string, version2: string): boolean {
const v1s = extractNumbers(version1);
const v2s = extractNumbers(version2);
const maxLen = Math.max(v1s.length, v2s.length);
v1s.push(...new Array(maxLen - v1s.length).fill('0'));
v2s.push(...new Array(maxLen - v2s.length).fill('0'));
for (let i = 0; i < maxLen; i++) {
const v1 = parseInt(v1s[i], 10);
const v2 = parseInt(v2s[i], 10);
if (v1 !== v2) {
return v1 > v2;
}
}
return true;
}
function extractNumbers(version: string): string[] {
const numbers: string[] = [];
let start = -1;
for (let i = 0; i < version.length; i++) {
if (isDigit(version[i])) {
if (start === -1) {
start = i;
}
} else {
if (start !== -1) {
numbers.push(version.slice(start, i));
start = -1;
}
}
}
if (start !== -1) {
numbers.push(version.slice(start));
}
return numbers;
}
function isDigit(char: string): boolean {
return /^\d$/.test(char);
}