using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using MCI18n.AI; using MCI18n.Models; using MCI18n.Services; using MCI18n.Utilities; using Microsoft.Win32; using SharpNBT; using SharpNBT.SNBT; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; namespace MCI18n { public partial class MainWindowViewModel : ObservableObject { private List _oriQuestsData; private List _updatedChapters; private List _langs; [ObservableProperty] private ObservableCollection _chapters; private FTBQuestsService _service; [ObservableProperty] private ObservableCollection _selectedQuests; [ObservableProperty] private bool _loading = false; [ObservableProperty] private bool _multipleLangSupport; [RelayCommand] private void LoadQuests() { var openFolderDialog = new OpenFolderDialog { Title = "选择ftbquests文件夹", Multiselect = false }; if (openFolderDialog.ShowDialog() == true) { try { var folderPath = openFolderDialog.FolderName; _service = new FTBQuestsService(folderPath); var ftbQuests = _service.Parse(); Chapters = []; foreach (var group in ftbQuests.Groups) { foreach (var chapter in group.Chapters) { Chapters.Add(chapter); } } MultipleLangSupport = GlobalContext.MultipleLangSupport; } catch (Exception ex) { MessageBox.Show($"加载文件失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } } [RelayCommand] private void SaveQuest() { //TODO Sava ALL (非多语言) } [RelayCommand] private void SaveQuestAs() { if (GlobalContext.MultipleLangSupport) { /// 另存为多语言文件 var saveFileDialog = new SaveFileDialog { Title = "保存多语言文件", Filter = "SNBT 文件 (*.snbt)|*.snbt", FileName = "zh_cn.snbt", }; if (saveFileDialog.ShowDialog() == true) { try { var filePath = saveFileDialog.FileName; var langData = new CompoundTag(""); langData.Add(new StringTag("file.0000000000000001.title", Application.Current.MainWindow.Title)); foreach (var chapter in Chapters) { langData.Add(new StringTag($"chapter.{chapter.Id}.title", chapter.Title)); if (chapter.Quests != null) { foreach (var quest in chapter.Quests) { langData.Add(new StringTag($"quest.{quest.Id}.title", quest.Title)); if (!string.IsNullOrWhiteSpace(quest.SubTitle)) { langData.Add(new StringTag($"quest.{quest.Id}.quest_subtitle", quest.SubTitle)); } var descLines = quest.Description.Split(new[] { Environment.NewLine }, StringSplitOptions.None); var descList = new ListTag($"quest.{quest.Id}.quest_desc",TagType.String); foreach (var line in descLines) { if(!string.IsNullOrWhiteSpace(line)) descList.Add(new StringTag(null, line)); } langData.Add(descList); } } } SnbtWriter.SaveToFile(langData, filePath, prettyPrint: true); MessageBox.Show("多语言文件保存成功!", "成功", MessageBoxButton.OK, MessageBoxImage.Information); } catch (Exception ex) { MessageBox.Show($"保存文件失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } } } [RelayCommand] private void CreateNewQuest() { } [RelayCommand] private async Task TranslateTheChapter() { Loading = true; try { var aiClient = new I18nChatClient("doubao-1-5-pro-32k-250115"); var translationTasks = new List(); foreach (var item in SelectedQuests) { translationTasks.Add(TranslateQuestAsync(item, aiClient)); } await Task.WhenAll(translationTasks); } finally { Loading = false; } } private async Task TranslateQuestAsync(QuestModel quest, I18nChatClient aiClient) { var titleTask = !string.IsNullOrWhiteSpace(quest.Title) ? aiClient.TranslateAsync(quest.Title, "zh_cn") : Task.FromResult(quest.Title); var subtitleTask = !string.IsNullOrWhiteSpace(quest.SubTitle) ? aiClient.TranslateAsync(quest.SubTitle, "zh_cn") : Task.FromResult(quest.SubTitle); var descriptionTask = !string.IsNullOrWhiteSpace(quest.Description) ? aiClient.TranslateAsync(quest.Description, "zh_cn") : Task.FromResult(quest.Description); // 等待所有翻译任务完成 await Task.WhenAll(titleTask, subtitleTask, descriptionTask); // 更新属性 quest.Title = await titleTask; quest.SubTitle = await subtitleTask; quest.Description = await descriptionTask; } internal void ChapterSelectionChanged(ChapterModel selectedChapter) { if (selectedChapter != null && selectedChapter.Quests != null) { SelectedQuests = selectedChapter.Quests; } else { SelectedQuests = []; } } } }