Files
TeyvatGuide/src/pages/common/PostForum.vue
目棃 582d2cffb8 🚸 添加Hint
2024-12-16 11:57:24 +08:00

326 lines
9.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<v-app-bar>
<template #prepend>
<div class="posts-top">
<img src="/source/UI/posts.png" alt="posts" />
<span>帖子</span>
</div>
</template>
<div class="posts-switch">
<v-select
v-model="curGid"
class="post-switch-item"
:items="sortGameList"
item-title="text"
item-value="gid"
variant="outlined"
label="分区"
/>
<v-select
v-model="curForum"
class="post-switch-item"
:items="getGameForums(curGid)"
item-title="text"
item-value="value"
variant="outlined"
label="版块"
/>
<v-select
v-model="curSortType"
class="post-switch-item"
:items="sortOrderList"
item-title="text"
item-value="value"
variant="outlined"
label="排序"
/>
<v-text-field
v-model="search"
class="post-switch-item"
append-inner-icon="mdi-magnify"
label="请输入帖子 ID 或搜索词"
variant="outlined"
:single-line="true"
:hide-details="true"
@click:append="searchPost"
@keyup.enter="searchPost"
/>
<v-btn :rounded="true" class="post-forum-btn" @click="freshPostData()">
<v-icon>mdi-refresh</v-icon>
<span>刷新</span>
</v-btn>
</div>
<template #extension>
<TGameNav :model-value="curGid" />
</template>
</v-app-bar>
<div class="posts-grid">
<div v-for="post in posts" :key="post.post.post_id">
<TPostCard :model-value="post" v-if="post" />
</div>
</div>
<div class="posts-load-more">
<v-btn class="post-forum-btn" :rounded="true" @click="loadMore()">
已加载{{ posts.length }}加载更多
</v-btn>
</div>
<VpOverlaySearch :gid="curGid.toString()" v-model="showSearch" :keyword="search" />
</template>
<script setup lang="ts">
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 TGLogger from "@/utils/TGLogger.js";
import { createPost } from "@/utils/TGWindow.js";
type SortSelect = { text: string; value: number };
type SortSelectGame = { gid: number; forum: Array<SortSelect>; text: string };
const sortOrderList: Array<SortSelect> = [
{ text: "最新回复", value: 1 },
{ text: "最新发布", value: 2 },
{ text: "热门", value: 3 },
];
const forumYsList: Array<SortSelect> = [
{ text: "酒馆", value: 26 },
{ text: "攻略", value: 43 },
{ text: "同人图", value: 29 },
{ text: "COS", value: 49 },
{ text: "硬核", value: 50 },
];
const forumSrList: Array<SortSelect> = [
{ text: "候车室", value: 52 },
{ text: "攻略", value: 61 },
{ text: "同人图", value: 56 },
{ text: "COS", value: 62 },
];
const forumBh3List: Array<SortSelect> = [
{ text: "甲板", value: 1 },
{ text: "攻略", value: 14 },
{ text: "同人图", value: 4 },
{ text: "同人文", value: 41 },
];
const forumBh2List: Array<SortSelect> = [
{ text: "学园", value: 30 },
{ text: "攻略", value: 51 },
{ text: "同人图", value: 40 },
];
const forumWdList: Array<SortSelect> = [
{ text: "律所", value: 37 },
{ text: "攻略", value: 60 },
{ text: "同人文", value: 42 },
{ text: "同人图", value: 38 },
];
const forumZzzList: Array<SortSelect> = [
{ text: "咖啡馆", value: 57 },
{ text: "攻略", value: 64 },
{ text: "同人图", value: 59 },
{ text: "COS", value: 65 },
];
const forumDbyList: Array<SortSelect> = [
{ text: "校园", value: 54 },
{ text: "ACG", value: 35 },
{ text: "生活", value: 34 },
{ text: "同人图", value: 39 },
{ text: "COS", value: 47 },
{ text: "脑洞", value: 48 },
{ text: "科技", value: 55 },
{ text: "公告", value: 36 },
];
const sortGameList: Readonly<Array<SortSelectGame>> = [
{ gid: 2, forum: forumYsList, text: "原神" },
{ gid: 6, forum: forumSrList, text: "崩坏:星穹铁道" },
{ gid: 8, forum: forumZzzList, text: "绝区零" },
{ gid: 1, forum: forumBh3List, text: "崩坏3" },
{ gid: 3, forum: forumBh2List, text: "崩坏2" },
{ gid: 4, forum: forumWdList, text: "未定事件簿" },
{ gid: 5, forum: forumDbyList, 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 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);
if (forum && typeof forum === "string") curForum.value = Number(forum);
const gameLabel = getGameLabel(curGid.value);
const forumLabel = getForumLabel(curGid.value, curForum.value);
await TGLogger.Info(`[Posts][${gameLabel}][onMounted][${forumLabel}] 打开帖子列表`);
await freshPostData();
curForumLabel.value = forumLabel;
firstLoad.value = true;
});
watch(
() => curGid.value,
() => {
const forums = getGameForums(curGid.value);
const forumFind = forums.find((item) => item.text === curForumLabel.value);
if (!firstLoad.value) return;
if (forumFind) curForum.value = forumFind.value;
else curForum.value = forums[0].value;
showSnackbar.success(`已将分区切换到 ${getGameLabel(curGid.value)}`);
},
);
watch(
() => curForum.value,
async () => {
await freshPostData();
const oldForumLabel = JSON.parse(JSON.stringify(curForumLabel.value));
curForumLabel.value = getForumLabel(curGid.value, curForum.value);
if (oldForumLabel !== curForumLabel.value) {
showSnackbar.success(`已将版块切换到 ${curForumLabel.value}`);
}
},
);
watch(
() => curSortType.value,
async () => {
await freshPostData();
const sortLabel = getSortLabel(curSortType.value);
showSnackbar.success(`已将排序切换到 ${sortLabel}`);
},
);
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> {
await showLoading.start(`正在刷新${getGameLabel(curGid.value)}帖子`);
const gameLabel = getGameLabel(curGid.value);
const forumLabel = getForumLabel(curGid.value, curForum.value);
const sortLabel = getSortLabel(curSortType.value);
await TGLogger.Info(
`[Posts][${gameLabel}][freshPostData][${forumLabel}][${sortLabel}] 刷新帖子列表`,
);
await showLoading.update(`版块:${forumLabel},排序:${sortLabel}`);
document.documentElement.scrollTo({ top: 0, behavior: "smooth" });
const postsGet = await Mys.Post.getForumPostList(curForum.value, curSortType.value);
posts.value = postsGet.list;
lastId.value = postsGet.last_id;
isLast.value = postsGet.is_last;
showSnackbar.success(`刷新成功,共加载 ${postsGet.list.length} 条帖子`);
await showLoading.end();
}
async function loadMore(): Promise<void> {
if (isLast.value) {
showSnackbar.warn("没有更多帖子了");
return;
}
await showLoading.start("正在加载更多帖子数据", `游戏:${getGameLabel(curGid.value)}`);
const postsGet = await Mys.Post.getForumPostList(curForum.value, curSortType.value, lastId.value);
await showLoading.update(
`版块:${curForumLabel.value},排序:${getSortLabel(curSortType.value)},数量:${postsGet.list.length}`,
);
posts.value = posts.value.concat(postsGet.list);
lastId.value = postsGet.last_id;
isLast.value = postsGet.is_last;
showSnackbar.success(`加载成功,共加载 ${postsGet.list.length} 条帖子`);
await showLoading.end();
}
function searchPost(): void {
if (search.value === "") {
showSnackbar.warn("请输入搜索内容");
return;
}
const numCheck = Number(search.value);
if (isNaN(numCheck)) showSearch.value = true;
else createPost(search.value);
}
</script>
<style lang="css" scoped>
.posts-top {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
img {
width: 32px;
height: 32px;
}
span {
color: var(--common-text-title);
font-family: var(--font-title);
font-size: 20px;
}
}
.posts-switch {
display: flex;
align-items: flex-end;
justify-content: center;
margin: 0 10px;
gap: 10px;
}
.post-switch-item {
width: 250px;
height: 50px;
}
.post-forum-btn {
height: 40px;
background: var(--btn-bg-1);
color: var(--btn-text-1);
font-family: var(--font-title);
}
.dark .post-forum-btn {
border: 1px solid var(--common-shadow-2);
}
.posts-grid {
display: grid;
padding: 5px;
font-family: var(--font-title);
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
.posts-load-more {
display: flex;
align-items: center;
justify-content: center;
margin: 10px;
font-family: var(--font-title);
transition: all 0.3s linear;
}
</style>