Skip to content

Commit a37618f

Browse files
committed
feat: 下载路径自动转换 Windows/Linux 路径
- 后端 /status API 新增 platform 字段,返回 linux/windows - 前端下载器设置页显示当前平台标识 - 添加「路径转换」按钮,一键在 /downloads/ 和 D:\ 之间切换
1 parent ce0ba8f commit a37618f

3 files changed

Lines changed: 93 additions & 14 deletions

File tree

backend/src/module/api/program.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
import os
33
import signal
4+
import sys
45

56
from fastapi import APIRouter, Depends, HTTPException
67
from fastapi.responses import JSONResponse
@@ -68,18 +69,14 @@ async def stop():
6869

6970
@router.get("/status", response_model=dict, dependencies=[Depends(get_current_user)])
7071
async def program_status():
71-
if not program.is_running:
72-
return {
73-
"status": False,
74-
"version": VERSION,
75-
"first_run": program.first_run,
76-
}
77-
else:
78-
return {
79-
"status": True,
80-
"version": VERSION,
81-
"first_run": program.first_run,
82-
}
72+
is_linux = sys.platform == "linux"
73+
base = {
74+
"status": program.is_running,
75+
"version": VERSION,
76+
"first_run": program.first_run,
77+
"platform": "linux" if is_linux else "windows",
78+
}
79+
return base
8380

8481

8582
@router.get(

webui/src/api/program.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export const apiProgram = {
2929
* 状态
3030
*/
3131
async status() {
32-
const { data } = await axios.get<{ status: boolean; version: string }>(
32+
const { data } = await axios.get<{ status: boolean; version: string; platform: string; first_run: boolean }>(
3333
'api/v1/status'
3434
);
3535

webui/src/components/setting/config-download.vue

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,42 @@
1-
<script lang="ts" setup>
1+
<script lang="ts" setup>
22
import type { Downloader, DownloaderType } from '#/config';
33
import type { SettingItem } from '#/components';
4+
import { ref, onMounted } from 'vue';
5+
import { apiProgram } from '@/api/program';
46
57
const { t } = useMyI18n();
68
const { getSettingGroup } = useConfigStore();
79
810
const downloader = getSettingGroup('downloader');
911
const downloaderType: DownloaderType = ['qbittorrent'];
1012
13+
const platform = ref<string>('linux');
14+
15+
onMounted(async () => {
16+
try {
17+
const status = await apiProgram.status();
18+
platform.value = status.platform;
19+
} catch {
20+
platform.value = 'linux';
21+
}
22+
});
23+
24+
function convertPath() {
25+
const current = downloader.path as string;
26+
if (!current) return;
27+
if (platform.value === 'linux') {
28+
const winPath = current.replace(/^\/downloads\//, 'D:\\').replace(/\//g, '\\');
29+
if (winPath !== current) {
30+
downloader.path = winPath;
31+
}
32+
} else {
33+
const linuxPath = current.replace(/^[A-Za-z]:\\/, '/downloads/').replace(/\\/g, '/');
34+
if (linuxPath !== current) {
35+
downloader.path = linuxPath;
36+
}
37+
}
38+
}
39+
1140
const items: SettingItem<Downloader>[] = [
1241
{
1342
configKey: 'type',
@@ -72,6 +101,59 @@ const items: SettingItem<Downloader>[] = [
72101
v-bind="i"
73102
v-model:data="downloader[i.configKey]"
74103
></ab-setting>
104+
<div class="convert-bar">
105+
<span class="convert-label">{{ $t('config.downloader_set.path') }}</span>
106+
<div class="convert-actions">
107+
<span class="platform-badge">{{ platform === 'linux' ? 'Linux/Docker' : 'Windows' }}</span>
108+
<button class="convert-btn" @click="convertPath">
109+
路径转换 &rarr;
110+
</button>
111+
</div>
112+
</div>
75113
</div>
76114
</ab-fold-panel>
77115
</template>
116+
117+
<style scoped>
118+
.convert-bar {
119+
display: flex;
120+
align-items: center;
121+
justify-content: space-between;
122+
padding: 8px 12px;
123+
background: var(--el-color-info-light-9);
124+
border-radius: 6px;
125+
font-size: 13px;
126+
margin-top: 8px;
127+
}
128+
.convert-label {
129+
color: var(--el-text-color-secondary);
130+
}
131+
.convert-actions {
132+
display: flex;
133+
align-items: center;
134+
gap: 8px;
135+
}
136+
.platform-badge {
137+
padding: 2px 8px;
138+
border-radius: 4px;
139+
background: var(--el-color-primary-light-9);
140+
color: var(--el-color-primary);
141+
font-size: 12px;
142+
font-weight: 500;
143+
}
144+
.convert-btn {
145+
padding: 4px 12px;
146+
border: 1px solid var(--el-border-color);
147+
border-radius: 4px;
148+
background: var(--el-bg-color);
149+
color: var(--el-text-color-primary);
150+
cursor: pointer;
151+
font-size: 12px;
152+
transition: all 0.2s;
153+
}
154+
.convert-btn:hover {
155+
background: var(--el-color-primary-light-9);
156+
border-color: var(--el-color-primary);
157+
color: var(--el-color-primary);
158+
}
159+
</style>

0 commit comments

Comments
 (0)