From 3ff531f4188698eb0465b61184dc95136d805a19 Mon Sep 17 00:00:00 2001 From: BTMuli Date: Thu, 9 Mar 2023 13:14:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(achievement):=20=E5=AF=BC=E5=85=A5=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E9=80=BB=E8=BE=91=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Achievements.vue | 272 ++++++++++----------------- src/plugins/UIAF/utils/importData.ts | 7 +- src/store/modules/achievements.ts | 15 ++ 3 files changed, 124 insertions(+), 170 deletions(-) diff --git a/src/pages/Achievements.vue b/src/pages/Achievements.vue index 72deb1e6..e288750d 100644 --- a/src/pages/Achievements.vue +++ b/src/pages/Achievements.vue @@ -10,37 +10,16 @@ 导入 - - - 合并 - 导出 - - + - - - - - - - - - - - - - - - - - - + + @@ -52,11 +31,11 @@ import UIAF_Oper from "../plugins/UIAF"; import { dialog, fs } from "@tauri-apps/api"; import { UIAF_Achievement, Achievements } from "../plugins/UIAF/interface/UIAF"; import { - Achievement as TGAchievement, - AchievementSeries as TGAchievementSeries, - AchievementDisplay as TGAchievementDisplay, - AchievementSeriesDisplay as TGAchievementSeriesDisplay, + AchievementMap as TGAchievementMap, + SeriesMap as TGSeriesMap, } from "../interface/Achievements"; +import TGMap from "../utils/TGMap"; +import { Map } from "../interface/Base"; export default defineComponent({ name: "Achievements", @@ -65,16 +44,45 @@ export default defineComponent({ // 标题 成就完成数/成就总数 完成率 title: "" as string, // 成就系列列表,用于侧边栏 - seriesList: [] as TGAchievementSeries[], - // 成就列表-所有 - achievementsAll: [] as TGAchievementDisplay[], + seriesList: {} as Map, + // 成就列表-所有成就的数据 + achievementsList: {} as Map, + // 选中的成就系列 id,用于决定右侧显示的成就列表 + selectedSeries: -1 as number, }; }, async mounted() { await this.loadData(); }, methods: { - // 导入 + // 加载数据,数据源:合并后的本地数据 + async loadData() { + const appStore = useAppStore(); + const achievementsStore = useAchievementsStore(); + const localSeriesPath = appStore.mergePath.achievementSeries; + const localAchievementsPath = appStore.mergePath.achievements; + const seriesMap: TGMap = new TGMap( + JSON.parse(await fs.readTextFile(localSeriesPath)) + ); + const achievementsMap: TGMap = new TGMap( + JSON.parse(await fs.readTextFile(localAchievementsPath)) + ); + await achievementsStore.flushData(seriesMap); + this.title = this.getTitle(); + this.achievementsList = achievementsMap.getMap(); + this.seriesList = seriesMap.getMap(); + }, + // 获取标题 + getTitle() { + const achievementsStore = useAchievementsStore(); + const achievementsAll = achievementsStore.total_achievements; + const achievementsDone = achievementsStore.fin_achievements; + return `成就完成数:${achievementsDone}/${achievementsAll} 完成率:${( + (achievementsDone / achievementsAll) * + 100 + ).toFixed(2)}%`; + }, + // 导入 UIAF 数据,进行数据合并、刷新 async importJson() { const appStore = useAppStore(); const localPath = appStore.userPath.achievements; @@ -87,55 +95,71 @@ export default defineComponent({ }, ], }); - // 选中文件 - if (selectedFile) { - console.log("正在读取本地文件..."); - // 读取应用内文件 + if (selectedFile && (await UIAF_Oper.importOper.checkUIAFData(selectedFile))) { const localRaw: string | false = await UIAF_Oper.importOper.readUIAFData(localPath); - console.log("读取本地文件成功"); - // 检测文件是否符合 UIAF 格式 - console.log("正在检测文件格式..."); - if (await UIAF_Oper.importOper.checkUIAFData(selectedFile)) { - await console.log("检测文件格式成功, 开始导入..."); - // 读取选中文件 - const remoteRaw: string | false = await UIAF_Oper.importOper.readUIAFData( - selectedFile - ); - console.log("读取选中文件成功,开始解析数据..."); - // 解析数据 - let localData: UIAF_Achievement[] | false = false; - let remoteData: Achievements; - if (localRaw !== false) { - localData = JSON.parse(localRaw); - } - await console.log("解析数据成功,开始合并数据..."); - if (localData === false) { - localData = []; - } - if (remoteRaw === false) { - await dialog.message("文件格式不正确,导入失败"); - return; - } - remoteData = JSON.parse(remoteRaw); - // 数据合并 - const mergedData = await UIAF_Oper.importOper.mergeUIAFData( - localData, - remoteData - ); - if (mergedData === false) { - await dialog.message("合并数据失败,请检查文件是否符合 UIAF 格式"); - return; - } - await console.log("合并数据成功,开始写入数据..."); - // 写入数据 - await fs.writeTextFile(localPath, JSON.stringify(mergedData, null, 2)); - await console.log("写入数据成功,导入完成"); - await console.log("正在刷新数据..."); - // 刷新数据 - await this.flushStore(mergedData.length); - } else { - await dialog.message("文件格式不正确,请检查文件是否符合 UIAF 格式"); + const remoteRaw: string | false = await UIAF_Oper.importOper.readUIAFData( + selectedFile + ); + if (remoteRaw === false) { + await dialog.message("文件格式不正确,导入失败"); + return; } + let remoteData: Achievements = JSON.parse(remoteRaw); + let localData: UIAF_Achievement[] = JSON.parse(localRaw || "[]"); + // 因为 + const mergeUIAF: UIAF_Achievement[] = await UIAF_Oper.importOper.mergeUIAFData( + localData, + remoteData + ); + await fs.writeTextFile(localPath, JSON.stringify(mergeUIAF, null, 4)); + // 读取本地 mergeData + const mergeAchievementMap: TGMap = new TGMap( + JSON.parse(await fs.readTextFile(appStore.mergePath.achievements)) + ); + const mergeSeriesMap: TGMap = new TGMap( + JSON.parse(await fs.readTextFile(appStore.mergePath.achievementSeries)) + ); + // 遍历 mergeUIAF,对 mergeData 进行更新 + mergeUIAF.map(UIAF_Item => { + // 更新成就 + if (mergeAchievementMap.has(UIAF_Item.id)) { + const achievement = mergeAchievementMap.get(UIAF_Item.id); + achievement.completed = true; + achievement.completed_time = new Date( + UIAF_Item.timestamp * 1000 + ).toLocaleString(); + mergeAchievementMap.set(UIAF_Item.id, achievement); + // 如果成就系列中没有该成就,则添加 + if (!mergeSeriesMap.has(achievement.series)) { + const series = mergeSeriesMap.get(achievement.series); + series.achievements.push(achievement.id); + mergeSeriesMap.set(achievement.series, series); + } + } + }); + // 更新成就系列 + mergeSeriesMap.forEach(seriesMap => { + let completed = 0; + seriesMap.achievements.map(achievement => { + if (mergeAchievementMap.get(achievement).completed) { + completed++; + } + }); + seriesMap.completed_count = completed; + seriesMap.total_count = seriesMap.achievements.length; + mergeSeriesMap.set(seriesMap.id, seriesMap); + }); + // 写入数据 + await fs.writeTextFile( + appStore.mergePath.achievements, + JSON.stringify(mergeAchievementMap.getMap(), null, 4) + ); + await fs.writeTextFile( + appStore.mergePath.achievementSeries, + JSON.stringify(mergeSeriesMap.getMap(), null, 4) + ); + // 刷新数据 + await this.loadData(); } }, // 导出 @@ -156,97 +180,9 @@ export default defineComponent({ ], }); if (is_save) { - await fs.writeTextFile(is_save, JSON.stringify(achievements, null, 2)); + await fs.writeTextFile(is_save, JSON.stringify(achievements, null, 4)); } }, - // 获取 MergeData - async mergeJson() { - const appStore = useAppStore(); - const localPath = appStore.userPath.achievements; - // 读取用户的 UIAF 数据 - const localRaw: string | false = await UIAF_Oper.importOper.readUIAFData(localPath); - if (localRaw === false) { - await dialog.message("读取用户数据失败,请检查文件是否符合 UIAF 格式"); - return; - } - const localData: UIAF_Achievement[] = JSON.parse(localRaw); - // 读取 MergeData - const mergeAchievementRaw = await fs.readTextFile(appStore.mergePath.achievements); - const mergeSeriesRaw = await fs.readTextFile(appStore.mergePath.achievementSeries); - const mergeAchievementData: TGAchievementDisplay[] = JSON.parse(mergeAchievementRaw); - const mergeSeriesData: TGAchievementSeriesDisplay[] = JSON.parse(mergeSeriesRaw); - // 遍历 localData,对 MergeData 进行更新 - localData.map(localAchievement => { - const achievementSingle = mergeAchievementData.find( - achievement => achievement.id === localAchievement.id - ); - if (achievementSingle) { - achievementSingle.completed = true; - achievementSingle.completed_time = new Date( - localAchievement.timestamp * 1000 - ).toLocaleString(); - } - }); - // 遍历 mergeSeries 对 mergeSeries 进行更新 - // todo 缺乏拓展性 - mergeSeriesData.map(mergeSeries => { - let completed = 0; - // 更新成就 - mergeSeries.achievements.map(achievement => { - const findAchievement = mergeAchievementData.find(achievementSingle => { - return achievementSingle.id === achievement.id; - }); - if (findAchievement) { - if (findAchievement !== achievement) { - achievement.completed = findAchievement.completed; - achievement.completed_time = findAchievement.completed_time; - } - } - if (achievement.completed) { - completed++; - } - }); - // 更新系列 - mergeSeries.completed_count = completed; - }); - // 写入数据 - await fs.writeTextFile( - appStore.mergePath.achievements, - JSON.stringify(mergeAchievementData, null, 4) - ); - await fs.writeTextFile( - appStore.mergePath.achievementSeries, - JSON.stringify(mergeSeriesData, null, 4) - ); - await dialog.message("合并数据成功"); - }, - // 获取标题 - getTitle() { - const achievementsStore = useAchievementsStore(); - const achievementsAll = achievementsStore.total_achievements; - const achievementsDone = achievementsStore.fin_achievements; - return `成就完成数:${achievementsDone}/${achievementsAll} 完成率:${( - (achievementsDone / achievementsAll) * - 100 - ).toFixed(2)}%`; - }, - // 刷新数据 - async flushStore(fin_num: number) { - const achievementsStore = useAchievementsStore(); - achievementsStore.fin_achievements = fin_num; - const appStore = useAppStore(); - const localPath = appStore.appPath.achievements; - const localRaw: string = await fs.readTextFile(localPath); - const localData: TGAchievement[] = JSON.parse(localRaw); - achievementsStore.total_achievements = localData.length; - this.title = this.getTitle(); - }, - // 加载数据 - async loadData() { - this.title = this.getTitle(); - // this.seriesList = TGAppData.MergeData.achievementSeries; - // this.achievementsAll = TGAppData.MergeData.achievements; - }, }, }); diff --git a/src/plugins/UIAF/utils/importData.ts b/src/plugins/UIAF/utils/importData.ts index fe42fe8d..e2d82cba 100644 --- a/src/plugins/UIAF/utils/importData.ts +++ b/src/plugins/UIAF/utils/importData.ts @@ -11,6 +11,7 @@ import { fs } from "@tauri-apps/api"; /** * @description 检测是否存在 UIAF 数据 * @description 粗略检测,不保证数据完整性 + * @since Alpha * @param {string} path - UIAF 数据路径 * @return {Promise} 是否存在 UIAF 数据 */ @@ -22,6 +23,7 @@ export async function checkUIAFData(path: string): Promise { /** * @description 读取 UIAF 数据 + * @since Alpha * @param {string} userPath - UIAF 数据路径 * @return {Promise} UIAF 数据 */ @@ -40,14 +42,15 @@ export async function readUIAFData(userPath: string): Promise { /** * @description 数据合并 + * @since Alpha * @param {UIAF_Achievement[]} localData - 本地数据 * @param {Achievements} remoteData - 远程数据 - * @return {Promise} 合并后的数据,如果合并失败则返回 false + * @return {Promise} 合并后的数据 */ export async function mergeUIAFData( localData: UIAF_Achievement[], remoteData: Achievements -): Promise { +): Promise { // 遍历 remoteData.list remoteData.list.map((remoteAchievement: UIAF_Achievement) => { // 查找 id 相同的 localAchievement diff --git a/src/store/modules/achievements.ts b/src/store/modules/achievements.ts index da3abec0..aa959e23 100644 --- a/src/store/modules/achievements.ts +++ b/src/store/modules/achievements.ts @@ -6,6 +6,8 @@ */ import { defineStore } from "pinia"; +import TGMap from "../../utils/TGMap"; +import { SeriesMap } from "../../interface/Achievements"; const useAchievementsStore = defineStore({ id: "achievements", @@ -13,10 +15,23 @@ const useAchievementsStore = defineStore({ return { total_achievements: 899, fin_achievements: 0, + // 这个数据用于说明当前的数据版本,不会被渲染 last_version: "v3.5", UIAF_Version: "v1.1", }; }, + actions: { + flushData(seriesMap: TGMap) { + let total = 0; + let fin = 0; + seriesMap.forEach(series => { + total += series.total_count; + fin += series.completed_count; + }); + this.total_achievements = total; + this.fin_achievements = fin; + }, + }, persist: true, });