mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-18 10:18:14 +08:00
♻️ 全面整理重构
This commit is contained in:
@@ -37,9 +37,8 @@
|
||||
v-model:cur="selectedSeries"
|
||||
:series="item"
|
||||
:uid="uidCur"
|
||||
@click="selectSeries(item)"
|
||||
@click="selectedSeries = item"
|
||||
/>
|
||||
<div style="height: 10px" />
|
||||
</template>
|
||||
</v-virtual-scroll>
|
||||
<TuaAchiList
|
||||
@@ -53,54 +52,45 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import showDialog from "@comp/func/dialog.js";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TuaAchiList from "@comp/userAchi/tua-achi-list.vue";
|
||||
import TuaSeries from "@comp/userAchi/tua-series.vue";
|
||||
import TSUserAchi from "@Sqlite/modules/userAchi.js";
|
||||
import { path } from "@tauri-apps/api";
|
||||
import { listen, UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { open, save } from "@tauri-apps/plugin-dialog";
|
||||
import { writeTextFile } from "@tauri-apps/plugin-fs";
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
import { computed, onMounted, onUnmounted, ref, shallowRef, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showLoading from "../../components/func/loading.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TuaAchiList from "../../components/userAchi/tua-achi-list.vue";
|
||||
import TuaSeries from "../../components/userAchi/tua-series.vue";
|
||||
import { AppAchievementSeriesData } from "../../data/index.js";
|
||||
import TSUserAchi from "../../plugins/Sqlite/modules/userAchi.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { AppAchievementSeriesData } from "@/data/index.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import {
|
||||
getUiafHeader,
|
||||
readUiafData,
|
||||
verifyUiafData,
|
||||
verifyUiafDataClipboard,
|
||||
} from "../../utils/UIAF.js";
|
||||
} from "@/utils/UIAF.js";
|
||||
|
||||
const seriesList = AppAchievementSeriesData.sort((a, b) => a.order - b.order).map((s) => s.id);
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
let achiListener: UnlistenFn | null = null;
|
||||
|
||||
const search = ref<string>("");
|
||||
const isSearch = ref<boolean>(false);
|
||||
const hideFin = ref<boolean>(false);
|
||||
|
||||
const uidList = ref<number[]>([]);
|
||||
const uidCur = ref<number>(0);
|
||||
const overview = ref<TGApp.Sqlite.Achievement.Overview>({ fin: 0, total: 1 });
|
||||
const seriesList = AppAchievementSeriesData.sort((a, b) => a.order - b.order).map((s) => s.id);
|
||||
const selectedSeries = ref<number>(-1);
|
||||
|
||||
const overview = shallowRef<TGApp.Sqlite.Achievement.Overview>({ fin: 0, total: 1 });
|
||||
const title = computed<string>(() => {
|
||||
const percentage = ((overview.value.fin * 100) / overview.value.total).toFixed(2);
|
||||
return `${overview.value.fin}/${overview.value.total} ${percentage}%`;
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
let achiListener: UnlistenFn | null = null;
|
||||
|
||||
async function switchHideFin() {
|
||||
const text = hideFin.value ? "显示已完成" : "隐藏已完成";
|
||||
hideFin.value = !hideFin.value;
|
||||
showSnackbar.success(`已${text}`);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
showLoading.start("正在加载成就数据...");
|
||||
await TGLogger.Info("[Achievements][onMounted] 打开成就页面");
|
||||
@@ -112,29 +102,21 @@ onMounted(async () => {
|
||||
if (route.query.app && typeof route.query.app === "string") {
|
||||
await handleImportOuter(route.query.app);
|
||||
}
|
||||
achiListener = await listen<number>("updateAchi", async () => await refreshOverview());
|
||||
achiListener = await listen<void>("updateAchi", async () => await refreshOverview());
|
||||
});
|
||||
|
||||
watch(
|
||||
() => uidCur.value,
|
||||
async () => await refreshOverview(),
|
||||
);
|
||||
watch(() => uidCur.value, refreshOverview);
|
||||
|
||||
onUnmounted(async () => {
|
||||
if (achiListener !== null) {
|
||||
achiListener();
|
||||
achiListener = null;
|
||||
}
|
||||
});
|
||||
function switchHideFin(): void {
|
||||
const text = hideFin.value ? "显示已完成" : "隐藏已完成";
|
||||
hideFin.value = !hideFin.value;
|
||||
showSnackbar.success(`已${text}`);
|
||||
}
|
||||
|
||||
async function refreshOverview(): Promise<void> {
|
||||
overview.value = await TSUserAchi.getOverview(uidCur.value);
|
||||
}
|
||||
|
||||
function selectSeries(series: number): void {
|
||||
selectedSeries.value = series;
|
||||
}
|
||||
|
||||
async function importJson(): Promise<void> {
|
||||
await TGLogger.Info("[Achievements][importJson] 导入 UIAF 数据");
|
||||
const selectedFile = await open({
|
||||
@@ -266,6 +248,13 @@ async function deleteUid(): Promise<void> {
|
||||
if (uidList.value.length === 0) uidList.value = [0];
|
||||
uidCur.value = uidList.value[0];
|
||||
}
|
||||
|
||||
onUnmounted(async () => {
|
||||
if (achiListener !== null) {
|
||||
achiListener();
|
||||
achiListener = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.achi-search {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<v-select
|
||||
class="anno-select"
|
||||
:items="annoServerList"
|
||||
v-model="curRegion"
|
||||
v-model="server"
|
||||
item-title="text"
|
||||
item-value="value"
|
||||
label="服务器"
|
||||
@@ -20,7 +20,7 @@
|
||||
<v-select
|
||||
class="anno-select"
|
||||
:items="annoLangList"
|
||||
v-model="curLang"
|
||||
v-model="lang"
|
||||
item-title="text"
|
||||
item-value="value"
|
||||
label="语言"
|
||||
@@ -30,10 +30,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template #append>
|
||||
<v-btn class="anno-switch-btn" @click="switchNews">
|
||||
<template #prepend>
|
||||
<v-icon>mdi-bullhorn</v-icon>
|
||||
</template>
|
||||
<v-btn class="anno-switch-btn" @click="switchNews" prepend-icon="mdi-bullhorn">
|
||||
切换米游社咨讯
|
||||
</v-btn>
|
||||
</template>
|
||||
@@ -45,8 +42,8 @@
|
||||
v-for="item in annoCards[value]"
|
||||
:key="item.id"
|
||||
:model-value="item"
|
||||
:region="curRegion"
|
||||
:lang="curLang"
|
||||
:region="server"
|
||||
:lang="lang"
|
||||
/>
|
||||
</div>
|
||||
</v-window-item>
|
||||
@@ -54,21 +51,24 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, onMounted, ref, watch } from "vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TaCard from "@comp/pageAnno/ta-card.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref, shallowRef, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import showLoading from "../../components/func/loading.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TaCard from "../../components/pageAnno/ta-card.vue";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import Hk4eApi, { AnnoLang, AnnoServer } from "../../web/request/hk4eReq.js";
|
||||
import { getAnnoCard } from "../../web/utils/getAnnoCard.js";
|
||||
import { decodeRegExp } from "../../web/utils/tools.js";
|
||||
import { useAppStore } from "@/store/modules/app.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import Hk4eApi, { type AnnoLang, AnnoServer } from "@/web/request/hk4eReq.js";
|
||||
import { getAnnoCard } from "@/web/utils/getAnnoCard.js";
|
||||
import { decodeRegExp } from "@/web/utils/tools.js";
|
||||
|
||||
type AnnoSelect = { text: string; value: string };
|
||||
type AnnoKey = keyof typeof AnnoType;
|
||||
type AnnoCard = { [key in AnnoKey]: TGApp.App.Announcement.ListCard[] };
|
||||
|
||||
const annoServerList: AnnoSelect[] = [
|
||||
const annoServerList: Array<AnnoSelect> = [
|
||||
{ text: "国服-官方服", value: AnnoServer.CN_ISLAND },
|
||||
{ text: "国服-渠道服", value: AnnoServer.CN_TREE },
|
||||
{ text: "国际服-亚服", value: AnnoServer.OS_ASIA },
|
||||
@@ -76,44 +76,28 @@ const annoServerList: AnnoSelect[] = [
|
||||
{ text: "国际服-美服", value: AnnoServer.OS_USA },
|
||||
{ text: "国际服-港澳台服", value: AnnoServer.OS_CHT },
|
||||
];
|
||||
const annoLangList: AnnoSelect[] = [
|
||||
const annoLangList: Array<AnnoSelect> = [
|
||||
{ text: "简体中文", value: "zh-cn" },
|
||||
{ text: "繁体中文", value: "zh-tw" },
|
||||
{ text: "English", value: "en" },
|
||||
{ text: "日本語", value: "ja" },
|
||||
];
|
||||
|
||||
// 类型定义
|
||||
enum AnnoType {
|
||||
activity = "活动公告",
|
||||
game = "游戏公告",
|
||||
}
|
||||
|
||||
type AnnoKey = keyof typeof AnnoType;
|
||||
type AnnoCard = {
|
||||
[key in AnnoKey]: TGApp.App.Announcement.ListCard[];
|
||||
};
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
// 路由
|
||||
const { server, lang } = storeToRefs(useAppStore());
|
||||
const router = useRouter();
|
||||
const curRegion = ref<AnnoServer>(appStore.server);
|
||||
const curLang = ref<AnnoLang>(appStore.lang);
|
||||
|
||||
// 数据
|
||||
const tabValues: Readonly<Array<AnnoKey>> = ["activity", "game"];
|
||||
const tab = ref<AnnoKey>("activity");
|
||||
const tabValues = ref<Array<AnnoKey>>(["activity", "game"]);
|
||||
const annoCards = ref<AnnoCard>({
|
||||
activity: [],
|
||||
game: [],
|
||||
});
|
||||
const annoCards = shallowRef<AnnoCard>({ activity: [], game: [] });
|
||||
|
||||
watch(
|
||||
() => curRegion.value,
|
||||
() => server.value,
|
||||
async () => {
|
||||
appStore.server = curRegion.value;
|
||||
const name = getRegionName(curRegion.value);
|
||||
const name = getRegionName(server.value);
|
||||
await TGLogger.Info(`[Announcements][watch][curRegionName] 切换服务器:${name}`);
|
||||
await loadData();
|
||||
showSnackbar.success(`服务器切换为:${name}`);
|
||||
@@ -121,10 +105,9 @@ watch(
|
||||
);
|
||||
|
||||
watch(
|
||||
() => curLang.value,
|
||||
() => lang.value,
|
||||
async () => {
|
||||
appStore.lang = curLang.value;
|
||||
const name = getLangName(curLang.value);
|
||||
const name = getLangName(lang.value);
|
||||
await TGLogger.Info(`[Announcements][watch][curLangName] 切换语言:${name}`);
|
||||
await loadData();
|
||||
showSnackbar.success(`语言切换为:${name}`);
|
||||
@@ -133,22 +116,20 @@ watch(
|
||||
|
||||
onMounted(async () => {
|
||||
await TGLogger.Info("[Announcements][onMounted] 打开公告页面");
|
||||
curRegion.value = appStore.server;
|
||||
curLang.value = appStore.lang;
|
||||
await loadData();
|
||||
});
|
||||
|
||||
async function loadData(): Promise<void> {
|
||||
showLoading.start(
|
||||
"正在获取公告数据",
|
||||
`服务器:${getRegionName(curRegion.value)},语言:${getLangName(curLang.value)}`,
|
||||
`服务器:${getRegionName(server.value)},语言:${getLangName(lang.value)}`,
|
||||
);
|
||||
const annoData = await Hk4eApi.anno.list(curRegion.value, curLang.value);
|
||||
const annoData = await Hk4eApi.anno.list(server.value, lang.value);
|
||||
const listCards = getAnnoCard(annoData);
|
||||
await Promise.all(
|
||||
listCards.map(async (item) => {
|
||||
if (item.typeLabel === AnnoType.game) return;
|
||||
const detail = await Hk4eApi.anno.content(item.id, curRegion.value, "zh-cn");
|
||||
const detail = await Hk4eApi.anno.content(item.id, server.value, "zh-cn");
|
||||
const timeStr = getAnnoTime(detail.content);
|
||||
if (timeStr !== false) item.timeStr = timeStr;
|
||||
}),
|
||||
@@ -157,8 +138,7 @@ async function loadData(): Promise<void> {
|
||||
activity: listCards.filter((item) => item.typeLabel === AnnoType.activity),
|
||||
game: listCards.filter((item) => item.typeLabel === AnnoType.game),
|
||||
};
|
||||
showLoading.update("正在渲染公告数据");
|
||||
await nextTick(() => showLoading.end());
|
||||
showLoading.end();
|
||||
}
|
||||
|
||||
function getRegionName(value: AnnoServer): string {
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
</template>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="appStore.devMode"
|
||||
:label="appStore.devMode ? '开启' : '关闭'"
|
||||
v-model="devMode"
|
||||
:label="devMode ? '开启' : '关闭'"
|
||||
:inset="true"
|
||||
color="#FAC51E"
|
||||
@click="submitDevMode"
|
||||
@@ -51,8 +51,8 @@
|
||||
</template>
|
||||
<template #append>
|
||||
<v-switch
|
||||
v-model="needResize"
|
||||
:label="needResize ? '开启' : '关闭'"
|
||||
v-model="isNeedResize"
|
||||
:label="isNeedResize ? '开启' : '关闭'"
|
||||
:inset="true"
|
||||
color="#FAC51E"
|
||||
@click="submitResize"
|
||||
@@ -60,9 +60,7 @@
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item title="分享设置">
|
||||
<template #subtitle>
|
||||
默认保存到剪贴板,超过{{ appStore.shareDefaultFile }}MB时保存到文件
|
||||
</template>
|
||||
<template #subtitle>默认保存到剪贴板,超过{{ shareDefaultFile }}MB时保存到文件</template>
|
||||
<template #prepend>
|
||||
<div class="config-icon">
|
||||
<v-icon>mdi-share-variant</v-icon>
|
||||
@@ -81,8 +79,7 @@
|
||||
<v-list-item-title @click="confirmUpdateDevice()">刷新设备信息</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
<!-- @ts-expect-error-next-line Deprecated symbol used -->
|
||||
{{ appStore.deviceInfo.device_name }}({{ appStore.deviceInfo.product }}) -
|
||||
{{ appStore.deviceInfo.device_fp }}
|
||||
{{ deviceInfo.device_name }}({{ deviceInfo.product }}) - {{ deviceInfo.device_fp }}
|
||||
</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-icon @click="confirmUpdateDevice(true)">mdi-bug</v-icon>
|
||||
@@ -121,38 +118,40 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import showDialog from "@comp/func/dialog.js";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TcAppBadge from "@comp/pageConfig/tc-appBadge.vue";
|
||||
import TcDataDir from "@comp/pageConfig/tc-dataDir.vue";
|
||||
import TcGameBadge from "@comp/pageConfig/tc-gameBadge.vue";
|
||||
import TcInfo from "@comp/pageConfig/tc-info.vue";
|
||||
import TcUserBadge from "@comp/pageConfig/tc-userBadge.vue";
|
||||
import TGSqlite from "@Sqlite/index.js";
|
||||
import { core } from "@tauri-apps/api";
|
||||
import { open } from "@tauri-apps/plugin-dialog";
|
||||
import { remove } from "@tauri-apps/plugin-fs";
|
||||
import { platform } from "@tauri-apps/plugin-os";
|
||||
import { exit } from "@tauri-apps/plugin-process";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref } from "vue";
|
||||
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showLoading from "../../components/func/loading.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TcAppBadge from "../../components/pageConfig/tc-appBadge.vue";
|
||||
import TcDataDir from "../../components/pageConfig/tc-dataDir.vue";
|
||||
import TcGameBadge from "../../components/pageConfig/tc-gameBadge.vue";
|
||||
import TcInfo from "../../components/pageConfig/tc-info.vue";
|
||||
import TcUserBadge from "../../components/pageConfig/tc-userBadge.vue";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import { useHomeStore } from "../../store/modules/home.js";
|
||||
import { backUpUserData, restoreUserData } from "../../utils/dataBS.js";
|
||||
import { getBuildTime } from "../../utils/TGBuild.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { bytesToSize, getCacheDir, getDeviceInfo, getRandomString } from "../../utils/toolFunc.js";
|
||||
import OtherApi from "../../web/request/otherReq.js";
|
||||
import { useAppStore } from "@/store/modules/app.js";
|
||||
import { useHomeStore } from "@/store/modules/home.js";
|
||||
import { backUpUserData, restoreUserData } from "@/utils/dataBS.js";
|
||||
import { getBuildTime } from "@/utils/TGBuild.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import { bytesToSize, getCacheDir, getDeviceInfo, getRandomString } from "@/utils/toolFunc.js";
|
||||
import OtherApi from "@/web/request/otherReq.js";
|
||||
|
||||
// Store
|
||||
const { needResize, devMode, deviceInfo, shareDefaultFile, userDir, buildTime } =
|
||||
storeToRefs(useAppStore());
|
||||
const appStore = useAppStore();
|
||||
const homeStore = useHomeStore();
|
||||
|
||||
// @ts-expect-error-next-line
|
||||
const isDevEnv = ref<boolean>(import.meta.env.MODE === "development");
|
||||
const showReset = ref<boolean>(false);
|
||||
const needResize = ref<boolean>(appStore.needResize !== "false");
|
||||
|
||||
const isNeedResize = ref<boolean>(needResize.value !== "false");
|
||||
const cacheSize = ref<number>(0);
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -176,7 +175,7 @@ async function confirmBackup(): Promise<void> {
|
||||
showSnackbar.cancel("已取消备份");
|
||||
return;
|
||||
}
|
||||
let saveDir = appStore.userDir;
|
||||
let saveDir = userDir.value;
|
||||
if (!bcCheck) {
|
||||
const dir: string | null = await open({
|
||||
directory: true,
|
||||
@@ -189,9 +188,7 @@ async function confirmBackup(): Promise<void> {
|
||||
}
|
||||
await TGLogger.Info(`[Config][confirmBackup] 选择备份路径 ${dir.toString()}`);
|
||||
saveDir = dir;
|
||||
} else {
|
||||
await TGLogger.Info(`[Config][confirmBackup] 备份到默认路径 ${saveDir}`);
|
||||
}
|
||||
} else await TGLogger.Info(`[Config][confirmBackup] 备份到默认路径 ${saveDir}`);
|
||||
showLoading.start("正在备份数据...");
|
||||
await backUpUserData(saveDir);
|
||||
showLoading.end();
|
||||
@@ -206,7 +203,7 @@ async function confirmRestore(): Promise<void> {
|
||||
showSnackbar.cancel("已取消恢复");
|
||||
return;
|
||||
}
|
||||
let saveDir = appStore.userDir;
|
||||
let saveDir = userDir.value;
|
||||
if (!rsCheck) {
|
||||
const dir: string | null = await open({
|
||||
directory: true,
|
||||
@@ -219,9 +216,7 @@ async function confirmRestore(): Promise<void> {
|
||||
}
|
||||
await TGLogger.Info(`[Config][confirmRestore] 选择恢复路径 ${dir.toString()}`);
|
||||
saveDir = dir;
|
||||
} else {
|
||||
await TGLogger.Info(`[Config][confirmRestore] 恢复到默认路径 ${saveDir}`);
|
||||
}
|
||||
} else await TGLogger.Info(`[Config][confirmRestore] 恢复到默认路径 ${saveDir}`);
|
||||
showLoading.start("正在恢复数据...");
|
||||
await restoreUserData(saveDir);
|
||||
showLoading.end();
|
||||
@@ -238,7 +233,7 @@ async function confirmUpdate(title?: string): Promise<void> {
|
||||
}
|
||||
showLoading.start("正在更新数据库...");
|
||||
await TGSqlite.update();
|
||||
appStore.buildTime = getBuildTime();
|
||||
buildTime.value = getBuildTime();
|
||||
showLoading.end();
|
||||
showSnackbar.success("数据库已更新!");
|
||||
await TGLogger.Info("[Config][confirmUpdate] 数据库更新完成");
|
||||
@@ -250,7 +245,7 @@ async function confirmShare(): Promise<void> {
|
||||
const input = await showDialog.input(
|
||||
"请输入分享文件大小阈值(MB)",
|
||||
"阈值:",
|
||||
appStore.shareDefaultFile.toString(),
|
||||
shareDefaultFile.value.toString(),
|
||||
);
|
||||
if (input === undefined) {
|
||||
showSnackbar.cancel("已取消修改分享设置");
|
||||
@@ -264,7 +259,7 @@ async function confirmShare(): Promise<void> {
|
||||
showSnackbar.error("阈值必须为数字!");
|
||||
return;
|
||||
}
|
||||
if (Number(input) === appStore.shareDefaultFile) {
|
||||
if (Number(input) === shareDefaultFile.value) {
|
||||
showSnackbar.cancel("未修改分享设置");
|
||||
return;
|
||||
}
|
||||
@@ -280,7 +275,7 @@ async function confirmShare(): Promise<void> {
|
||||
showSnackbar.cancel("已取消修改分享设置");
|
||||
return;
|
||||
}
|
||||
appStore.shareDefaultFile = Number(input);
|
||||
shareDefaultFile.value = Number(input);
|
||||
showSnackbar.success(`成功修改分享设置!新阈值为${input}MB`);
|
||||
}
|
||||
|
||||
@@ -290,22 +285,20 @@ async function confirmUpdateDevice(force?: boolean): Promise<void> {
|
||||
await TGLogger.Info("[Config][confirmUpdateDevice][force] 开始强制更新设备信息");
|
||||
const forceCheck = await showDialog.check(
|
||||
"确认强制更新设备信息吗?",
|
||||
`DeviceFp:${appStore.deviceInfo.device_fp}`,
|
||||
`DeviceFp:${deviceInfo.value.device_fp}`,
|
||||
);
|
||||
if (!forceCheck) {
|
||||
showSnackbar.cancel("已取消强制更新设备信息");
|
||||
await TGLogger.Info("[Config][confirmUpdateDevice][force] 取消强制更新设备信息");
|
||||
return;
|
||||
}
|
||||
appStore.deviceInfo = await OtherApi.fp();
|
||||
if (appStore.deviceInfo.device_fp === "0000000000000") {
|
||||
appStore.deviceInfo.device_fp = getRandomString(13, "hex");
|
||||
showSnackbar.warn(`设备信息获取失败!已使用随机值${appStore.deviceInfo.device_fp}代替`);
|
||||
deviceInfo.value = await OtherApi.fp();
|
||||
if (deviceInfo.value.device_fp === "0000000000000") {
|
||||
deviceInfo.value.device_fp = getRandomString(13, "hex");
|
||||
showSnackbar.warn(`设备信息获取失败!已使用随机值${deviceInfo.value.device_fp}代替`);
|
||||
await TGLogger.Warn("[Config][confirmUpdateDevice][force] 设备信息获取失败!已使用随机值代替");
|
||||
} else {
|
||||
showSnackbar.success(`设备信息已更新! DeviceFp: ${appStore.deviceInfo.device_fp}`);
|
||||
}
|
||||
await TGSqlite.saveAppData("deviceInfo", JSON.stringify(appStore.deviceInfo));
|
||||
} else showSnackbar.success(`设备信息已更新! DeviceFp: ${deviceInfo.value.device_fp}`);
|
||||
await TGSqlite.saveAppData("deviceInfo", JSON.stringify(deviceInfo.value));
|
||||
await TGLogger.Info("[Config][confirmUpdateDevice][force] 设备信息更新完成");
|
||||
return;
|
||||
}
|
||||
@@ -319,17 +312,15 @@ async function confirmUpdateDevice(force?: boolean): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log(appStore.deviceInfo);
|
||||
appStore.deviceInfo = await OtherApi.fp(appStore.deviceInfo);
|
||||
console.log(appStore.deviceInfo);
|
||||
if (appStore.deviceInfo.device_fp === "0000000000000") {
|
||||
appStore.deviceInfo.device_fp = getRandomString(13, "hex");
|
||||
showSnackbar.warn(`设备信息获取失败!已使用随机值${appStore.deviceInfo.device_fp}代替`);
|
||||
deviceInfo.value = await OtherApi.fp(deviceInfo.value);
|
||||
if (deviceInfo.value.device_fp === "0000000000000") {
|
||||
deviceInfo.value.device_fp = getRandomString(13, "hex");
|
||||
showSnackbar.warn(`设备信息获取失败!已使用随机值${deviceInfo.value.device_fp}代替`);
|
||||
await TGLogger.Warn("[Config][confirmUpdateDevice] 设备信息获取失败!已使用随机值代替");
|
||||
return;
|
||||
}
|
||||
showSnackbar.success(`设备信息已更新! DeviceFp: ${appStore.deviceInfo.device_fp}`);
|
||||
await TGSqlite.saveAppData("deviceInfo", JSON.stringify(appStore.deviceInfo));
|
||||
showSnackbar.success(`设备信息已更新! DeviceFp: ${deviceInfo.value.device_fp}`);
|
||||
await TGSqlite.saveAppData("deviceInfo", JSON.stringify(deviceInfo.value));
|
||||
await TGLogger.Info("[Config][confirmUpdateDevice] 设备信息更新完成");
|
||||
}
|
||||
|
||||
@@ -433,8 +424,8 @@ function submitDevMode(): void {
|
||||
|
||||
// 开启窗口回正
|
||||
function submitResize(): void {
|
||||
appStore.needResize = (!needResize.value).toString();
|
||||
if (needResize.value) {
|
||||
appStore.needResize = (!isNeedResize.value).toString();
|
||||
if (isNeedResize.value) {
|
||||
showSnackbar.success("已关闭窗口回正!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="home-container">
|
||||
<div class="home-top">
|
||||
<div class="home-tools" v-if="appStore.isLogin">
|
||||
<div class="home-tools" v-if="isLogin">
|
||||
<v-select
|
||||
v-model="curGid"
|
||||
class="home-tool-select"
|
||||
@@ -32,18 +32,19 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import TGameNav from "@comp/app/t-gameNav.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import PhCompCalendar from "@comp/pageHome/ph-comp-calendar.vue";
|
||||
import PhCompPool from "@comp/pageHome/ph-comp-pool.vue";
|
||||
import PhCompPosition from "@comp/pageHome/ph-comp-position.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { type Component, computed, onMounted, ref, shallowRef, watch } from "vue";
|
||||
|
||||
import TGameNav from "../../components/app/t-gamenav.vue";
|
||||
import showLoading from "../../components/func/loading.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import PhCompCalendar from "../../components/pageHome/ph-comp-calendar.vue";
|
||||
import PhCompPool from "../../components/pageHome/ph-comp-pool.vue";
|
||||
import PhCompPosition from "../../components/pageHome/ph-comp-position.vue";
|
||||
import { useAppStore } from "../../store/modules/app.js";
|
||||
import { ShowItemEnum, useHomeStore } from "../../store/modules/home.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import TGConstant from "../../web/constant/TGConstant.js";
|
||||
import { useAppStore } from "@/store/modules/app.js";
|
||||
import { ShowItemEnum, useHomeStore } from "@/store/modules/home.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import TGConstant from "@/web/constant/TGConstant.js";
|
||||
|
||||
type SFComp = Component & {
|
||||
__file?: string;
|
||||
@@ -52,7 +53,7 @@ type SFComp = Component & {
|
||||
__scopeId?: string;
|
||||
};
|
||||
|
||||
const appStore = useAppStore();
|
||||
const { devMode, isLogin } = storeToRefs(useAppStore());
|
||||
const homeStore = useHomeStore();
|
||||
|
||||
const showItemsAll: Array<ShowItemEnum> = [
|
||||
@@ -60,12 +61,12 @@ const showItemsAll: Array<ShowItemEnum> = [
|
||||
ShowItemEnum.pool,
|
||||
ShowItemEnum.position,
|
||||
];
|
||||
const showItems = computed<ShowItemEnum[]>({
|
||||
const showItems = computed<Array<ShowItemEnum>>({
|
||||
get: () => homeStore.getShowItems(),
|
||||
set: (v: ShowItemEnum[]) => homeStore.setShowItems(v),
|
||||
set: (v: Array<ShowItemEnum>) => homeStore.setShowItems(v),
|
||||
});
|
||||
const loadItems = shallowRef<ShowItemEnum[]>([]);
|
||||
const components = shallowRef<SFComp[]>([]);
|
||||
const loadItems = shallowRef<Array<ShowItemEnum>>([]);
|
||||
const components = shallowRef<Array<SFComp>>([]);
|
||||
|
||||
const gameSelectList = TGConstant.BBS.CHANNELS;
|
||||
const curGid = ref<string>(gameSelectList[0].gid);
|
||||
@@ -74,7 +75,7 @@ onMounted(async () => {
|
||||
showLoading.start("正在加载首页...");
|
||||
// @ts-expect-error-next-line The import.meta meta-property is not allowed in files which will build into CommonJS output.
|
||||
const isProdEnv = import.meta.env.MODE === "production";
|
||||
if (isProdEnv && appStore.devMode) appStore.devMode = false;
|
||||
if (isProdEnv && devMode.value) devMode.value = false;
|
||||
await loadComp();
|
||||
});
|
||||
|
||||
@@ -88,7 +89,7 @@ watch(
|
||||
|
||||
async function loadComp(): Promise<void> {
|
||||
showLoading.start("正在加载首页...");
|
||||
const temp: SFComp[] = [];
|
||||
const temp: Array<SFComp> = [];
|
||||
for (const item of showItems.value) {
|
||||
switch (item) {
|
||||
case "限时祈愿":
|
||||
|
||||
@@ -94,47 +94,40 @@
|
||||
<ToCollectPost @submit="load" :post="selectedPost" v-model="showOverlay" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TPostCard from "@comp/app/t-postcard.vue";
|
||||
import showDialog from "@comp/func/dialog.js";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import ToCollectPost from "@comp/pageCollect/to-collectPost.vue";
|
||||
import TSUserCollection from "@Sqlite/modules/userCollect.js";
|
||||
import { event } from "@tauri-apps/api";
|
||||
import { UnlistenFn } from "@tauri-apps/api/event";
|
||||
import type { UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
import { computed, onMounted, onUnmounted, ref, shallowRef, watch } from "vue";
|
||||
|
||||
import TPostCard from "../../components/app/t-postcard.vue";
|
||||
import showDialog from "../../components/func/dialog.js";
|
||||
import showLoading from "../../components/func/loading.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import ToCollectPost from "../../components/pageCollect/to-collectPost.vue";
|
||||
import TSUserCollection from "../../plugins/Sqlite/modules/userCollect.js";
|
||||
import { useUserStore } from "../../store/modules/user.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import BBSApi from "../../web/request/bbsReq.js";
|
||||
|
||||
const userStore = storeToRefs(useUserStore());
|
||||
|
||||
const collections = ref<TGApp.Sqlite.UserCollection.UFCollection[]>([]);
|
||||
const selected = ref<TGApp.Sqlite.UserCollection.UFPost[]>([]);
|
||||
const curSelect = ref<string>("未分类");
|
||||
const page = ref(1);
|
||||
const length = computed(() => Math.ceil(selected.value.length / 12));
|
||||
const view = computed(() => {
|
||||
if (length.value === 1) return 0;
|
||||
return length.value > 5 ? 5 : length.value;
|
||||
});
|
||||
const curPosts = computed<TGApp.Plugins.Mys.Post.FullData[]>(() => {
|
||||
return selected.value
|
||||
.slice((page.value - 1) * 12, page.value * 12)
|
||||
.map((i) => JSON.parse(i.content));
|
||||
});
|
||||
|
||||
const selectedMode = ref<boolean>(false);
|
||||
const selectedPost = ref<Array<string>>([]);
|
||||
const showOverlay = ref(false);
|
||||
const sortId = ref<boolean>(false);
|
||||
import { useUserStore } from "@/store/modules/user.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import BBSApi from "@/web/request/bbsReq.js";
|
||||
|
||||
const { cookie, briefInfo } = storeToRefs(useUserStore());
|
||||
let collectListener: UnlistenFn | null = null;
|
||||
|
||||
const curSelect = ref<string>("未分类");
|
||||
const page = ref<number>(1);
|
||||
const selectedMode = ref<boolean>(false);
|
||||
const showOverlay = ref<boolean>(false);
|
||||
const sortId = ref<boolean>(false);
|
||||
const selectedPost = shallowRef<Array<string>>([]);
|
||||
const collections = shallowRef<Array<TGApp.Sqlite.UserCollection.UFCollection>>([]);
|
||||
const selected = shallowRef<Array<TGApp.Sqlite.UserCollection.UFPost>>([]);
|
||||
const length = computed<number>(() => Math.ceil(selected.value.length / 12));
|
||||
const view = computed<number>(() => (length.value === 1 ? 1 : length.value > 5 ? 5 : length.value));
|
||||
const curPosts = computed<Array<TGApp.Plugins.Mys.Post.FullData>>(() =>
|
||||
selected.value.slice((page.value - 1) * 12, page.value * 12).map((i) => JSON.parse(i.content)),
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
collectListener = await event.listen("refreshCollect", async () => await load());
|
||||
collectListener = await event.listen<void>("refreshCollect", load);
|
||||
await load();
|
||||
});
|
||||
onUnmounted(() => {
|
||||
@@ -144,27 +137,22 @@ onUnmounted(() => {
|
||||
}
|
||||
});
|
||||
|
||||
function handleSelected(v: string) {
|
||||
if (selectedPost.value.includes(v)) {
|
||||
selectedPost.value = selectedPost.value.filter((i) => i !== v);
|
||||
} else {
|
||||
selectedPost.value.push(v);
|
||||
function handleSelected(v: string): void {
|
||||
if (!selectedPost.value.includes(v)) {
|
||||
selectedPost.value = [...selectedPost.value, v];
|
||||
return;
|
||||
}
|
||||
selectedPost.value = selectedPost.value.filter((i) => i !== v);
|
||||
}
|
||||
|
||||
function sortPost(value: boolean) {
|
||||
function sortPost(value: boolean): void {
|
||||
let ori = sortId.value;
|
||||
sortId.value = value;
|
||||
selected.value = selected.value.sort((a, b) => {
|
||||
if (sortId.value) {
|
||||
return Number(b.id) - Number(a.id);
|
||||
} else {
|
||||
return Number(b.updated) - Number(a.updated);
|
||||
}
|
||||
});
|
||||
if (ori !== sortId.value) {
|
||||
showSnackbar.success(`已${sortId.value ? "按帖子ID排序" : "按更新时间排序"}`);
|
||||
}
|
||||
selected.value = selected.value.sort((a, b) =>
|
||||
sortId.value ? Number(b.id) - Number(a.id) : Number(b.updated) - Number(a.updated),
|
||||
);
|
||||
if (ori === sortId.value) return;
|
||||
showSnackbar.success(`已${sortId.value ? "按帖子ID排序" : "按更新时间排序"}`);
|
||||
}
|
||||
|
||||
async function load(): Promise<void> {
|
||||
@@ -187,7 +175,7 @@ async function load(): Promise<void> {
|
||||
showLoading.end();
|
||||
}
|
||||
|
||||
function toSelect() {
|
||||
function toSelect(): void {
|
||||
if (selectedMode.value) {
|
||||
selectedMode.value = false;
|
||||
if (selectedPost.value.length === 0) return;
|
||||
@@ -332,9 +320,7 @@ async function freshPost(select: string | null): Promise<void> {
|
||||
if (select === "未分类") {
|
||||
curSelect.value = "未分类";
|
||||
selected.value = await TSUserCollection.getUnCollectPostList();
|
||||
} else {
|
||||
selected.value = await TSUserCollection.getCollectPostList(select);
|
||||
}
|
||||
} else selected.value = await TSUserCollection.getCollectPostList(select);
|
||||
page.value = 1;
|
||||
showLoading.end();
|
||||
showSnackbar.success(`切换合集 ${select},共 ${selected.value.length} 条帖子`);
|
||||
@@ -359,33 +345,26 @@ async function freshOther(): Promise<void> {
|
||||
}
|
||||
|
||||
async function freshUser(uid?: string): Promise<void> {
|
||||
if (!userStore.cookie.value) {
|
||||
if (!cookie.value) {
|
||||
showSnackbar.warn("请先登录");
|
||||
return;
|
||||
}
|
||||
const uidReal = uid || userStore.briefInfo.value.uid;
|
||||
const uidReal = uid || briefInfo.value.uid;
|
||||
showLoading.start("获取用户收藏...", `UID: ${uidReal}`);
|
||||
let res = await BBSApi.lovePost(userStore.cookie.value, uidReal);
|
||||
let res = await BBSApi.lovePost(cookie.value, uidReal);
|
||||
while (true) {
|
||||
if ("retcode" in res) {
|
||||
showLoading.end();
|
||||
if (res.retcode === 1001) {
|
||||
showSnackbar.warn("用户收藏已设为私密,无法获取");
|
||||
} else {
|
||||
showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
}
|
||||
if (res.retcode === 1001) showSnackbar.warn("用户收藏已设为私密,无法获取");
|
||||
else showSnackbar.error(`[${res.retcode}] ${res.message}`);
|
||||
break;
|
||||
}
|
||||
let posts = res.list;
|
||||
showLoading.update("获取用户收藏...", `合并收藏帖子 [offset]${res.next_offset}...`);
|
||||
await mergePosts(posts, uid || userStore.briefInfo.value.uid);
|
||||
await mergePosts(posts, uid || briefInfo.value.uid);
|
||||
if (res.is_last) break;
|
||||
showLoading.update("获取用户收藏...", `[offset]${res.next_offset} [is_last]${res.is_last}`);
|
||||
res = await BBSApi.lovePost(
|
||||
userStore.cookie.value,
|
||||
uid || userStore.briefInfo.value.uid,
|
||||
res.next_offset,
|
||||
);
|
||||
res = await BBSApi.lovePost(cookie.value, uid || briefInfo.value.uid, res.next_offset);
|
||||
}
|
||||
showLoading.end();
|
||||
showSnackbar.success("获取用户收藏成功");
|
||||
@@ -394,16 +373,14 @@ async function freshUser(uid?: string): Promise<void> {
|
||||
|
||||
// 合并收藏帖子
|
||||
async function mergePosts(
|
||||
posts: TGApp.Plugins.Mys.Post.FullData[],
|
||||
posts: Array<TGApp.Plugins.Mys.Post.FullData>,
|
||||
collect: string,
|
||||
): Promise<void> {
|
||||
const title = `用户收藏-${collect}`;
|
||||
for (const post of posts) {
|
||||
showLoading.start("获取用户收藏...", `[POST]${post.post.subject} [collection]${title}`);
|
||||
const res = await TSUserCollection.addCollect(post.post.post_id, post, title, true);
|
||||
if (!res) {
|
||||
await TGLogger.Error(`[PostCollect] mergePosts [${post.post.post_id}]`);
|
||||
}
|
||||
if (!res) await TGLogger.Error(`[PostCollect] mergePosts [${post.post.post_id}]`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -67,71 +67,64 @@
|
||||
<VpOverlaySearch :gid="curGid.toString()" v-model="showSearch" :keyword="search" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import TGameNav from "@comp/app/t-gameNav.vue";
|
||||
import TPostCard from "@comp/app/t-postcard.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import VpOverlaySearch from "@comp/viewPost/vp-overlay-search.vue";
|
||||
import Mys from "@Mys/index.js";
|
||||
import { onMounted, ref, shallowRef, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
import TGameNav from "../../components/app/t-gamenav.vue";
|
||||
import TPostCard from "../../components/app/t-postcard.vue";
|
||||
import showLoading from "../../components/func/loading.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import VpOverlaySearch from "../../components/viewPost/vp-overlay-search.vue";
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import { getGameName } from "../../web/utils/tools.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import { createPost } from "@/utils/TGWindow.js";
|
||||
import { getGameName } from "@/web/utils/tools.js";
|
||||
|
||||
type SortSelect = {
|
||||
text: string;
|
||||
value: number;
|
||||
};
|
||||
type SortSelectGame = {
|
||||
gid: number;
|
||||
forum: SortSelect[];
|
||||
text: string;
|
||||
};
|
||||
type SortSelect = { text: string; value: number };
|
||||
type SortSelectGame = { gid: number; forum: Array<SortSelect>; text: string };
|
||||
|
||||
const sortOrderList: SortSelect[] = [
|
||||
const sortOrderList: Array<SortSelect> = [
|
||||
{ text: "最新回复", value: 1 },
|
||||
{ text: "最新发布", value: 2 },
|
||||
{ text: "热门", value: 3 },
|
||||
];
|
||||
const forumYsList: SortSelect[] = [
|
||||
const forumYsList: Array<SortSelect> = [
|
||||
{ text: "酒馆", value: 26 },
|
||||
{ text: "攻略", value: 43 },
|
||||
{ text: "同人图", value: 29 },
|
||||
{ text: "COS", value: 49 },
|
||||
{ text: "硬核", value: 50 },
|
||||
];
|
||||
const forumSrList: SortSelect[] = [
|
||||
const forumSrList: Array<SortSelect> = [
|
||||
{ text: "候车室", value: 52 },
|
||||
{ text: "攻略", value: 61 },
|
||||
{ text: "同人图", value: 56 },
|
||||
{ text: "COS", value: 62 },
|
||||
];
|
||||
const forumBh3List: SortSelect[] = [
|
||||
const forumBh3List: Array<SortSelect> = [
|
||||
{ text: "甲板", value: 1 },
|
||||
{ text: "攻略", value: 14 },
|
||||
{ text: "同人图", value: 4 },
|
||||
{ text: "同人文", value: 41 },
|
||||
];
|
||||
const forumBh2List: SortSelect[] = [
|
||||
const forumBh2List: Array<SortSelect> = [
|
||||
{ text: "学园", value: 30 },
|
||||
{ text: "攻略", value: 51 },
|
||||
{ text: "同人图", value: 40 },
|
||||
];
|
||||
const forumWdList: SortSelect[] = [
|
||||
const forumWdList: Array<SortSelect> = [
|
||||
{ text: "律所", value: 37 },
|
||||
{ text: "攻略", value: 60 },
|
||||
{ text: "同人文", value: 42 },
|
||||
{ text: "同人图", value: 38 },
|
||||
];
|
||||
const forumZzzList: SortSelect[] = [
|
||||
const forumZzzList: Array<SortSelect> = [
|
||||
{ text: "咖啡馆", value: 57 },
|
||||
{ text: "攻略", value: 64 },
|
||||
{ text: "同人图", value: 59 },
|
||||
{ text: "COS", value: 65 },
|
||||
];
|
||||
const forumDbyList: SortSelect[] = [
|
||||
const forumDbyList: Array<SortSelect> = [
|
||||
{ text: "校园", value: 54 },
|
||||
{ text: "ACG", value: 35 },
|
||||
{ text: "生活", value: 34 },
|
||||
@@ -141,7 +134,7 @@ const forumDbyList: SortSelect[] = [
|
||||
{ text: "科技", value: 55 },
|
||||
{ text: "公告", value: 36 },
|
||||
];
|
||||
const sortGameList: SortSelectGame[] = [
|
||||
const sortGameList: Readonly<Array<SortSelectGame>> = [
|
||||
{ gid: 2, forum: forumYsList, text: "原神" },
|
||||
{ gid: 6, forum: forumSrList, text: "崩坏:星穹铁道" },
|
||||
{ gid: 8, forum: forumZzzList, text: "绝区零" },
|
||||
@@ -150,47 +143,17 @@ const sortGameList: SortSelectGame[] = [
|
||||
{ gid: 4, forum: forumWdList, text: "未定事件簿" },
|
||||
{ gid: 5, forum: forumDbyList, text: "大别野" },
|
||||
];
|
||||
|
||||
// 路由
|
||||
const gid = useRoute().params.gid;
|
||||
const forum = useRoute().params.forum;
|
||||
|
||||
function getGameForums(gid: number): SortSelect[] {
|
||||
const game = sortGameList.find((item) => item.gid === gid);
|
||||
if (game) return game.forum;
|
||||
return [];
|
||||
}
|
||||
|
||||
function getGameLabel(gid: number): string {
|
||||
const game = sortGameList.find((item) => item.gid === gid);
|
||||
if (game) return game.text;
|
||||
return "";
|
||||
}
|
||||
|
||||
function getForumLabel(gid: number, forum: number): string {
|
||||
const forums = getGameForums(gid);
|
||||
const forumItem = forums.find((item) => item.value === forum);
|
||||
return forumItem ? forumItem.text : "";
|
||||
}
|
||||
|
||||
function getSortLabel(value: number): string {
|
||||
const order = sortOrderList.find((item) => item.value === value);
|
||||
return order ? order.text : "";
|
||||
}
|
||||
|
||||
// 渲染参数
|
||||
const { gid, forum } = useRoute().params;
|
||||
const curGid = ref<number>(2);
|
||||
const curSortType = ref<number>(1);
|
||||
const curForum = ref<number>(26);
|
||||
const curForumLabel = ref<string>("");
|
||||
|
||||
// 渲染数据
|
||||
const posts = ref<TGApp.Plugins.Mys.Post.FullData[]>([]);
|
||||
const lastId = ref<string>("");
|
||||
const isLast = ref<boolean>(false);
|
||||
const search = ref<string>("");
|
||||
const showSearch = ref<boolean>(false);
|
||||
const firstLoad = ref<boolean>(false);
|
||||
const posts = shallowRef<Array<TGApp.Plugins.Mys.Post.FullData>>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
if (gid && typeof gid === "string") curGid.value = Number(gid);
|
||||
@@ -204,7 +167,6 @@ onMounted(async () => {
|
||||
await freshPostData();
|
||||
curForumLabel.value = forumLabel;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => curGid.value,
|
||||
() => {
|
||||
@@ -236,6 +198,29 @@ watch(
|
||||
},
|
||||
);
|
||||
|
||||
function getGameForums(gid: number): SortSelect[] {
|
||||
const game = sortGameList.find((item) => item.gid === gid);
|
||||
if (game) return game.forum;
|
||||
return [];
|
||||
}
|
||||
|
||||
function getGameLabel(gid: number): string {
|
||||
const game = sortGameList.find((item) => item.gid === gid);
|
||||
if (game) return game.text;
|
||||
return "";
|
||||
}
|
||||
|
||||
function getForumLabel(gid: number, forum: number): string {
|
||||
const forums = getGameForums(gid);
|
||||
const forumItem = forums.find((item) => item.value === forum);
|
||||
return forumItem ? forumItem.text : "";
|
||||
}
|
||||
|
||||
function getSortLabel(value: number): string {
|
||||
const order = sortOrderList.find((item) => item.value === value);
|
||||
return order ? order.text : "";
|
||||
}
|
||||
|
||||
async function freshPostData(): Promise<void> {
|
||||
const gameLabel = getGameLabel(curGid.value);
|
||||
const forumLabel = getForumLabel(curGid.value, curForum.value);
|
||||
@@ -266,7 +251,6 @@ async function loadMore(): Promise<void> {
|
||||
showLoading.end();
|
||||
}
|
||||
|
||||
// 查询帖子
|
||||
function searchPost(): void {
|
||||
if (search.value === "") {
|
||||
showSnackbar.warn("请输入搜索内容");
|
||||
|
||||
@@ -25,16 +25,14 @@
|
||||
/>
|
||||
</template>
|
||||
<template #append>
|
||||
<v-btn class="post-news-btn" @click="firstLoad(tab, true)">
|
||||
<v-icon>mdi-refresh</v-icon>
|
||||
</v-btn>
|
||||
<v-btn class="post-news-btn" @click="showList = true">
|
||||
<v-icon>mdi-view-list</v-icon>
|
||||
</v-btn>
|
||||
<v-btn class="post-news-btn" @click="switchAnno" v-if="gid === '2'">
|
||||
<template #prepend>
|
||||
<v-icon>mdi-bullhorn</v-icon>
|
||||
</template>
|
||||
<v-btn class="post-news-btn" @click="firstLoad(tab, true)" icon="mdi-refresh" />
|
||||
<v-btn class="post-news-btn" @click="showList = true" icon="mdi-view-list" />
|
||||
<v-btn
|
||||
class="post-news-btn"
|
||||
@click="switchAnno"
|
||||
v-if="gid === '2'"
|
||||
prepend-icon="mdi-bullhorn"
|
||||
>
|
||||
切换游戏内公告
|
||||
</v-btn>
|
||||
</template>
|
||||
@@ -56,51 +54,44 @@
|
||||
<ToChannel v-model="showList" :gid="gid" />
|
||||
<VpOverlaySearch :gid="gid" v-model="showSearch" :keyword="search" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, onMounted, ref } from "vue";
|
||||
import TPostCard from "@comp/app/t-postcard.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import ToChannel from "@comp/pageNews/to-channel.vue";
|
||||
import VpOverlaySearch from "@comp/viewPost/vp-overlay-search.vue";
|
||||
import Mys from "@Mys/index.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, ref, shallowRef, triggerRef } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
|
||||
import TPostCard from "../../components/app/t-postcard.vue";
|
||||
import showLoading from "../../components/func/loading.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import ToChannel from "../../components/pageNews/to-channel.vue";
|
||||
import VpOverlaySearch from "../../components/viewPost/vp-overlay-search.vue";
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
import { NewsType, NewsTypeEnum, useAppStore } from "../../store/modules/app.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import { getGameName } from "../../web/utils/tools.js";
|
||||
import { type NewsType, NewsTypeEnum, useAppStore } from "@/store/modules/app.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import { createPost } from "@/utils/TGWindow.js";
|
||||
import { getGameName } from "@/web/utils/tools.js";
|
||||
|
||||
type PostData = { [key in NewsType]: TGApp.Plugins.Mys.Post.FullData[] };
|
||||
type RawData = {
|
||||
[key in NewsType]: { isLast: boolean; name: string; lastId: number };
|
||||
};
|
||||
type PostData = { [key in NewsType]: Array<TGApp.Plugins.Mys.Post.FullData> };
|
||||
type RawData = { [key in NewsType]: { isLast: boolean; name: string; lastId: number } };
|
||||
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
const gid = <string>useRoute().params.gid;
|
||||
const { recentNewsType } = storeToRefs(useAppStore());
|
||||
const tabValues: Readonly<Array<NewsType>> = ["notice", "activity", "news"];
|
||||
const { gid } = <{ gid: string }>useRoute().params;
|
||||
const gameName = getGameName(Number(gid));
|
||||
const loading = ref<boolean>(false);
|
||||
const tabValues: Readonly<Array<NewsType>> = ["notice", "activity", "news"];
|
||||
const showList = ref<boolean>(false);
|
||||
const showSearch = ref<boolean>(false);
|
||||
const tab = computed<NewsType>({
|
||||
get: () => {
|
||||
if (!(appStore.recentNewsType satisfies NewsType)) return "notice";
|
||||
return appStore.recentNewsType;
|
||||
},
|
||||
set: (v) => (appStore.recentNewsType = v),
|
||||
});
|
||||
|
||||
// 渲染数据
|
||||
const search = ref<string>("");
|
||||
const postData = ref<PostData>({ notice: [], activity: [], news: [] });
|
||||
const rawData = ref<RawData>({
|
||||
const postData = shallowRef<PostData>({ notice: [], activity: [], news: [] });
|
||||
const rawData = shallowRef<RawData>({
|
||||
notice: { isLast: false, name: "公告", lastId: 0 },
|
||||
activity: { isLast: false, name: "活动", lastId: 0 },
|
||||
news: { isLast: false, name: "咨讯", lastId: 0 },
|
||||
});
|
||||
const tab = computed<NewsType>({
|
||||
get: () => ((recentNewsType.value satisfies NewsType) ? recentNewsType.value : "notice"),
|
||||
set: (v) => (recentNewsType.value = v),
|
||||
});
|
||||
|
||||
onMounted(async () => await firstLoad(tab.value));
|
||||
|
||||
@@ -116,8 +107,9 @@ async function firstLoad(key: NewsType, refresh: boolean = false): Promise<void>
|
||||
rawData.value[key].isLast = getData.is_last;
|
||||
rawData.value[key].lastId = getData.list.length;
|
||||
postData.value[key] = getData.list;
|
||||
showLoading.update(`正在渲染${gameName}${rawData.value[key].name}数据...`);
|
||||
await nextTick(() => showLoading.end());
|
||||
triggerRef(postData);
|
||||
triggerRef(rawData);
|
||||
showLoading.end();
|
||||
await TGLogger.Info(`[News][${gid}][firstLoad] 获取${rawData.value[key].name}数据成功`);
|
||||
}
|
||||
|
||||
@@ -144,13 +136,15 @@ async function loadMore(key: NewsType): Promise<void> {
|
||||
rawData.value[key].lastId = rawData.value[key].lastId + getData.list.length;
|
||||
rawData.value[key].isLast = getData.is_last;
|
||||
postData.value[key] = postData.value[key].concat(getData.list);
|
||||
triggerRef(postData);
|
||||
triggerRef(rawData);
|
||||
if (rawData.value[key].isLast) {
|
||||
showLoading.end();
|
||||
showSnackbar.warn("已经是最后一页了");
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
await nextTick(() => showLoading.end());
|
||||
showLoading.end();
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
@@ -168,7 +162,6 @@ async function searchPost(): Promise<void> {
|
||||
showSearch.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.news-tab {
|
||||
margin-bottom: 10px;
|
||||
@@ -178,6 +171,7 @@ async function searchPost(): Promise<void> {
|
||||
|
||||
.post-news-btn {
|
||||
height: 40px;
|
||||
border-radius: 3px;
|
||||
margin-left: 15px;
|
||||
background: var(--btn-bg-1);
|
||||
color: var(--btn-text-1);
|
||||
|
||||
@@ -42,10 +42,7 @@
|
||||
@click:append="searchPost"
|
||||
@keyup.enter="searchPost"
|
||||
/>
|
||||
<v-btn :rounded="true" class="post-topic-btn" @click="firstLoad()">
|
||||
<v-icon>mdi-refresh</v-icon>
|
||||
<span>刷新</span>
|
||||
</v-btn>
|
||||
<v-btn class="post-topic-btn" @click="firstLoad()" prepend-icon="mdi-refresh">刷新</v-btn>
|
||||
</div>
|
||||
</v-app-bar>
|
||||
<div class="post-topic-grid">
|
||||
@@ -54,39 +51,37 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="load-more">
|
||||
<v-btn class="post-topic-btn" :rounded="true" @click="freshPostData()">
|
||||
<v-btn class="post-topic-btn" @click="freshPostData()">
|
||||
已加载:{{ posts.length }},加载更多
|
||||
</v-btn>
|
||||
</div>
|
||||
<VpOverlaySearch :gid="curGid.toString()" v-model="showSearch" :keyword="search" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref, toRaw, watch } from "vue";
|
||||
import TGameNav from "@comp/app/t-gameNav.vue";
|
||||
import TPostCard from "@comp/app/t-postcard.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import VpOverlaySearch from "@comp/viewPost/vp-overlay-search.vue";
|
||||
import Mys from "@Mys/index.js";
|
||||
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
import TGameNav from "../../components/app/t-gamenav.vue";
|
||||
import TPostCard from "../../components/app/t-postcard.vue";
|
||||
import showLoading from "../../components/func/loading.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import VpOverlaySearch from "../../components/viewPost/vp-overlay-search.vue";
|
||||
import Mys from "../../plugins/Mys/index.js";
|
||||
import { createPost } from "../../utils/TGWindow.js";
|
||||
import { createPost } from "@/utils/TGWindow.js";
|
||||
|
||||
const gid = <string>useRoute().params.gid;
|
||||
const topic = <string>useRoute().params.topic;
|
||||
type SortSelect = { text: string; value: number };
|
||||
|
||||
const { gid, topic } = <{ gid: string; topic: string }>useRoute().params;
|
||||
const showSearch = ref<boolean>(false);
|
||||
|
||||
const curGid = ref<number>(Number(gid));
|
||||
const curSortType = ref<0 | 1 | 2>(0);
|
||||
const search = ref<string>("");
|
||||
const topicInfo = ref<TGApp.Plugins.Mys.Topic.InfoData>();
|
||||
const posts = ref<TGApp.Plugins.Mys.Post.FullData[]>([]);
|
||||
const lastPostId = ref<string>();
|
||||
const isLastPage = ref<boolean>(false);
|
||||
const curGame = ref<TGApp.Plugins.Mys.Topic.GameInfo>();
|
||||
|
||||
type SortSelect = { text: string; value: number };
|
||||
const sortList = computed<SortSelect[]>(() => {
|
||||
const topicInfo = shallowRef<TGApp.Plugins.Mys.Topic.InfoData>();
|
||||
const posts = shallowRef<Array<TGApp.Plugins.Mys.Post.FullData>>([]);
|
||||
const curGame = shallowRef<TGApp.Plugins.Mys.Topic.GameInfo>();
|
||||
const sortList = computed<Array<SortSelect>>(() => {
|
||||
if (!topicInfo.value) return [];
|
||||
if (!topicInfo.value.good_post_exist) {
|
||||
return [
|
||||
@@ -111,11 +106,12 @@ onMounted(async () => {
|
||||
}
|
||||
topicInfo.value = info;
|
||||
if (curGame.value === undefined) {
|
||||
curGame.value = toRaw(info.game_info_list.find((i) => i.id === curGid.value));
|
||||
curGame.value = info.game_info_list.find((i) => i.id === curGid.value);
|
||||
}
|
||||
if (curGame.value === undefined) curGame.value = info.game_info_list[0];
|
||||
await firstLoad();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => curGame.value,
|
||||
async () => {
|
||||
|
||||
Reference in New Issue
Block a user