diff --git a/src/components/pageNews/to-channel.vue b/src/components/pageNews/to-channel.vue index 33d91923..a61ee73c 100644 --- a/src/components/pageNews/to-channel.vue +++ b/src/components/pageNews/to-channel.vue @@ -25,19 +25,21 @@ import { storeToRefs } from "pinia"; import { onMounted, shallowRef } from "vue"; import { type NewsType, useAppStore } from "@/store/modules/app.js"; -import apiHubReq from "@/web/request/apiHubReq.js"; +import useBBSStore from "@/store/modules/bbs.js"; type ChannelItem = { icon: string; title: string; gid: number }; type ToChannelProps = { gid?: string; curType?: string }; +const bbsStore = useBBSStore(); const { recentNewsType } = storeToRefs(useAppStore()); +const { gameList } = storeToRefs(bbsStore); const channelList = shallowRef>(); const props = defineProps(); const visible = defineModel({ default: false }); onMounted(async () => { - const allGames = await apiHubReq.game(); - channelList.value = allGames.map((i) => ({ icon: i.app_icon, title: i.name, gid: i.id })); + if (gameList.value.length === 0) await bbsStore.refreshGameList(); + channelList.value = gameList.value.map((i) => ({ icon: i.app_icon, title: i.name, gid: i.id })); }); async function toChannel(item: ChannelItem): Promise { diff --git a/src/components/viewPost/vp-overlay-search.vue b/src/components/viewPost/vp-overlay-search.vue index aeda9d45..537f00e6 100644 --- a/src/components/viewPost/vp-overlay-search.vue +++ b/src/components/viewPost/vp-overlay-search.vue @@ -3,7 +3,7 @@
查找:{{ search }}
- 分区:{{ gameName }} + 分区:{{ label }} 加载更多({{ results.length }}) @@ -24,27 +24,33 @@ import TOverlay from "@comp/app/t-overlay.vue"; import TPostCard from "@comp/app/t-postcard.vue"; import showSnackbar from "@comp/func/snackbar.js"; +import { storeToRefs } from "pinia"; import { computed, onMounted, ref, shallowRef, watch } from "vue"; -import TGBbs from "@/utils/TGBbs.js"; +import useBBSStore from "@/store/modules/bbs.js"; import postReq from "@/web/request/postReq.js"; type ToPostSearchProps = { gid: string; keyword?: string }; +const { gameList } = storeToRefs(useBBSStore()); + const props = defineProps(); const visible = defineModel(); + const search = ref(); const lastId = ref(""); -const game = ref("2"); +const gameId = ref("2"); const isLast = ref(false); const load = ref(false); const results = shallowRef>([]); -const gameName = computed( - () => TGBbs.channels.find((v) => v.gid.toString() === game.value)?.title || "未知分区", -); +const label = computed(() => { + const gameFind = gameList.value.find((v) => v.id.toString() === gameId.value); + if (gameFind === undefined) return "未知分区"; + return gameFind.name; +}); onMounted(async () => { - game.value = props.gid; + gameId.value = props.gid; if (props.keyword && props.keyword !== "") search.value = props.keyword; if (visible.value) await searchPosts(); }); @@ -79,8 +85,8 @@ watch( watch( () => props.gid, async () => { - if (game.value !== props.gid) { - game.value = props.gid; + if (gameId.value !== props.gid) { + gameId.value = props.gid; results.value = []; lastId.value = ""; isLast.value = false; @@ -106,7 +112,7 @@ async function searchPosts(): Promise { load.value = false; return; } - const res = await postReq.search(game.value, search.value, lastId.value); + const res = await postReq.search(gameId.value, search.value, lastId.value); if (lastId.value === "") results.value = res.posts; else results.value = results.value.concat(res.posts); lastId.value = res.last_id; diff --git a/src/pages/common/PageHome.vue b/src/pages/common/PageHome.vue index c2863e55..6cc8fee3 100644 --- a/src/pages/common/PageHome.vue +++ b/src/pages/common/PageHome.vue @@ -5,7 +5,7 @@ = ["素材日历", "限时祈愿", "近期活动"]; const curGid = ref(2); -const gameList = shallowRef>(); +const games = shallowRef>(); const loadItems = shallowRef>([]); const components = shallowRef>([]); const showItems = computed>({ @@ -100,13 +102,13 @@ const showItems = computed>({ }); onMounted(async () => { + await bbsStore.refreshGameList(); // @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 && devMode.value) devMode.value = false; if (isLogin.value) { await showLoading.start("正在加载首页小部件"); - const allGames = await apiHubReq.game(); - gameList.value = allGames.map((i) => ({ icon: i.app_icon, title: i.name, gid: i.id })); + games.value = gameList.value.map((i) => ({ icon: i.app_icon, title: i.name, gid: i.id })); } await loadComp(); }); diff --git a/src/pages/common/PostForum.vue b/src/pages/common/PostForum.vue index 08eb47bd..8cd1b717 100644 --- a/src/pages/common/PostForum.vue +++ b/src/pages/common/PostForum.vue @@ -132,9 +132,11 @@ import showLoading from "@comp/func/loading.js"; import showSnackbar from "@comp/func/snackbar.js"; import VpOverlaySearch from "@comp/viewPost/vp-overlay-search.vue"; import VpOverlayUser from "@comp/viewPost/vp-overlay-user.vue"; -import { computed, onMounted, ref, shallowRef, watch } from "vue"; +import { storeToRefs } from "pinia"; +import { computed, nextTick, onMounted, ref, shallowRef, watch } from "vue"; import { useRoute, useRouter } from "vue-router"; +import useBBSStore from "@/store/modules/bbs.js"; import TGLogger from "@/utils/TGLogger.js"; import { createPost } from "@/utils/TGWindow.js"; import ApiHubReq from "@/web/request/apiHubReq.js"; @@ -162,6 +164,7 @@ const showSearch = ref(false); const curUid = ref(""); const showUser = ref(false); +const { gameList } = storeToRefs(useBBSStore()); const selectedForum = shallowRef(); const sortGameList = shallowRef>([]); const postRaw = shallowRef({ isLast: false, lastId: "", total: 0 }); @@ -176,6 +179,7 @@ const curForums = computed>(() => { onMounted(async () => { await showLoading.start("正在加载帖子数据"); await loadForums(); + await nextTick(); let { gid, forum } = route.query; if (!gid) gid = route.params.gid; if (!forum) forum = route.params.forum; @@ -219,11 +223,10 @@ watch( // 初始化 async function loadForums(): Promise { - const allGames = await ApiHubReq.game(); const allForums = await ApiHubReq.forum(); - const gameList: Array = []; + const list: Array = []; for (const gameForum of allForums) { - const gameFind = allGames.find((i) => i.id === gameForum.game_id); + const gameFind = gameList.value.find((i) => i.id === gameForum.game_id); if (!gameFind) continue; const gameItem: SortSelectGame = { gid: gameForum.game_id, @@ -233,9 +236,9 @@ async function loadForums(): Promise { .map((i) => ({ text: i.name, value: i.id, icon: i.icon_pure })), text: gameFind.name, }; - gameList.push(gameItem); + list.push(gameItem); } - sortGameList.value = gameList; + sortGameList.value = list; } function getForum(forum: number): SortSelect { diff --git a/src/pages/common/PostNews.vue b/src/pages/common/PostNews.vue index 64b1dde9..498c976c 100644 --- a/src/pages/common/PostNews.vue +++ b/src/pages/common/PostNews.vue @@ -68,12 +68,11 @@ 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 { storeToRefs } from "pinia"; -import type { Ref } from "vue"; -import { computed, onMounted, reactive, ref, shallowRef } from "vue"; +import { computed, onMounted, reactive, Ref, ref, shallowRef } from "vue"; import { useRoute, useRouter } from "vue-router"; import { type NewsType, useAppStore } from "@/store/modules/app.js"; -import TGBbs from "@/utils/TGBbs.js"; +import useBBSStore from "@/store/modules/bbs.js"; import TGLogger from "@/utils/TGLogger.js"; import { createPost } from "@/utils/TGWindow.js"; import painterReq from "@/web/request/painterReq.js"; @@ -84,11 +83,15 @@ type RawData = { [key in NewsType]: Ref }; const router = useRouter(); const { recentNewsType } = storeToRefs(useAppStore()); +const { gameList } = storeToRefs(useBBSStore()); const { gid } = <{ gid: string }>useRoute().params; const tabValues: Readonly> = ["notice", "activity", "news"]; const tabMap: Readonly> = { notice: "1", activity: "2", news: "3" }; -const gameName = TGBbs.channels.find((v) => v.gid.toString() === gid)?.title || "未知分区"; +const label = computed(() => { + const game = gameList.value.find((v) => v.id.toString() === gid); + return game?.name || "未知分区"; +}); const loading = ref(false); const showList = ref(false); @@ -117,20 +120,22 @@ async function firstLoad(key: NewsType, refresh: boolean = false): Promise if (rawData[key].lastId !== 0) { if (!refresh) { loading.value = false; + document.documentElement.scrollTo({ top: 0, behavior: "smooth" }); return; } postData[key] = []; rawData[key].lastId = 0; } - await showLoading.start(`正在获取${gameName}${rawData[key].name}数据`); - document.documentElement.scrollTo({ top: 0, behavior: "smooth" }); + await showLoading.start(`正在获取${label.value}${rawData[key].name}数据`); const getData = await painterReq.news(gid, tabMap[key]); await showLoading.update(`数量:${getData.list.length},是否最后一页:${getData.is_last}`); rawData[key] = { isLast: getData.is_last, name: rawData[key].name, lastId: getData.list.length }; postData[key] = getData.list; await showLoading.end(); await TGLogger.Info(`[News][${gid}][firstLoad] 获取${rawData[key].name}数据成功`); - showSnackbar.success(`获取${gameName}${rawData[key].name}数据成功,共 ${getData.list.length} 条`); + showSnackbar.success( + `获取${label.value}${rawData[key].name}数据成功,共 ${getData.list.length} 条`, + ); loading.value = false; } @@ -148,7 +153,7 @@ async function loadMore(key: NewsType): Promise { loading.value = false; return; } - await showLoading.start(`正在获取${gameName}${rawData[key].name}数据`); + await showLoading.start(`正在获取${label.value}${rawData[key].name}数据`); const mod = rawData[key].lastId % 20; const pageSize = mod === 0 ? 20 : 20 - mod; const getData = await painterReq.news(gid, tabMap[key], pageSize, rawData[key].lastId); diff --git a/src/pages/common/PostTopic.vue b/src/pages/common/PostTopic.vue index 93b04639..527c3cbf 100644 --- a/src/pages/common/PostTopic.vue +++ b/src/pages/common/PostTopic.vue @@ -69,9 +69,14 @@ @click:append="searchPost" @keyup.enter="searchPost" /> - 刷新 + 刷新 +
@@ -96,11 +101,12 @@ import showLoading from "@comp/func/loading.js"; import showSnackbar from "@comp/func/snackbar.js"; import VpOverlaySearch from "@comp/viewPost/vp-overlay-search.vue"; import VpOverlayUser from "@comp/viewPost/vp-overlay-user.vue"; +import { storeToRefs } from "pinia"; import { computed, onMounted, ref, shallowRef, watch } from "vue"; import { useRoute, useRouter } from "vue-router"; +import useBBSStore from "@/store/modules/bbs.js"; import { createPost } from "@/utils/TGWindow.js"; -import apiHubReq from "@/web/request/apiHubReq.js"; import postReq from "@/web/request/postReq.js"; import topicReq from "@/web/request/topicReq.js"; @@ -121,7 +127,7 @@ const curUid = ref(""); const showUser = ref(false); const isReq = ref(false); -const allGames = shallowRef>([]); +const { gameList } = storeToRefs(useBBSStore()); const postRaw = shallowRef({ isLast: false, lastId: "", total: 0 }); const topicInfo = shallowRef(); const posts = shallowRef>([]); @@ -150,7 +156,6 @@ onMounted(async () => { curGid.value = Number(gid); curTopic.value = topic; await showLoading.start(`正在加载话题${topic}信息`); - allGames.value = await apiHubReq.game(); const info = await topicReq.info(gid, topic); if ("retcode" in info) { await showLoading.end(); @@ -163,7 +168,7 @@ onMounted(async () => { tmpGame = info.game_info_list.find((i) => i.id === curGid.value); } if (tmpGame === undefined) tmpGame = info.game_info_list[0]; - const gameFind = allGames.value.find((i) => i.id === tmpGame?.id); + const gameFind = gameList.value.find((i) => i.id === tmpGame?.id); curGame.value = { ...tmpGame, icon: gameFind?.app_icon }; await firstLoad(); }); @@ -257,10 +262,10 @@ function searchPost(): void { } else createPost(search.value); } -function getGameList(gameList: Array | undefined): Array { - if (!gameList) return []; - return gameList.map((item) => { - const game = allGames.value.find((i) => i.id === item.id); +function getGameList(list: Array | undefined): Array { + if (!list) return []; + return list.map((item) => { + const game = gameList.value.find((i) => i.id === item.id); return { ...item, icon: game?.app_icon }; }); } diff --git a/src/store/modules/app.ts b/src/store/modules/app.ts index 4708b723..e4e40ea8 100644 --- a/src/store/modules/app.ts +++ b/src/store/modules/app.ts @@ -1,7 +1,7 @@ /** * @file store/modules/app.ts * @description App store module - * @since Beta v0.7.2 + * @since Beta v0.7.3 */ import { path } from "@tauri-apps/api"; @@ -131,13 +131,9 @@ export const useAppStore = defineStore( "shareDefaultFile", "imageQualityPercent", "incognito", + "sidebar", ], }, - { - key: "sidebar", - storage: window.localStorage, - pick: ["sidebar"], - }, { key: "theme", storage: window.localStorage, diff --git a/src/store/modules/bbs.ts b/src/store/modules/bbs.ts new file mode 100644 index 00000000..b501153c --- /dev/null +++ b/src/store/modules/bbs.ts @@ -0,0 +1,27 @@ +/** + * @file store/modules/bbs.ts + * @description BBS 模块状态管理 + * @since Beta v0.7.3 + */ +import { defineStore } from "pinia"; +import { shallowRef } from "vue"; + +import apiHubReq from "@/web/request/apiHubReq.js"; + +const useBBSStore = defineStore( + "bbs", + () => { + // 游戏列表 + const gameList = shallowRef>([]); + + // 刷新游戏列表 + async function refreshGameList(): Promise { + gameList.value = await apiHubReq.game(); + } + + return { gameList, refreshGameList }; + }, + { persist: true }, +); + +export default useBBSStore; diff --git a/src/utils/TGBbs.ts b/src/utils/TGBbs.ts index af493d61..c532a9e5 100644 --- a/src/utils/TGBbs.ts +++ b/src/utils/TGBbs.ts @@ -4,35 +4,29 @@ * @since Beta v0.7.3 */ +/** + * @description salt 类型 + * @since Beta v0.7.3 + */ +export type SaltKey = "K2" | "LK2" | "X4" | "X6" | "PROD"; + const BBS_VERSION: Readonly = "2.85.1"; const BBS_UA_MOBILE: Readonly = `Mozilla/5.0 (Linux; Android 12) Mobile miHoYoBBS/${BBS_VERSION}`; +const BBS_UA_PC: Readonly = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) miHoYoBBS/${BBS_VERSION}`; /** - * @description 频道列表 - * @since Beta v0.6.8 - * @interface ChannelItem - * @property {string} title - 频道名称 - * @property {number} gid - 频道 gid - * @property {string} mini - 频道简称 - * @return ToChannelItem + * @description salt 值 + * @version 2.85.1 + * @since Beta v0.7.3 */ -type ChannelItem = { title: string; gid: number; mini: string }; +const BBS_SALT: Readonly> = { + K2: "ss6ZUzUlaWv6iDe0SHPSdCZYr0RSKPdi", + LK2: "gW20AtTxpc0V5GR3SmsytCLhVBgXtW6I", + X4: "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs", + X6: "t0qEgfub6cvueAPgR5m9aQWWVciEer7v", + PROD: "t0qEgfub6cvueAPgR5m9aQWWVciEer7v", +}; -/** - * @description 渠道列表 - * @since Beta v0.6.8 - * @type {Array} - */ -const CHANNEL_LIST: Readonly> = [ - { title: "原神", gid: 2, mini: "ys" }, - { title: "崩坏:星穹铁道", gid: 6, mini: "sr" }, - { title: "绝区零", gid: 8, mini: "zzz" }, - { title: "崩坏3", gid: 1, mini: "bh3" }, - { title: "崩坏2", gid: 3, mini: "bh2" }, - { title: "未定事件簿", gid: 4, mini: "wd" }, - { title: "大别野", gid: 5, mini: "dby" }, -]; - -const TGBbs = { version: BBS_VERSION, ua: BBS_UA_MOBILE, channels: CHANNEL_LIST }; +const TGBbs = { version: BBS_VERSION, ua: BBS_UA_MOBILE, uap: BBS_UA_PC, salt: BBS_SALT }; export default TGBbs; diff --git a/src/utils/linkParser.ts b/src/utils/linkParser.ts index decf2584..3462cf96 100644 --- a/src/utils/linkParser.ts +++ b/src/utils/linkParser.ts @@ -1,7 +1,7 @@ /** * @file src/utils/linkParser.ts * @description 处理链接 - * @since Beta v0.7.2 + * @since Beta v0.7.3 */ import showDialog from "@comp/func/dialog.js"; @@ -11,8 +11,6 @@ import { emit } from "@tauri-apps/api/event"; import TGClient from "./TGClient.js"; import { createPost } from "./TGWindow.js"; -import TGBbs from "@/utils/TGBbs.js"; - /** * @function parsePost * @since Beta v0.6.9 @@ -114,17 +112,19 @@ export async function parseLink( if (url.pathname.includes("/article/")) { const postId = url.pathname.split("/").pop(); if (typeof postId !== "string") return false; - if (!useInner) { - return "post"; - } + if (!useInner) return "post"; await createPost(postId); return true; - } else if (url.pathname.includes("/topicDetail/")) { + } + if (url.pathname.includes("/topicDetail/")) { const regex = /\/(\w+)\/topicDetail\/(\d+)/; const result = url.pathname.match(regex); if (!result) return false; const [, game, topicId] = result; - const id = TGBbs.channels.find((item) => item.mini === game)?.gid; + const bbsStore = localStorage.getItem("bbs"); + if (!bbsStore) return false; + const gameList: Array = JSON.parse(bbsStore)["gameList"]; + const id = gameList.find((item) => item.en_name === game)?.id; await emit("active_deep_link", `router?path=/posts/topic/${id}/${topicId}`); return true; } diff --git a/src/views/t-post.vue b/src/views/t-post.vue index ad34286a..33bfcfbd 100644 --- a/src/views/t-post.vue +++ b/src/views/t-post.vue @@ -11,7 +11,7 @@