From 7add9384c13b25be6f82b2a8f545267a65225f0c Mon Sep 17 00:00:00 2001 From: r Date: Sun, 21 Jun 2026 11:11:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=88=E7=AB=AF=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E4=BF=9D=E6=8C=81=E4=BC=9A=E8=AF=9D=20+=20=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E5=88=97=E8=A1=A8=E6=8C=89=E5=88=9B=E5=BB=BA=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E5=80=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit keep-alive 下终端切换不 dispose SSH;列表/推送/终端默认 newest first。 Co-authored-by: Cursor --- .../2026-06-18-terminal-persist-navigation.md | 40 +++++++++++++++++++ .../2026-06-21-server-list-created-at-sort.md | 27 +++++++++++++ .../src/composables/push/usePushServers.ts | 7 +++- .../terminal/useTerminalSessions.ts | 7 +++- .../src/composables/useServerPagination.ts | 2 +- frontend/src/pages/TerminalPage.vue | 40 +++++++++++++++++-- frontend/src/utils/serverTableSort.ts | 1 + server/infrastructure/database/server_repo.py | 22 +++++++--- 8 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 docs/changelog/2026-06-18-terminal-persist-navigation.md create mode 100644 docs/changelog/2026-06-21-server-list-created-at-sort.md diff --git a/docs/changelog/2026-06-18-terminal-persist-navigation.md b/docs/changelog/2026-06-18-terminal-persist-navigation.md new file mode 100644 index 00000000..b5ed350e --- /dev/null +++ b/docs/changelog/2026-06-18-terminal-persist-navigation.md @@ -0,0 +1,40 @@ +# 终端页切换路由保持 SSH 会话 + +**日期**:2026-06-18 + +## 摘要 + +用户从「终端」页导航至其他 SPA 页面时,WebSSH 会话不再被主动断开;返回终端页可继续操作同一标签与会话。 + +## 动机 + +此前 `TerminalPage` 被刻意排除在 `keep-alive` 之外,且 `onBeforeUnmount` 中调用 `disposeAllSessions()`,路由切换即卸载组件并关闭全部 WebSocket/SSH 连接,与运维「开终端查问题、切页看列表、再回来继续敲命令」的工作流冲突。 + +## 方案 + +1. 将 `TerminalPage` 加入 `CACHED_PAGE_NAMES`,由 `App.vue` 现有 `` 缓存实例。 +2. 生命周期调整: + - `onDeactivated`:仅移除全局快捷键监听,**不** dispose 会话。 + - `onActivated`:恢复快捷键、refit xterm、聚焦当前标签。 + - `onBeforeUnmount`:仅在缓存淘汰或组件真正销毁时 dispose(与 `keep-alive max=12` 一致)。 + - 监听 `auth.isLoggedIn`:登出时 dispose,避免缓存中残留 SSH 连接。 + +未将会话提升到全局 store:`termNativeStore` 已是模块级单例,配合 keep-alive 即可,改动最小。 + +## 涉及文件 + +- `frontend/src/constants/cachedPages.ts` +- `frontend/src/pages/TerminalPage.vue` + +## 迁移 / 重启 + +无。仅前端构建/热更新。 + +## 验证 + +```bash +cd frontend && npm run build +pytest tests/test_webssh_terminal_payload.py tests/test_terminal_quick_commands.py -q +``` + +手动:登录 → 终端连接一台服务器 → 侧栏切「服务器」→ 再切回「终端」→ 会话仍 connected,可继续输入;登出后重进终端应为空会话。 diff --git a/docs/changelog/2026-06-21-server-list-created-at-sort.md b/docs/changelog/2026-06-21-server-list-created-at-sort.md new file mode 100644 index 00000000..a55c6e54 --- /dev/null +++ b/docs/changelog/2026-06-21-server-list-created-at-sort.md @@ -0,0 +1,27 @@ +# 服务器列表默认按创建时间倒序 + +**日期**:2026-06-21 + +## 变更摘要 + +服务器列表、推送/终端全量拉取默认 `sort_by=created_at&sort_order=desc`;后端 `server_repo` 无排序参数时同样默认最新在前。 + +## 动机 + +新机入库后应出现在列表顶部,便于运维发现与操作。 + +## 涉及文件 + +- `server/infrastructure/database/server_repo.py` +- `frontend/src/composables/useServerPagination.ts` +- `frontend/src/composables/push/usePushServers.ts` +- `frontend/src/composables/terminal/useTerminalSessions.ts` +- `frontend/src/utils/serverTableSort.ts` + +## 迁移 / 重启 + +需 API 重启(后端排序逻辑)。 + +## 验证 + +打开 `#/servers`,新加服务器应排在前列;终端/推送页服务器下拉顺序一致。 diff --git a/frontend/src/composables/push/usePushServers.ts b/frontend/src/composables/push/usePushServers.ts index 7ec0fef9..eca664a2 100644 --- a/frontend/src/composables/push/usePushServers.ts +++ b/frontend/src/composables/push/usePushServers.ts @@ -45,7 +45,12 @@ export function usePushServers(pushStatus: Ref>) { async function loadServers(silent = false) { if (!silent) serversLoading.value = true try { - const res = await fetchPagePerPage('/servers/', {}, 1, -1) + const res = await fetchPagePerPage( + '/servers/', + { sort_by: 'created_at', sort_order: 'desc' }, + 1, + -1, + ) servers.value = res.items } catch { servers.value = [] diff --git a/frontend/src/composables/terminal/useTerminalSessions.ts b/frontend/src/composables/terminal/useTerminalSessions.ts index de323e6b..31815b7e 100644 --- a/frontend/src/composables/terminal/useTerminalSessions.ts +++ b/frontend/src/composables/terminal/useTerminalSessions.ts @@ -729,7 +729,12 @@ export function useTerminalSessions(nexusDrawer: Ref) { serversLoading.value = true try { await loadHistoryOnly() - const { items } = await fetchPagePerPage('/servers/', {}, 1, -1) + const { items } = await fetchPagePerPage( + '/servers/', + { sort_by: 'created_at', sort_order: 'desc' }, + 1, + -1, + ) servers.value = items.map(toTerminalServerItem) } catch { servers.value = [] diff --git a/frontend/src/composables/useServerPagination.ts b/frontend/src/composables/useServerPagination.ts index 53992734..db10e2ea 100644 --- a/frontend/src/composables/useServerPagination.ts +++ b/frontend/src/composables/useServerPagination.ts @@ -27,7 +27,7 @@ export function useServerPagination(options?: UseServerPaginationOptions) { const categoryFilter = ref('') /** null = all; true = online only; false = offline only */ const isOnlineFilter = ref(null) - const sortBy = ref([{ key: 'status', order: 'asc' }]) + const sortBy = ref([{ key: 'created_at', order: 'desc' }]) function listQueryParams(): Record { const q = String(search.value ?? '').trim() diff --git a/frontend/src/pages/TerminalPage.vue b/frontend/src/pages/TerminalPage.vue index 806e4e67..6580f35f 100644 --- a/frontend/src/pages/TerminalPage.vue +++ b/frontend/src/pages/TerminalPage.vue @@ -115,8 +115,9 @@