feat(frontend): 跨服务器传输源机 A 展示可点击站点链接
与服务器列表同源 resolveServerSiteUrl;选 A 后显示域名链接。
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# 审计 — 2026-06-21 跨服务器传输 UI 补强
|
||||
|
||||
**Changelog**: `docs/changelog/2026-06-21-server-transfer-dest-browser.md`、`docs/changelog/2026-06-21-server-transfer-source-site-link.md`
|
||||
|
||||
## Step 3 规则扫描
|
||||
|
||||
| 文件 | 规则 | 结论 |
|
||||
|------|------|------|
|
||||
| `useServerFileTransfer.ts` | B 机 browse 同步 destPath;站点 URL 计算 | PASS |
|
||||
| `ServerTransferPage.vue` | 双端文件表;A 机站点外链 `rel=noopener` | PASS |
|
||||
| `useServerList.ts` | ServerBrief 扩展 extra_attrs 供站点解析 | PASS |
|
||||
|
||||
## 文件清单
|
||||
|
||||
- `frontend/src/composables/useServerFileTransfer.ts`
|
||||
- `frontend/src/composables/useServerList.ts`
|
||||
- `frontend/src/pages/ServerTransferPage.vue`
|
||||
- `docs/changelog/2026-06-21-server-transfer-dest-browser.md`
|
||||
- `docs/changelog/2026-06-21-server-transfer-source-site-link.md`
|
||||
|
||||
## Closure
|
||||
|
||||
| 项 | 状态 |
|
||||
|----|------|
|
||||
| B 机目录浏览 | DONE |
|
||||
| A 机站点链接 | DONE |
|
||||
|
||||
## DoD
|
||||
|
||||
- [x] B 机文件列表与路径同步
|
||||
- [x] A 机下方可点击站点 URL
|
||||
- [x] `vite build` 通过
|
||||
@@ -0,0 +1,17 @@
|
||||
# 跨服务器传输:源机 A 下方展示可点击网址
|
||||
|
||||
**日期**:2026-06-21
|
||||
|
||||
## 摘要
|
||||
|
||||
选择源服务器 A 后,在服务器选择框下方显示站点域名链接(`resolveServerSiteUrl`),新标签页打开。
|
||||
|
||||
## 涉及文件
|
||||
|
||||
- `frontend/src/composables/useServerList.ts` — `ServerBrief` 增加 `description` / `extra_attrs`
|
||||
- `frontend/src/composables/useServerFileTransfer.ts` — `sourceSiteUrl` / `sourceSiteHost`
|
||||
- `frontend/src/pages/ServerTransferPage.vue` — 链接展示
|
||||
|
||||
## 说明
|
||||
|
||||
未 push Gitea;需上线时由用户指示再传输。
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
normalizeRemotePath,
|
||||
parentRemotePath,
|
||||
} from '@/utils/remotePath'
|
||||
import { resolveServerSiteHost, resolveServerSiteUrl } from '@/utils/serverSiteUrl'
|
||||
|
||||
export type ServerTransferMode = 'relay' | 'deliver'
|
||||
|
||||
@@ -83,6 +84,20 @@ export function useServerFileTransfer() {
|
||||
filterServerList(destServers.value, destServerSearchQuery.value, destServerId.value),
|
||||
)
|
||||
|
||||
const selectedSourceServer = computed(() =>
|
||||
sourceServerId.value != null
|
||||
? serverList.value.find((s) => s.id === sourceServerId.value)
|
||||
: undefined,
|
||||
)
|
||||
|
||||
const sourceSiteUrl = computed(() =>
|
||||
selectedSourceServer.value ? resolveServerSiteUrl(selectedSourceServer.value) : null,
|
||||
)
|
||||
|
||||
const sourceSiteHost = computed(() =>
|
||||
selectedSourceServer.value ? resolveServerSiteHost(selectedSourceServer.value) : null,
|
||||
)
|
||||
|
||||
const selectedItems = computed(() => {
|
||||
const set = new Set(selectedPaths.value)
|
||||
return files.value.filter((f) => set.has(joinRemotePath(currentPath.value, f.name)))
|
||||
@@ -456,6 +471,8 @@ export function useServerFileTransfer() {
|
||||
destServerSearchQuery,
|
||||
filteredSourceServerList,
|
||||
filteredDestServerList,
|
||||
sourceSiteUrl,
|
||||
sourceSiteHost,
|
||||
sourceServerId,
|
||||
destServerId,
|
||||
destServers,
|
||||
|
||||
@@ -18,6 +18,8 @@ export interface ServerBrief {
|
||||
category?: string | null
|
||||
is_online?: boolean
|
||||
status?: string
|
||||
description?: string | null
|
||||
extra_attrs?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export function useServerList() {
|
||||
|
||||
@@ -58,6 +58,20 @@
|
||||
</template>
|
||||
</v-autocomplete>
|
||||
|
||||
<div v-if="sourceSiteUrl && sourceSiteHost" class="mb-3 d-flex align-center ga-1">
|
||||
<v-icon size="small" color="primary">mdi-web</v-icon>
|
||||
<a
|
||||
:href="sourceSiteUrl"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-body-2 text-primary text-decoration-none transfer-site-link"
|
||||
:title="`打开 ${sourceSiteHost}`"
|
||||
>
|
||||
{{ sourceSiteHost }}
|
||||
<v-icon size="x-small" class="ml-1">mdi-open-in-new</v-icon>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="d-flex ga-2 mb-3 flex-wrap align-center">
|
||||
<v-text-field
|
||||
:model-value="currentPath"
|
||||
@@ -380,6 +394,8 @@ const {
|
||||
destServerSearchQuery,
|
||||
filteredSourceServerList,
|
||||
filteredDestServerList,
|
||||
sourceSiteUrl,
|
||||
sourceSiteHost,
|
||||
sourceServerId,
|
||||
destServerId,
|
||||
currentPath,
|
||||
@@ -445,4 +461,7 @@ function formatSize(bytes: number): string {
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.transfer-site-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user