Skip to content

Commit 98dbdaf

Browse files
committed
fix(theme): 修复文件导入冲突确认时重复弹出文件选择框的问题,新增导入成功 toast 提示
- ImportThemeResult 新增 file_path 字段,冲突时回传已选文件路径 - 新增 ImportThemeFromFilePath API,确认覆盖直接用缓存路径无需重选文件 - ThemeImportModal 缓存 conflictFilePath,confirmOverwrite 统一管理 loading 状态 - AppearancePage 导入成功后显示 toast 提示
1 parent 7302c5b commit 98dbdaf

4 files changed

Lines changed: 59 additions & 9 deletions

File tree

wind_setting/app_theme.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ type ImportThemeResult struct {
2222
ThemeName string `json:"theme_name"`
2323
Conflict bool `json:"conflict"`
2424
ErrorMsg string `json:"error_msg"`
25+
FilePath string `json:"file_path"` // 文件导入冲突时回传已选路径,供二次确认时直接导入无需重新选择
2526
}
2627

2728
// ImportThemeFromFile 打开系统文件选择对话框,读取并导入 yaml 主题文件。
28-
// force=true 时覆盖同名主题。
29+
// force=true 时覆盖同名主题。冲突时在结果中回传 FilePath,供前端确认覆盖时调用 ImportThemeFromFilePath 无需重新选择文件。
2930
func (a *App) ImportThemeFromFile(force bool) ImportThemeResult {
3031
path, err := wailsRuntime.OpenFileDialog(a.ctx, wailsRuntime.OpenDialogOptions{
3132
Title: "选择主题文件",
@@ -45,7 +46,28 @@ func (a *App) ImportThemeFromFile(force bool) ImportThemeResult {
4546
return ImportThemeResult{ErrorMsg: "读取文件失败: " + err.Error()}
4647
}
4748

48-
return importThemeFromContent(content, force)
49+
result := importThemeFromContent(content, force)
50+
if result.Conflict {
51+
result.FilePath = path
52+
}
53+
return result
54+
}
55+
56+
// ImportThemeFromFilePath 直接使用已知路径导入主题文件,不再打开文件选择对话框。
57+
// 用于文件导入冲突确认后的二次调用:前端缓存第一次选择的路径,确认覆盖时传入。
58+
func (a *App) ImportThemeFromFilePath(path string, force bool) ImportThemeResult {
59+
if path == "" {
60+
return ImportThemeResult{ErrorMsg: "文件路径不能为空"}
61+
}
62+
content, err := os.ReadFile(path)
63+
if err != nil {
64+
return ImportThemeResult{ErrorMsg: "读取文件失败: " + err.Error()}
65+
}
66+
result := importThemeFromContent(content, force)
67+
if result.Conflict {
68+
result.FilePath = path
69+
}
70+
return result
4971
}
5072

5173
// ImportThemeFromURL 从指定 URL 下载并导入 yaml 主题文件。

wind_setting/frontend/src/api/wails.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,7 @@ export interface ImportThemeResult {
10031003
theme_name: string;
10041004
conflict: boolean;
10051005
error_msg: string;
1006+
file_path: string;
10061007
}
10071008

10081009
export async function importThemeFromFile(
@@ -1013,6 +1014,16 @@ export async function importThemeFromFile(
10131014
) as ImportThemeResult;
10141015
}
10151016

1017+
export async function importThemeFromFilePath(
1018+
path: string,
1019+
force: boolean,
1020+
): Promise<ImportThemeResult> {
1021+
return (window as any).go.main.App.ImportThemeFromFilePath(
1022+
path,
1023+
force,
1024+
) as ImportThemeResult;
1025+
}
1026+
10161027
export async function importThemeFromText(
10171028
yamlContent: string,
10181029
force: boolean,

wind_setting/frontend/src/components/ThemeImportModal.vue

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ const activeTab = ref<Tab>("file");
2525
const loading = ref(false);
2626
const errorMsg = ref("");
2727
const conflictName = ref("");
28+
const conflictFilePath = ref(""); // 文件导入冲突时缓存已选路径,确认覆盖无需重新选文件
2829
const yamlText = ref("");
2930
const urlInput = ref("");
3031
3132
function resetState() {
3233
errorMsg.value = "";
3334
conflictName.value = "";
35+
conflictFilePath.value = "";
3436
}
3537
3638
function close() {
@@ -84,25 +86,36 @@ function handleResult(result: wailsApi.ImportThemeResult) {
8486
}
8587
if (result.conflict) {
8688
conflictName.value = result.theme_name;
89+
conflictFilePath.value = result.file_path ?? "";
8790
errorMsg.value = "";
8891
return;
8992
}
9093
errorMsg.value = result.error_msg || "导入失败";
9194
}
9295
9396
async function confirmOverwrite() {
94-
if (activeTab.value === "file") {
95-
await handleFileImport(true);
96-
} else if (activeTab.value === "text") {
97-
await handleTextImport(true);
98-
} else {
99-
await handleURLImport(true);
97+
loading.value = true;
98+
errorMsg.value = "";
99+
try {
100+
let result: wailsApi.ImportThemeResult;
101+
if (activeTab.value === "file" && conflictFilePath.value) {
102+
result = await wailsApi.importThemeFromFilePath(conflictFilePath.value, true);
103+
} else if (activeTab.value === "text") {
104+
result = await wailsApi.importThemeFromText(yamlText.value, true);
105+
} else {
106+
result = await wailsApi.importThemeFromURL(urlInput.value, true);
107+
}
108+
conflictName.value = "";
109+
conflictFilePath.value = "";
110+
handleResult(result);
111+
} finally {
112+
loading.value = false;
100113
}
101-
conflictName.value = "";
102114
}
103115
104116
function cancelOverwrite() {
105117
conflictName.value = "";
118+
conflictFilePath.value = "";
106119
}
107120
108121
async function pasteFromClipboard() {

wind_setting/frontend/src/pages/AppearancePage.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
indicatorSchema,
4545
} from "@/schemas/appearance.schema";
4646
import type { PageSchema } from "@/schemas/types";
47+
import { useToast } from "../composables/useToast";
4748
4849
const props = defineProps<{
4950
formData: Config;
@@ -62,6 +63,8 @@ const emit = defineEmits<{
6263
themeDeleted: [themeName: string];
6364
}>();
6465
66+
const { toast } = useToast();
67+
6568
const themeImportOpen = ref(false);
6669
6770
const themeServerRunning = ref(false);
@@ -72,6 +75,7 @@ const themeServerLoading = ref(false);
7275
function onThemeImported(themeName: string) {
7376
themeImportOpen.value = false;
7477
emit("themeImported", themeName);
78+
toast(`主题「${themeName}」导入成功`);
7579
}
7680
7781
const themeSelectOpen = ref(false);

0 commit comments

Comments
 (0)