mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-13 09:28:14 +08:00
fix(achievements): 精简代码,完成 IndexedDB 的接轨,删去 dev 相关页面
This commit is contained in:
@@ -37,11 +37,6 @@
|
|||||||
<img src="../assets/icons/setting.svg" alt="setting" class="sideIcon" />
|
<img src="../assets/icons/setting.svg" alt="setting" class="sideIcon" />
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item link href="/dev" v-show="showDev" title="开发">
|
|
||||||
<template v-slot:prepend>
|
|
||||||
<v-icon>mdi-bug-outline</v-icon>
|
|
||||||
</template>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
</v-list>
|
||||||
</v-navigation-drawer>
|
</v-navigation-drawer>
|
||||||
</template>
|
</template>
|
||||||
@@ -50,14 +45,11 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import useAppStore from "../store/modules/app";
|
import useAppStore from "../store/modules/app";
|
||||||
import useDevStore from "../store/modules/dev";
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const devStore = useDevStore();
|
|
||||||
|
|
||||||
const rail = ref(appStore.sidebar);
|
const rail = ref(appStore.sidebar);
|
||||||
const showDev = ref(devStore.showDev);
|
|
||||||
|
|
||||||
const back = () => {
|
const back = () => {
|
||||||
try {
|
try {
|
||||||
@@ -70,16 +62,6 @@ function collapse() {
|
|||||||
rail.value = !rail.value;
|
rail.value = !rail.value;
|
||||||
appStore.sidebar = rail.value;
|
appStore.sidebar = rail.value;
|
||||||
}
|
}
|
||||||
function magicClick() {
|
|
||||||
// 打包的时候不显示开发功能
|
|
||||||
// if (!showDev.value) {
|
|
||||||
// devStore.magicCount++;
|
|
||||||
// if (devStore.magicCount >= 10) {
|
|
||||||
// showDev.value = true;
|
|
||||||
// devStore.showDev = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="css">
|
<style lang="css">
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
* @author BTMuli<bt-muli@outlook.com>
|
* @author BTMuli<bt-muli@outlook.com>
|
||||||
* @since Alpha
|
* @since Alpha
|
||||||
*/
|
*/
|
||||||
import { MergeData } from "../merge";
|
import { AchievementSeries } from "../../interface/Achievements";
|
||||||
import { SeriesMap } from "../../interface/Achievements";
|
|
||||||
import { Map } from "../../interface/Base";
|
import { Map } from "../../interface/Base";
|
||||||
|
import { AppData } from "../app";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 成就系列表参数
|
* @description 成就系列表参数
|
||||||
@@ -15,16 +15,16 @@ import { Map } from "../../interface/Base";
|
|||||||
export const Config = {
|
export const Config = {
|
||||||
storeName: "AchievementSeries",
|
storeName: "AchievementSeries",
|
||||||
keyPath: "id",
|
keyPath: "id",
|
||||||
indexes: ["order", "name", "version", "card", "total_count", "complete_count"],
|
indexes: ["order", "name", "card"],
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 成就系列数据
|
* @description 成就系列数据
|
||||||
* @since Alpha
|
* @since Alpha
|
||||||
* @return {SeriesMap[]}
|
* @return {AchievementSeries[]}
|
||||||
*/
|
*/
|
||||||
export function getData() {
|
export function getData() {
|
||||||
const data: Map<SeriesMap> = MergeData.achievementSeries;
|
const data: Map<AchievementSeries> = AppData.achievementSeries;
|
||||||
return Object.keys(data).map(key => {
|
return Object.keys(data).map(key => {
|
||||||
return data[Number(key)];
|
return data[Number(key)];
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* @author BTMuli<bt-muli@outlook.com>
|
* @author BTMuli<bt-muli@outlook.com>
|
||||||
* @since Alpha
|
* @since Alpha
|
||||||
*/
|
*/
|
||||||
import { TGAppData } from "../index";
|
import { AppData } from "../app";
|
||||||
import { Achievement } from "../../interface/Achievements";
|
import { Achievement } from "../../interface/Achievements";
|
||||||
import { Map } from "../../interface/Base";
|
import { Map } from "../../interface/Base";
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ export const Config = {
|
|||||||
* @return {Achievement[]}
|
* @return {Achievement[]}
|
||||||
*/
|
*/
|
||||||
export function getData() {
|
export function getData() {
|
||||||
const data: Map<Achievement> = TGAppData.achievements;
|
const data: Map<Achievement> = AppData.achievements;
|
||||||
return Object.keys(data).map(key => {
|
return Object.keys(data).map(key => {
|
||||||
return data[Number(key)];
|
return data[Number(key)];
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ import { onMounted, ref } from "vue";
|
|||||||
// Store
|
// Store
|
||||||
import useAchievementsStore from "../store/modules/achievements";
|
import useAchievementsStore from "../store/modules/achievements";
|
||||||
// Interface
|
// Interface
|
||||||
import { Achievements } from "../plugins/UIAF/interface/UIAF";
|
import { Achievements, UIAF_Info, UIAF_Achievement } from "../plugins/UIAF/interface/UIAF";
|
||||||
import {
|
import {
|
||||||
Achievement as TGAchievement,
|
Achievement as TGAchievement,
|
||||||
AchievementSeries as TGSeries,
|
AchievementSeries as TGSeries,
|
||||||
@@ -112,7 +112,12 @@ import { NameCard } from "../interface/NameCard";
|
|||||||
import UIAF_Oper from "../plugins/UIAF";
|
import UIAF_Oper from "../plugins/UIAF";
|
||||||
// Utils
|
// Utils
|
||||||
import { createTGWindow } from "../utils/TGWindow";
|
import { createTGWindow } from "../utils/TGWindow";
|
||||||
import { ReadAllTGData, ReadTGData, UpdateTGData } from "../utils/TGIndex";
|
import {
|
||||||
|
ReadAllTGData,
|
||||||
|
ReadTGDataByIndex,
|
||||||
|
ReadTGDataByKey,
|
||||||
|
UpdateTGDataByKey,
|
||||||
|
} from "../utils/TGIndex";
|
||||||
|
|
||||||
// Store
|
// Store
|
||||||
const achievementsStore = useAchievementsStore();
|
const achievementsStore = useAchievementsStore();
|
||||||
@@ -133,7 +138,7 @@ onMounted(() => {
|
|||||||
// 加载数据,数据源:合并后的本地数据
|
// 加载数据,数据源:合并后的本地数据
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
const seriesDB: TGSeries[] = await ReadAllTGData("AchievementSeries");
|
const seriesDB: TGSeries[] = await ReadAllTGData("AchievementSeries");
|
||||||
CardsInfo.value = await ReadTGData("NameCard", "type", 1);
|
CardsInfo.value = await ReadTGDataByIndex("NameCard", "type", 1);
|
||||||
// 按照 order 排序
|
// 按照 order 排序
|
||||||
seriesList.value = seriesDB.sort((a, b) => a.order - b.order);
|
seriesList.value = seriesDB.sort((a, b) => a.order - b.order);
|
||||||
selectedAchievement.value = await ReadAllTGData("Achievements");
|
selectedAchievement.value = await ReadAllTGData("Achievements");
|
||||||
@@ -143,7 +148,11 @@ async function loadData() {
|
|||||||
async function selectSeries(index: number) {
|
async function selectSeries(index: number) {
|
||||||
selectedIndex.value = index;
|
selectedIndex.value = index;
|
||||||
selectedSeries.value = seriesList.value[index].id;
|
selectedSeries.value = seriesList.value[index].id;
|
||||||
selectedAchievement.value = await ReadTGData("Achievements", "series", selectedSeries.value);
|
selectedAchievement.value = await ReadTGDataByIndex(
|
||||||
|
"Achievements",
|
||||||
|
"series",
|
||||||
|
selectedSeries.value
|
||||||
|
);
|
||||||
if (selectedSeries.value !== 0 && selectedSeries.value !== 17) {
|
if (selectedSeries.value !== 0 && selectedSeries.value !== 17) {
|
||||||
getCardInfo.value = CardsInfo.value.find(card => card.name === seriesList.value[index].card)!;
|
getCardInfo.value = CardsInfo.value.find(card => card.name === seriesList.value[index].card)!;
|
||||||
} else {
|
} else {
|
||||||
@@ -174,8 +183,8 @@ async function importJson() {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
if (selectedFile && (await UIAF_Oper.importOper.checkUIAFData(<string>selectedFile))) {
|
if (selectedFile && (await UIAF_Oper.checkUIAFData(<string>selectedFile))) {
|
||||||
const remoteRaw: string | false = await UIAF_Oper.importOper.readUIAFData(<string>selectedFile);
|
const remoteRaw: string | false = await UIAF_Oper.readUIAFData(<string>selectedFile);
|
||||||
if (remoteRaw === false) {
|
if (remoteRaw === false) {
|
||||||
await dialog.message("文件格式不正确,导入失败");
|
await dialog.message("文件格式不正确,导入失败");
|
||||||
return;
|
return;
|
||||||
@@ -185,7 +194,7 @@ async function importJson() {
|
|||||||
remoteData.list.map(async data => {
|
remoteData.list.map(async data => {
|
||||||
// 获取 id
|
// 获取 id
|
||||||
const id = data.id;
|
const id = data.id;
|
||||||
let localData: TGAchievement = (await ReadTGData("Achievements", "id", id))[0];
|
let localData: TGAchievement = (await ReadTGDataByKey("Achievements", [id]))[0];
|
||||||
// 获取 timeStamp 2023-03-15 00:00:00
|
// 获取 timeStamp 2023-03-15 00:00:00
|
||||||
const localTime = localData.completed_time;
|
const localTime = localData.completed_time;
|
||||||
// 如果本地数据不存在,或者本地数据的 timeStamp 小于远程数据的 timeStamp,更新数据
|
// 如果本地数据不存在,或者本地数据的 timeStamp 小于远程数据的 timeStamp,更新数据
|
||||||
@@ -203,21 +212,46 @@ async function importJson() {
|
|||||||
localData.completed = data.status === 3;
|
localData.completed = data.status === 3;
|
||||||
}
|
}
|
||||||
// 更新数据
|
// 更新数据
|
||||||
await UpdateTGData("Achievements", "id", id, localData);
|
await UpdateTGDataByKey("Achievements", localData);
|
||||||
});
|
});
|
||||||
const fin_achievements = (await ReadTGData("Achievements", "completed", true)).length;
|
// 更新成就系列的完成数
|
||||||
const total_achievements = (await ReadAllTGData("Achievements")).length;
|
const seriesDB = await ReadAllTGData("AchievementSeries");
|
||||||
await achievementsStore.flushData(fin_achievements, total_achievements);
|
seriesDB.map(async data => {
|
||||||
|
const seriesId = data.id;
|
||||||
|
const achievementsDB = await ReadTGDataByIndex("Achievements", "series", seriesId);
|
||||||
|
data.completed_count = achievementsDB.filter(data => {
|
||||||
|
return data.completed === true;
|
||||||
|
}).length;
|
||||||
|
await UpdateTGDataByKey("AchievementSeries", data);
|
||||||
|
});
|
||||||
|
const achievementsDB = await ReadAllTGData("Achievements");
|
||||||
|
const fin_achievements = achievementsDB.filter(data => {
|
||||||
|
return data.completed === true;
|
||||||
|
}).length;
|
||||||
|
const total_achievements = achievementsDB.length;
|
||||||
|
console.log(fin_achievements, total_achievements);
|
||||||
|
achievementsStore.flushData(total_achievements, fin_achievements);
|
||||||
// 刷新数据
|
// 刷新数据
|
||||||
await loadData();
|
await loadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 导出
|
// 导出
|
||||||
async function exportJson() {
|
async function exportJson() {
|
||||||
|
// 判断是否有数据
|
||||||
|
if (achievementsStore.fin_achievements === 0) {
|
||||||
|
await dialog.message("没有数据可以导出");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 获取本地数据
|
// 获取本地数据
|
||||||
const achievements = await ReadTGData("Achievements", "completed", true);
|
const achievements = (await ReadAllTGData("Achievements")).filter(data => {
|
||||||
|
return data.progress !== 0 || data.completed === true;
|
||||||
|
});
|
||||||
|
let UIAF_DATA = {
|
||||||
|
info: {} as UIAF_Info,
|
||||||
|
list: [] as UIAF_Achievement[],
|
||||||
|
};
|
||||||
// 转换数据
|
// 转换数据
|
||||||
let achievementsList = achievements.map(data => {
|
UIAF_DATA.list = achievements.map(data => {
|
||||||
let status;
|
let status;
|
||||||
// 计算点数但是没有完成
|
// 计算点数但是没有完成
|
||||||
if (data.progress !== 0 && data.completed === false) {
|
if (data.progress !== 0 && data.completed === false) {
|
||||||
@@ -238,6 +272,7 @@ async function exportJson() {
|
|||||||
status: status,
|
status: status,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
UIAF_DATA.info = await UIAF_Oper.getUIAFInfo();
|
||||||
const is_save = await dialog.save({
|
const is_save = await dialog.save({
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
@@ -247,7 +282,7 @@ async function exportJson() {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
if (is_save) {
|
if (is_save) {
|
||||||
await fs.writeTextFile(is_save, JSON.stringify(achievementsList, null, 4));
|
await fs.writeTextFile(is_save, JSON.stringify(UIAF_DATA));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ import useAppStore from "../store/modules/app";
|
|||||||
import useAchievementsStore from "../store/modules/achievements";
|
import useAchievementsStore from "../store/modules/achievements";
|
||||||
import { dialog, fs } from "@tauri-apps/api";
|
import { dialog, fs } from "@tauri-apps/api";
|
||||||
import { BaseDirectory } from "@tauri-apps/api/fs";
|
import { BaseDirectory } from "@tauri-apps/api/fs";
|
||||||
import { TGAppDataList } from "../data";
|
|
||||||
|
|
||||||
// Store
|
// Store
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
@@ -77,7 +76,7 @@ function changeRenderMode() {
|
|||||||
// 打开用户数据目录
|
// 打开用户数据目录
|
||||||
async function openMergeData() {
|
async function openMergeData() {
|
||||||
await dialog.open({
|
await dialog.open({
|
||||||
defaultPath: appStore.dataPath.merge,
|
defaultPath: appStore.dataPath.user,
|
||||||
filters: [],
|
filters: [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -100,14 +99,7 @@ async function deleteData() {
|
|||||||
await dialog.message("用户数据已删除!");
|
await dialog.message("用户数据已删除!");
|
||||||
await achievementsStore.init();
|
await achievementsStore.init();
|
||||||
await fs.createDir("userData", { dir: BaseDirectory.AppLocalData });
|
await fs.createDir("userData", { dir: BaseDirectory.AppLocalData });
|
||||||
await fs.createDir("mergeData", { dir: BaseDirectory.AppLocalData });
|
|
||||||
await fs.createDir("tempData", { dir: BaseDirectory.AppLocalData });
|
await fs.createDir("tempData", { dir: BaseDirectory.AppLocalData });
|
||||||
TGAppDataList.MergeData.map(async item => {
|
|
||||||
await fs.writeFile(
|
|
||||||
`${appStore.dataPath.merge}\\${item.name}`,
|
|
||||||
JSON.stringify(item.data, null, 4)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 删除临时数据
|
// 删除临时数据
|
||||||
|
|||||||
@@ -1,203 +0,0 @@
|
|||||||
<template>
|
|
||||||
<h1>开发</h1>
|
|
||||||
<v-card class="common-card">
|
|
||||||
<v-list>
|
|
||||||
<v-list-item @click="devInit" prepend-icon="mdi-refresh">
|
|
||||||
<v-list-item-title>初始化开发</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
<v-list-item @click="parseAchievement" prepend-icon="mdi-export">
|
|
||||||
<v-list-item-title>解析成就数据</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
<v-list-item @click="mergeAchievement" prepend-icon="mdi-export">
|
|
||||||
<v-list-item-title>合并成就数据</v-list-item-title>
|
|
||||||
</v-list-item>
|
|
||||||
</v-list>
|
|
||||||
</v-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import useDevStore from "../store/modules/dev";
|
|
||||||
import useAppStore from "../store/modules/app";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { dialog, fs } from "@tauri-apps/api";
|
|
||||||
import { SnapHutaoData } from "../plugins/Snap.Hutao";
|
|
||||||
import {
|
|
||||||
Achievement as HutaoAchievement,
|
|
||||||
AchievementGoal as HutaoGoal,
|
|
||||||
} from "../plugins/Snap.Hutao/interface/achievement";
|
|
||||||
import { PaimonMoeData } from "../plugins/Paimon.moe";
|
|
||||||
import { AchievementSeries as PaimonSeries } from "../plugins/Paimon.moe/interface/achievement";
|
|
||||||
import {
|
|
||||||
Achievement as TGAchievement,
|
|
||||||
AchievementMap as TGAchievementMap,
|
|
||||||
AchievementSeries as TGSeries,
|
|
||||||
SeriesMap as TGSeriesMap,
|
|
||||||
} from "../interface/achievements";
|
|
||||||
import TGMap from "../utils/TGMap";
|
|
||||||
import { TGAppData } from "../data";
|
|
||||||
|
|
||||||
// Store
|
|
||||||
const appStore = useAppStore();
|
|
||||||
const devStore = useDevStore();
|
|
||||||
|
|
||||||
async function devInit() {
|
|
||||||
await devStore.init();
|
|
||||||
await dialog.message("初始化完成!");
|
|
||||||
// 跳转到首页
|
|
||||||
const router = useRouter();
|
|
||||||
await router.push({ path: "/", replace: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function parseAchievement() {
|
|
||||||
const appDataDir = appStore.devPath.app;
|
|
||||||
// 读取原始数据
|
|
||||||
const hutaoAchievementData: HutaoAchievement[] = SnapHutaoData.Achievement.data;
|
|
||||||
const hutaoGoalData: HutaoGoal[] = SnapHutaoData.AchievementGoal.data;
|
|
||||||
const paimonSeriesMap: TGMap<PaimonSeries> = new TGMap<PaimonSeries>(
|
|
||||||
PaimonMoeData.Achievement.data
|
|
||||||
);
|
|
||||||
// 新建目标数据
|
|
||||||
const achievementSeries: TGSeries[] = [];
|
|
||||||
const achievement: TGAchievement[] = [];
|
|
||||||
// 先解析 Hutao 的成就数据
|
|
||||||
hutaoGoalData.map(hutaoGoalItem => {
|
|
||||||
const achievementSeriesItem: TGSeries = {
|
|
||||||
id: hutaoGoalItem.Id,
|
|
||||||
order: hutaoGoalItem.Order,
|
|
||||||
name: hutaoGoalItem.Name,
|
|
||||||
version: "",
|
|
||||||
card: undefined,
|
|
||||||
icon: `/source/achievementSeries/${hutaoGoalItem.Id}.webp`,
|
|
||||||
};
|
|
||||||
achievementSeries.push(achievementSeriesItem);
|
|
||||||
});
|
|
||||||
hutaoAchievementData.map(hutaoAchievementItem => {
|
|
||||||
const achievementItem: TGAchievement = {
|
|
||||||
id: hutaoAchievementItem.Id,
|
|
||||||
series: hutaoAchievementItem.Goal,
|
|
||||||
order: hutaoAchievementItem.Order,
|
|
||||||
name: hutaoAchievementItem.Title,
|
|
||||||
description: hutaoAchievementItem.Description,
|
|
||||||
reward: hutaoAchievementItem.FinishReward.ID,
|
|
||||||
version: "",
|
|
||||||
progress: hutaoAchievementItem.Progress,
|
|
||||||
};
|
|
||||||
achievement.push(achievementItem);
|
|
||||||
});
|
|
||||||
// 再解析 Paimon.moe 的成就数据
|
|
||||||
paimonSeriesMap.forEach(paimonSeries => {
|
|
||||||
const seriesItem: TGSeries | undefined = achievementSeries.find(
|
|
||||||
achievementSeriesItem => achievementSeriesItem.name === paimonSeries.name
|
|
||||||
);
|
|
||||||
// 成就版本-暂存
|
|
||||||
let achievementVersion: string = "";
|
|
||||||
paimonSeries.achievements.map(paimonAchievementItem => {
|
|
||||||
if (Array.isArray(paimonAchievementItem)) {
|
|
||||||
paimonAchievementItem.map(paimonAchievement => {
|
|
||||||
// 查找成就中 id 相同的成就
|
|
||||||
const achievementItem: TGAchievement | undefined = achievement.find(
|
|
||||||
achievementItem => achievementItem.id === paimonAchievement.id
|
|
||||||
);
|
|
||||||
if (achievementItem) {
|
|
||||||
// 更新数据
|
|
||||||
achievementItem.version = paimonAchievement.ver;
|
|
||||||
if (seriesItem) {
|
|
||||||
if (achievementVersion === "") {
|
|
||||||
achievementVersion = paimonAchievement.ver;
|
|
||||||
} else {
|
|
||||||
// 比较 v1.1 和 v1.2 的大小
|
|
||||||
if (achievementVersion < paimonAchievement.ver) {
|
|
||||||
achievementVersion = paimonAchievement.ver;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 查找成就中 id 相同的成就
|
|
||||||
const achievementItem: TGAchievement | undefined = achievement.find(
|
|
||||||
achievementItem => achievementItem.id === paimonAchievementItem.id
|
|
||||||
);
|
|
||||||
if (achievementItem) {
|
|
||||||
// 更新数据
|
|
||||||
achievementItem.version = paimonAchievementItem.ver;
|
|
||||||
if (seriesItem) {
|
|
||||||
if (achievementVersion === "") {
|
|
||||||
achievementVersion = paimonAchievementItem.ver;
|
|
||||||
} else {
|
|
||||||
// 比较 v1.1 和 v1.2 的大小
|
|
||||||
if (achievementVersion < paimonAchievementItem.ver) {
|
|
||||||
achievementVersion = paimonAchievementItem.ver;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 更新成就系列版本
|
|
||||||
if (seriesItem && achievementVersion !== "") {
|
|
||||||
seriesItem.version = achievementVersion;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 输出数据
|
|
||||||
await fs.writeFile(
|
|
||||||
`${appDataDir}\\achievementSeries.json`,
|
|
||||||
JSON.stringify(achievementSeries, null, 4)
|
|
||||||
);
|
|
||||||
await fs.writeFile(`${appDataDir}\\achievements.json`, JSON.stringify(achievement, null, 4));
|
|
||||||
await dialog.message("文件已导出至 " + appDataDir);
|
|
||||||
}
|
|
||||||
async function mergeAchievement() {
|
|
||||||
const mergeDataDir = appStore.devPath.merge;
|
|
||||||
// 读取原始数据
|
|
||||||
const oriAchievement = TGAppData.AppData.achievements;
|
|
||||||
const oriSeries = TGAppData.AppData.achievementSeries;
|
|
||||||
// 读取合并数据
|
|
||||||
const transSeries: TGMap<TGSeriesMap> = new TGMap<TGSeriesMap>();
|
|
||||||
const transAchievement: TGMap<TGAchievementMap> = new TGMap<TGAchievementMap>();
|
|
||||||
// 先遍历成就系列生成成就系列数据
|
|
||||||
oriSeries.map(oriSeriesItem => {
|
|
||||||
transSeries.set(oriSeriesItem.id, {
|
|
||||||
id: oriSeriesItem.id,
|
|
||||||
order: oriSeriesItem.order,
|
|
||||||
name: oriSeriesItem.name,
|
|
||||||
card: oriSeriesItem.card,
|
|
||||||
icon: oriSeriesItem.icon,
|
|
||||||
achievements: [],
|
|
||||||
total_count: 0,
|
|
||||||
completed_count: 0,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// 遍历成就
|
|
||||||
oriAchievement.map(oriAchievementItem => {
|
|
||||||
// 生成成就数据
|
|
||||||
transAchievement.set(oriAchievementItem.id, {
|
|
||||||
id: oriAchievementItem.id,
|
|
||||||
series: oriAchievementItem.series,
|
|
||||||
order: oriAchievementItem.order,
|
|
||||||
name: oriAchievementItem.name,
|
|
||||||
description: oriAchievementItem.description,
|
|
||||||
reward: oriAchievementItem.reward,
|
|
||||||
completed: false,
|
|
||||||
});
|
|
||||||
// 默认成就系列是完备的,所以不需要判断成就系列是否存在
|
|
||||||
// 更新成就系列数据的 achievements 跟 total_count
|
|
||||||
const seriesItem = transSeries.get(oriAchievementItem.series);
|
|
||||||
seriesItem.achievements.push(oriAchievementItem.id);
|
|
||||||
seriesItem.total_count += 1;
|
|
||||||
transSeries.set(oriAchievementItem.series, seriesItem);
|
|
||||||
});
|
|
||||||
// 写入文件
|
|
||||||
await fs.writeTextFile(
|
|
||||||
`${mergeDataDir}\\achievementSeries.json`,
|
|
||||||
JSON.stringify(transSeries.getMap(), null, 4)
|
|
||||||
);
|
|
||||||
await fs.writeTextFile(
|
|
||||||
`${mergeDataDir}\\achievements.json`,
|
|
||||||
JSON.stringify(transAchievement.getMap(), null, 4)
|
|
||||||
);
|
|
||||||
await dialog.message("文件已导出至 " + mergeDataDir);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="css"></style>
|
|
||||||
@@ -22,13 +22,6 @@
|
|||||||
>查看</v-btn
|
>查看</v-btn
|
||||||
>
|
>
|
||||||
<v-card-subtitle>id:{{ item.post_id }}</v-card-subtitle>
|
<v-card-subtitle>id:{{ item.post_id }}</v-card-subtitle>
|
||||||
<v-btn
|
|
||||||
v-show="showLog"
|
|
||||||
@click="logPost(item.post_id)"
|
|
||||||
prepend-icon="mdi-arrow-right-circle"
|
|
||||||
class="ms-2 card-btn"
|
|
||||||
>原始数据</v-btn
|
|
||||||
>
|
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,16 +43,10 @@
|
|||||||
class="ms-2 card-btn"
|
class="ms-2 card-btn"
|
||||||
>查看</v-btn
|
>查看</v-btn
|
||||||
>
|
>
|
||||||
|
<v-card-subtitle>id:{{ item.post_id }}</v-card-subtitle>
|
||||||
<v-btn v-if="item.status === 1" color="ms-2 card-btn-0">进行中</v-btn>
|
<v-btn v-if="item.status === 1" color="ms-2 card-btn-0">进行中</v-btn>
|
||||||
<v-btn v-else-if="item.status === 2" color="ms-2 card-btn-2">已结束</v-btn>
|
<v-btn v-else-if="item.status === 2" color="ms-2 card-btn-2">已结束</v-btn>
|
||||||
<v-btn v-else color="ms-2 card-btn-1">评选中</v-btn>
|
<v-btn v-else color="ms-2 card-btn-1">评选中</v-btn>
|
||||||
<v-btn
|
|
||||||
v-show="showLog"
|
|
||||||
@click="logPost(item.post_id)"
|
|
||||||
prepend-icon="mdi-arrow-right-circle"
|
|
||||||
class="ms-2 card-btn"
|
|
||||||
>原始数据</v-btn
|
|
||||||
>
|
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -77,13 +64,6 @@
|
|||||||
>查看</v-btn
|
>查看</v-btn
|
||||||
>
|
>
|
||||||
<v-card-subtitle>id:{{ item.post_id }}</v-card-subtitle>
|
<v-card-subtitle>id:{{ item.post_id }}</v-card-subtitle>
|
||||||
<v-btn
|
|
||||||
v-show="showLog"
|
|
||||||
@click="logPost(item.post_id)"
|
|
||||||
prepend-icon="mdi-arrow-right-circle"
|
|
||||||
class="ms-2 card-btn"
|
|
||||||
>原始数据</v-btn
|
|
||||||
>
|
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,7 +73,6 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import useDevStore from "../store/modules/dev";
|
|
||||||
import useAppStore from "../store/modules/app";
|
import useAppStore from "../store/modules/app";
|
||||||
import {
|
import {
|
||||||
MysPostType,
|
MysPostType,
|
||||||
@@ -109,7 +88,6 @@ import { createTGWindow } from "../utils/TGWindow";
|
|||||||
import { parseMys } from "../utils/MysParse";
|
import { parseMys } from "../utils/MysParse";
|
||||||
|
|
||||||
// Store
|
// Store
|
||||||
const devStore = useDevStore();
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
|
||||||
// 渲染模式
|
// 渲染模式
|
||||||
@@ -131,7 +109,6 @@ const postData = ref({
|
|||||||
activity: [] as CardDataType[],
|
activity: [] as CardDataType[],
|
||||||
news: [] as CardDataType[],
|
news: [] as CardDataType[],
|
||||||
});
|
});
|
||||||
const showLog = ref(devStore.showDev);
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const noticeRaw: ResponseNewsList = await http
|
const noticeRaw: ResponseNewsList = await http
|
||||||
|
|||||||
@@ -5,18 +5,13 @@
|
|||||||
* @since Alpha
|
* @since Alpha
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { checkUIAFData, readUIAFData, mergeUIAFData } from "./utils/importData";
|
import { checkUIAFData, readUIAFData } from "./utils/importData";
|
||||||
import { getAchievements } from "./utils/exportData";
|
import { getUIAFInfo } from "./utils/exportData";
|
||||||
|
|
||||||
const UIAF_Oper = {
|
const UIAF_Oper = {
|
||||||
importOper: {
|
|
||||||
checkUIAFData,
|
checkUIAFData,
|
||||||
readUIAFData,
|
readUIAFData,
|
||||||
mergeUIAFData,
|
getUIAFInfo,
|
||||||
},
|
|
||||||
exportOper: {
|
|
||||||
getAchievements,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UIAF_Oper;
|
export default UIAF_Oper;
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
* @since Alpha
|
* @since Alpha
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Achievements, UIAF_Info, UIAF_Achievement } from "../interface/UIAF";
|
import { UIAF_Info } from "../interface/UIAF";
|
||||||
import { app, fs } from "@tauri-apps/api";
|
import { app } from "@tauri-apps/api";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 获取 UIAF_Info
|
* @description 获取 UIAF_Info
|
||||||
* @return Promise<UIAF_Info>
|
* @return Promise<UIAF_Info>
|
||||||
*/
|
*/
|
||||||
async function getUIAFInfo(): Promise<UIAF_Info> {
|
export async function getUIAFInfo(): Promise<UIAF_Info> {
|
||||||
return {
|
return {
|
||||||
export_app: "Tauri.Genshin",
|
export_app: "Tauri.Genshin",
|
||||||
export_timestamp: Math.floor(Date.now() / 1000),
|
export_timestamp: Math.floor(Date.now() / 1000),
|
||||||
@@ -20,20 +20,3 @@ async function getUIAFInfo(): Promise<UIAF_Info> {
|
|||||||
uiaf_version: "v1.1",
|
uiaf_version: "v1.1",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 获取 Achievements
|
|
||||||
* @param {string} userPath - 本地文件路径
|
|
||||||
* @return Promise<Achievements>
|
|
||||||
*/
|
|
||||||
export async function getAchievements(userPath: string): Promise<Achievements> {
|
|
||||||
// 读取本地文件
|
|
||||||
const achievementsRaw = await fs.readTextFile(userPath);
|
|
||||||
// 解析 JSON
|
|
||||||
const achievements: UIAF_Achievement[] = JSON.parse(achievementsRaw);
|
|
||||||
// 返回
|
|
||||||
return {
|
|
||||||
info: await getUIAFInfo(),
|
|
||||||
list: achievements,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* @since Alpha
|
* @since Alpha
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Achievements, UIAF_Achievement, UIAF_Info } from "../interface/UIAF";
|
import { UIAF_Info } from "../interface/UIAF";
|
||||||
import { fs } from "@tauri-apps/api";
|
import { fs } from "@tauri-apps/api";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,37 +39,3 @@ export async function readUIAFData(userPath: string): Promise<string | false> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 数据合并
|
|
||||||
* @since Alpha
|
|
||||||
* @param {UIAF_Achievement[]} localData - 本地数据
|
|
||||||
* @param {Achievements} remoteData - 远程数据
|
|
||||||
* @return {Promise<UIAF_Achievement[]>} 合并后的数据
|
|
||||||
*/
|
|
||||||
export async function mergeUIAFData(
|
|
||||||
localData: UIAF_Achievement[],
|
|
||||||
remoteData: Achievements
|
|
||||||
): Promise<UIAF_Achievement[]> {
|
|
||||||
// 遍历 remoteData.list
|
|
||||||
remoteData.list.map((remoteAchievement: UIAF_Achievement) => {
|
|
||||||
// 查找 id 相同的 localAchievement
|
|
||||||
const localAchievement = localData.find(achievement => achievement.id === remoteAchievement.id);
|
|
||||||
// 如果没找到,就直接添加
|
|
||||||
if (localAchievement === undefined) {
|
|
||||||
localData.push(remoteAchievement);
|
|
||||||
} else {
|
|
||||||
// 检测数据是否需要更新
|
|
||||||
if (localAchievement.timestamp < remoteAchievement.timestamp) {
|
|
||||||
// 更新数据
|
|
||||||
localAchievement.timestamp = remoteAchievement.timestamp;
|
|
||||||
localAchievement.current = remoteAchievement.current;
|
|
||||||
localAchievement.status = remoteAchievement.status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 按照 id 排序
|
|
||||||
localData.sort((a, b) => a.id - b.id);
|
|
||||||
// 返回合并后的数据
|
|
||||||
return localData;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import News from "../pages/News.vue";
|
|||||||
import Achievements from "../pages/Achievements.vue";
|
import Achievements from "../pages/Achievements.vue";
|
||||||
// 应用配置相关
|
// 应用配置相关
|
||||||
import Config from "../pages/Config.vue";
|
import Config from "../pages/Config.vue";
|
||||||
import Dev from "../pages/Dev.vue";
|
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@@ -27,11 +26,6 @@ const routes = [
|
|||||||
name: "咨讯",
|
name: "咨讯",
|
||||||
component: News,
|
component: News,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/dev",
|
|
||||||
name: "开发者工具",
|
|
||||||
component: Dev,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/config",
|
path: "/config",
|
||||||
name: "设置",
|
name: "设置",
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ const appDataDir = `${await path.appLocalDataDir()}appData`;
|
|||||||
const userDataDir = `${await path.appLocalDataDir()}userData`;
|
const userDataDir = `${await path.appLocalDataDir()}userData`;
|
||||||
// 用于各种临时数据的路径
|
// 用于各种临时数据的路径
|
||||||
const tempDataDir = `${await path.appLocalDataDir()}tempData`;
|
const tempDataDir = `${await path.appLocalDataDir()}tempData`;
|
||||||
// 用于开发者模式的路径
|
|
||||||
const devDataDir = `${await path.resolve("../")}\\src\\data`;
|
|
||||||
|
|
||||||
const useAppStore = defineStore({
|
const useAppStore = defineStore({
|
||||||
id: "app",
|
id: "app",
|
||||||
@@ -31,7 +29,6 @@ const useAppStore = defineStore({
|
|||||||
dataPath: {
|
dataPath: {
|
||||||
app: appDataDir,
|
app: appDataDir,
|
||||||
user: userDataDir,
|
user: userDataDir,
|
||||||
dev: devDataDir,
|
|
||||||
temp: tempDataDir,
|
temp: tempDataDir,
|
||||||
},
|
},
|
||||||
// 应用数据路径
|
// 应用数据路径
|
||||||
@@ -44,11 +41,6 @@ const useAppStore = defineStore({
|
|||||||
userPath: {
|
userPath: {
|
||||||
achievements: `${userDataDir}\\achievements.json`,
|
achievements: `${userDataDir}\\achievements.json`,
|
||||||
},
|
},
|
||||||
// 开发者模式
|
|
||||||
devPath: {
|
|
||||||
app: `${devDataDir}\\app`,
|
|
||||||
merge: `${devDataDir}\\merge`,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@@ -62,11 +54,6 @@ const useAppStore = defineStore({
|
|||||||
this.userPath = {
|
this.userPath = {
|
||||||
achievements: `${userDataDir}\\achievements.json`,
|
achievements: `${userDataDir}\\achievements.json`,
|
||||||
};
|
};
|
||||||
// 初始化开发者模式
|
|
||||||
this.devPath = {
|
|
||||||
app: `${devDataDir}\\app`,
|
|
||||||
merge: `${devDataDir}\\merge`,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
persist: true,
|
persist: true,
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
import { defineStore } from "pinia";
|
|
||||||
|
|
||||||
const useDevStore = defineStore({
|
|
||||||
id: "dev",
|
|
||||||
state() {
|
|
||||||
return {
|
|
||||||
showDev: false,
|
|
||||||
magicCount: 0,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
init() {
|
|
||||||
this.showDev = false;
|
|
||||||
this.magicCount = 0;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
persist: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default useDevStore;
|
|
||||||
@@ -61,7 +61,24 @@ export async function WriteTGData(storeName: string, data: any[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 更新数据库中的单条数据
|
* @description 更新数据库中的单条数据-根据主键
|
||||||
|
* @since Alpha
|
||||||
|
* @param {string} storeName 表名
|
||||||
|
* @param {any} data 数据
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function UpdateTGDataByKey(storeName: string, data: any): Promise<void> {
|
||||||
|
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
|
||||||
|
request.onsuccess = () => {
|
||||||
|
const db = request.result;
|
||||||
|
const transaction = db.transaction(storeName, "readwrite");
|
||||||
|
const store = transaction.objectStore(storeName);
|
||||||
|
store.put(data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 更新数据库中的单条数据-根据索引
|
||||||
* @since Alpha
|
* @since Alpha
|
||||||
* @param {string} storeName 表名
|
* @param {string} storeName 表名
|
||||||
* @param {string} indexName 索引名
|
* @param {string} indexName 索引名
|
||||||
@@ -69,7 +86,7 @@ export async function WriteTGData(storeName: string, data: any[]) {
|
|||||||
* @param {any} data 数据
|
* @param {any} data 数据
|
||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export async function UpdateTGData(
|
export async function UpdateTGDataByIndex(
|
||||||
storeName: string,
|
storeName: string,
|
||||||
indexName: string,
|
indexName: string,
|
||||||
key: any,
|
key: any,
|
||||||
@@ -95,14 +112,50 @@ export async function UpdateTGData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 从数据库中读取某些数据
|
* @description 从数据库中读取某些数据-按照主键
|
||||||
|
* @since Alpha
|
||||||
|
* @param {string} storeName 表名
|
||||||
|
* @param {any[]} keys 主键值
|
||||||
|
* @return {Promise<any[]>}
|
||||||
|
*/
|
||||||
|
export async function ReadTGDataByKey(storeName: string, keys: any[]): Promise<any[]> {
|
||||||
|
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request.onsuccess = () => {
|
||||||
|
const db = request.result;
|
||||||
|
const transaction = db.transaction(storeName, "readonly");
|
||||||
|
const store = transaction.objectStore(storeName);
|
||||||
|
const requestData = store.getAll();
|
||||||
|
requestData.onsuccess = () => {
|
||||||
|
const result = requestData.result;
|
||||||
|
const data = result.filter(item => {
|
||||||
|
return keys.includes(item.id);
|
||||||
|
});
|
||||||
|
resolve(data);
|
||||||
|
};
|
||||||
|
requestData.onerror = () => {
|
||||||
|
reject(requestData.error);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
request.onerror = () => {
|
||||||
|
reject(request.error);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 从数据库中读取某些数据-按照索引
|
||||||
* @since Alpha
|
* @since Alpha
|
||||||
* @param {string} storeName 表名
|
* @param {string} storeName 表名
|
||||||
* @param {string} indexName 索引名
|
* @param {string} indexName 索引名
|
||||||
* @param {any} key 索引值
|
* @param {any} key 索引值
|
||||||
* @return {Promise<any[]>}
|
* @return {Promise<any[]>}
|
||||||
*/
|
*/
|
||||||
export async function ReadTGData(storeName: string, indexName: string, key: any): Promise<any[]> {
|
export async function ReadTGDataByIndex(
|
||||||
|
storeName: string,
|
||||||
|
indexName: string,
|
||||||
|
key: any
|
||||||
|
): Promise<any[]> {
|
||||||
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
|
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request.onsuccess = () => {
|
request.onsuccess = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user