feat(interconnect): display active node name in travel mode & update changelog
- Persist active interconnect node name in localStorage via api - Pass node name on MasterList and NodeSwitcher when traveling - Display current node name on the 'Return to Master' floating button in App.vue - Update CHANGELOG.md, README.md and docs with v1.1.17 release notes highlighting interconnect features
This commit is contained in:
+14
-10
@@ -1,17 +1,21 @@
|
|||||||
# 更新日志 (v1.1.16)
|
# 更新日志 (v1.1.17)
|
||||||
|
|
||||||
### 2026.06.22 - 体验优化与 Bug 修复
|
### 2026.06.28 - 全新节点互联功能发布!
|
||||||
* **执行历史自适应**:修复了大屏或竖屏下页面高度被限制在 520px 导致底部留白的问题,动态计算视口高度,让列表和日志输出区域自伸缩(#134)。
|
|
||||||
* **通知日志截断优化**:修复了执行日志在全局发送前被 1000 字符强行截断导致自定义 LogLimit 失效的 Bug(#133)。
|
🎉 **重磅新功能:节点互联体系**
|
||||||
* **通知发送性能优化**:将 `stripAnsi` 清除控制字符逻辑移到发送循环外只执行一次,避免高开销正则在多渠道分发时重复运算(#133)。
|
* **互联协议与通道**:新增开放连接(OpenConnect)协议支持,轻松打通并管理多个白虎面板实例,解决分布式定时任务环境隔离痛点。
|
||||||
* **机密使用说明**:在机密管理页面新增了温馨提示及使用说明,并支持点击关闭和 localStorage 持久化记忆状态(#135)。
|
* **互联控制台**:全新上线的同步管理面板,可实时总览所有连接节点的资源开销、连接状态及各项负载指标。
|
||||||
* **系统命令与兼容性**:新增了版本输出命令(`version`),修复了终端 UTF-8 字节截断时的字符乱码问题。
|
* **核心数据同步**:支持了跨节点间的环境变量全量同步,并完美保留变量的原始结构与关联 ID,为任务跨环境漂移和无缝分发提供底层保障。
|
||||||
* **数据恢复兼容**:在数据恢复时,自动将老的 task 环境和标签迁移至关系表(#135)。
|
* **路由与代理增强**:底层代理路由机制迎来全面升级,完美支持了基于穿透隧道的前端互联访问代理。
|
||||||
* **仓库同步增强**:支持了自定义仓库同步文件夹名称(#132)。
|
|
||||||
* **Docker 支持**:在 CI 构建中,增加 arm64 架构支持,并在非 Release 构建中只为分支打 Tag。
|
**✨ 其它优化与修复**
|
||||||
|
* **终端体验优化**:针对移动端深度优化终端(xterm)交互,禁用移动端点击自动弹出软键盘,支持选中内容后 Ctrl+C 快捷复制,并大幅提升了小屏幕下的滑动流畅性。
|
||||||
|
* **调度器安全**:为 Worker 数量和队列大小添加了边界验证及安全限制,从底层防止高并发场景下出现 OOM 问题。
|
||||||
|
* **UI 体验优化**:修复了大屏模式下环境变量表格删除按钮丢失的问题;MasterView 按钮在小屏幕下支持自适应填满;增加了演示模式下互联角色的操作限制。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
> 出于安全及环境隔离考虑,推荐使用 Docker/Compose 部署方式。[镜像地址](https://github.com/engigu/baihu-panel/pkgs/container/baihu)
|
> 出于安全及环境隔离考虑,推荐使用 Docker/Compose 部署方式。[镜像地址](https://github.com/engigu/baihu-panel/pkgs/container/baihu)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
### 最近更新
|
### 最近更新
|
||||||
|
|
||||||
|
**2026.06.28** - **节点互联大更新与终端UX优化**:全面升级节点互联功能体系(支持环境变量全量同步、OpenConnect 协议及全新同步面板);深度优化移动端下 XTerminal 流畅性与原生交互体验,并加入 Worker 数量防 OOM 边界安全检查。
|
||||||
|
|
||||||
**2026.06.12** - **调度器与面板资源监控**:新增对面板底层运行资源、调度器并发池(Worker)运行情况以及底层内存堆栈的实时高频监控。
|
**2026.06.12** - **调度器与面板资源监控**:新增对面板底层运行资源、调度器并发池(Worker)运行情况以及底层内存堆栈的实时高频监控。
|
||||||
**2026.05.29** - **自定义前端框架 (WebUI)**:新增前端定制管理机制,支持开发和上传第三方前端静态资源包 (`.tar.gz` / `.zip`),完全无缝接管并替换内置的系统面板界面,支持实现深度主题化定制。详情请看[前端定制说明文档](docs/guide/webui.md)
|
**2026.05.29** - **自定义前端框架 (WebUI)**:新增前端定制管理机制,支持开发和上传第三方前端静态资源包 (`.tar.gz` / `.zip`),完全无缝接管并替换内置的系统面板界面,支持实现深度主题化定制。详情请看[前端定制说明文档](docs/guide/webui.md)
|
||||||
|
|
||||||
@@ -106,6 +108,12 @@
|
|||||||
- 执行日志自动搜索并**屏蔽(********)**敏感机密内容
|
- 执行日志自动搜索并**屏蔽(********)**敏感机密内容
|
||||||
- 严格权限隔离:机密仅在定时任务调度时注入,终端/测试环境不可见
|
- 严格权限隔离:机密仅在定时任务调度时注入,终端/测试环境不可见
|
||||||
|
|
||||||
|
### 节点互联体系 (New)
|
||||||
|
- 支持 OpenConnect 协议,轻松实现多台白虎面板之间的互联互通
|
||||||
|
- 支持节点间的环境变量无缝同步(保留原有结构与 ID)
|
||||||
|
- 集成同步管理控制台,统一查看与控制各节点状态与负载指标
|
||||||
|
- 底层路由深度适配穿透隧道,完美支持分布式前端代理访问
|
||||||
|
|
||||||
### 仓库任务同步 (New)
|
### 仓库任务同步 (New)
|
||||||
- 支持 青龙 仓库命令格式快捷导入
|
- 支持 青龙 仓库命令格式快捷导入
|
||||||
- 自动解析脚本注释中的 Cron 表达式和环境变量名
|
- 自动解析脚本注释中的 Cron 表达式和环境变量名
|
||||||
|
|||||||
@@ -4,6 +4,13 @@
|
|||||||
|
|
||||||
## 最近更新概览
|
## 最近更新概览
|
||||||
|
|
||||||
|
### 2026.06.28 - 全新节点互联功能发布! (v1.1.17)
|
||||||
|
- **节点互联体系 (New)**:新增开放连接(OpenConnect)协议支持,轻松打通并管理多个白虎面板实例;全新上线同步管理面板,可实时总览所有连接节点的资源开销与各项负载指标;支持了跨节点间的环境变量全量无缝同步(完美保留原始结构与关联 ID);底层路由机制迎来全面升级,完美支持基于穿透隧道的前端互联访问代理。
|
||||||
|
- **终端体验优化**:针对移动端深度优化终端(xterm)交互,禁用移动端点击自动弹出软键盘,支持选中内容后 Ctrl+C 快捷复制,并大幅提升了小屏幕下的滑动流畅性。
|
||||||
|
- **调度器安全**:为 Worker 数量和队列大小添加了边界验证及安全限制,从底层防止高并发场景下出现 OOM 问题。
|
||||||
|
- **UI 体验优化**:修复了大屏模式下环境变量表格删除按钮丢失的问题;MasterView 按钮在小屏幕下支持自适应填满;增加了演示模式下互联角色的操作限制。
|
||||||
|
|
||||||
|
|
||||||
### 2026.06.22 - 体验优化与 Bug 修复 (v1.1.16)
|
### 2026.06.22 - 体验优化与 Bug 修复 (v1.1.16)
|
||||||
- **执行历史自适应 (New)**:修复了执行历史列表及日志卡片高度被固定限制在 `520px` 的 Bug,改为通过 `calc(100vh - 190px)` 动态铺满视口,大幅提升大屏及竖屏利用率(#134)。
|
- **执行历史自适应 (New)**:修复了执行历史列表及日志卡片高度被固定限制在 `520px` 的 Bug,改为通过 `calc(100vh - 190px)` 动态铺满视口,大幅提升大屏及竖屏利用率(#134)。
|
||||||
- **通知日志截断 Bug 修复**:修复了任务通知中执行日志在全局被提前硬编码截断导致个性化字数限制失效的 Bug(#133)。
|
- **通知日志截断 Bug 修复**:修复了任务通知中执行日志在全局被提前硬编码截断导致个性化字数限制失效的 Bug(#133)。
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@ import { onMounted } from 'vue'
|
|||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import { Toaster } from '@/components/ui/sonner'
|
import { Toaster } from '@/components/ui/sonner'
|
||||||
import { LogOut } from 'lucide-vue-next'
|
import { LogOut } from 'lucide-vue-next'
|
||||||
import { activeInterconnectNodeId, setActiveInterconnectNodeId } from '@/api'
|
import { activeInterconnectNodeId, activeInterconnectNodeName, setActiveInterconnectNodeId } from '@/api'
|
||||||
|
|
||||||
function exitTravel() {
|
function exitTravel() {
|
||||||
setActiveInterconnectNodeId('')
|
setActiveInterconnectNodeId('')
|
||||||
@@ -37,7 +37,7 @@ onMounted(() => {
|
|||||||
hover:scale-105 active:scale-95 cursor-pointer"
|
hover:scale-105 active:scale-95 cursor-pointer"
|
||||||
>
|
>
|
||||||
<LogOut class="h-3 w-3 transition-transform group-hover:-translate-x-0.5" />
|
<LogOut class="h-3 w-3 transition-transform group-hover:-translate-x-0.5" />
|
||||||
<span>返回主节点</span>
|
<span>返回主节点 <template v-if="activeInterconnectNodeName">当前:({{ activeInterconnectNodeName }})</template></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -66,15 +66,22 @@ export interface MonitorStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export let activeInterconnectNodeId = localStorage.getItem('activeInterconnectNodeId') || ''
|
export let activeInterconnectNodeId = localStorage.getItem('activeInterconnectNodeId') || ''
|
||||||
|
export let activeInterconnectNodeName = localStorage.getItem('activeInterconnectNodeName') || ''
|
||||||
|
|
||||||
export function setActiveInterconnectNodeId(id: string) {
|
export function setActiveInterconnectNodeId(id: string, name?: string) {
|
||||||
activeInterconnectNodeId = id
|
activeInterconnectNodeId = id
|
||||||
|
if (name !== undefined) {
|
||||||
|
activeInterconnectNodeName = name
|
||||||
|
}
|
||||||
localStorage.removeItem('site_settings_cache')
|
localStorage.removeItem('site_settings_cache')
|
||||||
if (id) {
|
if (id) {
|
||||||
localStorage.setItem('activeInterconnectNodeId', id)
|
localStorage.setItem('activeInterconnectNodeId', id)
|
||||||
|
if (name) localStorage.setItem('activeInterconnectNodeName', name)
|
||||||
document.cookie = `active_interconnect_node_id=${id}; path=/; max-age=${7 * 24 * 3600}`
|
document.cookie = `active_interconnect_node_id=${id}; path=/; max-age=${7 * 24 * 3600}`
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem('activeInterconnectNodeId')
|
localStorage.removeItem('activeInterconnectNodeId')
|
||||||
|
localStorage.removeItem('activeInterconnectNodeName')
|
||||||
|
activeInterconnectNodeName = ''
|
||||||
document.cookie = `active_interconnect_node_id=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC`
|
document.cookie = `active_interconnect_node_id=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ function handleNodeChange(val: any) {
|
|||||||
if (strVal === 'local') {
|
if (strVal === 'local') {
|
||||||
setActiveInterconnectNodeId('')
|
setActiveInterconnectNodeId('')
|
||||||
} else {
|
} else {
|
||||||
setActiveInterconnectNodeId(strVal)
|
const nodeName = nodes.value.find(n => n.id === strVal)?.name || ''
|
||||||
|
setActiveInterconnectNodeId(strVal, nodeName)
|
||||||
}
|
}
|
||||||
// Refresh the current page to reload data from the new node
|
// Refresh the current page to reload data from the new node
|
||||||
window.location.reload()
|
window.location.reload()
|
||||||
|
|||||||
@@ -143,8 +143,8 @@ async function showDetail(node: interconnectApi.InterconnectNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTravel(nodeId: string) {
|
function handleTravel(node: interconnectApi.InterconnectNode) {
|
||||||
setActiveInterconnectNodeId(nodeId)
|
setActiveInterconnectNodeId(node.id, node.name)
|
||||||
window.location.href = '/'
|
window.location.href = '/'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ defineExpose({
|
|||||||
<Button variant="ghost" size="icon" class="h-7 w-7" @click="showDetail(node)" title="查看详情">
|
<Button variant="ghost" size="icon" class="h-7 w-7" @click="showDetail(node)" title="查看详情">
|
||||||
<Eye class="h-3.5 w-3.5" />
|
<Eye class="h-3.5 w-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" size="icon" class="h-7 w-7" @click="handleTravel(node.id)" title="穿越到此子节点">
|
<Button variant="ghost" size="icon" class="h-7 w-7" @click="handleTravel(node)" title="穿越到此子节点">
|
||||||
<ExternalLink class="h-3.5 w-3.5" />
|
<ExternalLink class="h-3.5 w-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" size="icon" class="h-7 w-7" @click="openEditDialog(node)" title="编辑">
|
<Button variant="ghost" size="icon" class="h-7 w-7" @click="openEditDialog(node)" title="编辑">
|
||||||
@@ -329,7 +329,7 @@ defineExpose({
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-36 shrink-0 flex justify-center gap-0.5">
|
<div class="w-36 shrink-0 flex justify-center gap-0.5">
|
||||||
<Button variant="ghost" size="icon" class="h-7 w-7" @click="showDetail(node)" title="查看详情"><Eye class="h-3.5 w-3.5" /></Button>
|
<Button variant="ghost" size="icon" class="h-7 w-7" @click="showDetail(node)" title="查看详情"><Eye class="h-3.5 w-3.5" /></Button>
|
||||||
<Button variant="ghost" size="icon" class="h-7 w-7" @click="handleTravel(node.id)" title="穿越到此子节点"><ExternalLink class="h-3.5 w-3.5" /></Button>
|
<Button variant="ghost" size="icon" class="h-7 w-7" @click="handleTravel(node)" title="穿越到此子节点"><ExternalLink class="h-3.5 w-3.5" /></Button>
|
||||||
<Button variant="ghost" size="icon" class="h-7 w-7" @click="openEditDialog(node)" title="编辑"><Edit2 class="h-3.5 w-3.5" /></Button>
|
<Button variant="ghost" size="icon" class="h-7 w-7" @click="openEditDialog(node)" title="编辑"><Edit2 class="h-3.5 w-3.5" /></Button>
|
||||||
<Button variant="ghost" size="icon" class="h-7 w-7" @click="confirmDelete(node.id)" title="删除"><Trash2 class="h-3.5 w-3.5" /></Button>
|
<Button variant="ghost" size="icon" class="h-7 w-7" @click="confirmDelete(node.id)" title="删除"><Trash2 class="h-3.5 w-3.5" /></Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -386,7 +386,7 @@ defineExpose({
|
|||||||
<Button variant="ghost" class="h-9 px-0 text-xs gap-1 hover:bg-primary/5 rounded-none" @click="showDetail(node)">
|
<Button variant="ghost" class="h-9 px-0 text-xs gap-1 hover:bg-primary/5 rounded-none" @click="showDetail(node)">
|
||||||
<Eye class="h-3.5 w-3.5" />详情
|
<Eye class="h-3.5 w-3.5" />详情
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" class="h-9 px-0 text-xs gap-1 hover:bg-primary/5 rounded-none border-l border-border/10" @click="handleTravel(node.id)">
|
<Button variant="ghost" class="h-9 px-0 text-xs gap-1 hover:bg-primary/5 rounded-none border-l border-border/10" @click="handleTravel(node)">
|
||||||
<ExternalLink class="h-3.5 w-3.5" />穿越
|
<ExternalLink class="h-3.5 w-3.5" />穿越
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" class="h-9 px-0 text-xs gap-1 hover:bg-primary/5 rounded-none border-l border-border/10" @click="openEditDialog(node)">
|
<Button variant="ghost" class="h-9 px-0 text-xs gap-1 hover:bg-primary/5 rounded-none border-l border-border/10" @click="openEditDialog(node)">
|
||||||
|
|||||||
Reference in New Issue
Block a user