mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-10 08:58:15 +08:00
feat(announcements): 支持游戏内公告查看
This commit is contained in:
@@ -25,7 +25,8 @@
|
||||
"https://api-static.mihoyo.com/*",
|
||||
"https://bbs-api.mihoyo.com/*",
|
||||
"https://bbs-api.miyoushe.com/*",
|
||||
"https://bbs.mihoyo.com/*"
|
||||
"https://bbs.mihoyo.com/*",
|
||||
"https://hk4e-api.mihoyo.com/*"
|
||||
]
|
||||
},
|
||||
"shell": {
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
<img src="/source/UI/paimon.webp" alt="homeIcon" class="sideIcon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item title="咨讯" value="news" link href="/news">
|
||||
<v-list-item title="公告" value="announcements" link href="/announcements">
|
||||
<template v-slot:prepend>
|
||||
<img src="../assets/icons/board.svg" alt="newsIcon" class="sideIcon" />
|
||||
<img src="../assets/icons/board.svg" alt="annoIcon" class="sideIcon" />
|
||||
</template>
|
||||
</v-list-item>
|
||||
<v-list-item title="成就" value="achievements" link href="/achievements">
|
||||
|
||||
167
src/pages/Announcements.vue
Normal file
167
src/pages/Announcements.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div v-if="loading">
|
||||
<t-loading :title="loadingTitle" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<v-tabs v-model="tab" align-tabs="start" class="global-font mb-2">
|
||||
<v-tab value="activity" title="活动公告" />
|
||||
<v-tab value="game" title="游戏公告" />
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn class="switch-btn" @click="switchNews">
|
||||
<template v-slot:prepend>
|
||||
<v-icon>mdi-bullhorn</v-icon>
|
||||
</template>
|
||||
切换米游社咨讯
|
||||
</v-btn>
|
||||
</v-tabs>
|
||||
<v-window v-model="tab">
|
||||
<v-window-item value="activity">
|
||||
<div class="anno-grid">
|
||||
<v-card class="anno-card" v-for="item in annoCards.activity" width="340">
|
||||
<div class="anno-cover" @click="toPost(item)">
|
||||
<img :src="item.banner" alt="cover" />
|
||||
</div>
|
||||
<v-card-title>{{ item.title }}</v-card-title>
|
||||
<v-card-subtitle>{{ item.subtitle }}</v-card-subtitle>
|
||||
<v-card-actions>
|
||||
<v-btn @click="toPost(item)" class="card-btn">
|
||||
<template v-slot:prepend>
|
||||
<img src="../assets/icons/arrow-right.svg" alt="right" />
|
||||
</template>
|
||||
查看
|
||||
</v-btn>
|
||||
<v-card-subtitle
|
||||
><v-icon>mdi-calendar</v-icon> {{ item.start_time.split(" ")[0] }} -
|
||||
{{ item.end_time.split(" ")[0] }}</v-card-subtitle
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</div>
|
||||
</v-window-item>
|
||||
<v-window-item value="game">
|
||||
<div class="anno-grid">
|
||||
<v-card class="anno-card" v-for="item in annoCards.game" width="340">
|
||||
<div class="anno-cover" @click="toPost(item)">
|
||||
<img :src="item.banner" alt="cover" />
|
||||
</div>
|
||||
<v-card-title>{{ item.title }}</v-card-title>
|
||||
<v-card-subtitle>{{ item.subtitle }}</v-card-subtitle>
|
||||
<v-card-actions>
|
||||
<v-btn @click="toPost(item)" class="card-btn">
|
||||
<template v-slot:prepend>
|
||||
<img src="../assets/icons/arrow-right.svg" alt="right" />
|
||||
</template>
|
||||
查看
|
||||
</v-btn>
|
||||
<v-card-subtitle>
|
||||
<v-icon>mdi-calendar</v-icon>
|
||||
{{ item.start_time.split(" ")[0] }} -
|
||||
{{ item.end_time.split(" ")[0] }}</v-card-subtitle
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</div>
|
||||
</v-window-item>
|
||||
</v-window>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
// vue
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import TLoading from "../components/t-loading.vue";
|
||||
// plugin
|
||||
import GenshinOper from "../plugins/Genshin";
|
||||
// utils
|
||||
import { createTGWindow } from "../utils/TGWindow";
|
||||
// interface
|
||||
import { AnnoListData, AnnoListCard } from "../plugins/Genshin/interface/announcement";
|
||||
|
||||
// loading
|
||||
const loading = ref(true);
|
||||
const loadingTitle = ref("正在加载");
|
||||
// 路由
|
||||
const router = useRouter();
|
||||
|
||||
// 数据
|
||||
const tab = ref("");
|
||||
const annoCards = ref({
|
||||
activity: [] as AnnoListCard[],
|
||||
game: [] as AnnoListCard[],
|
||||
});
|
||||
const annoData = ref({} as AnnoListData);
|
||||
|
||||
onMounted(async () => {
|
||||
loadingTitle.value = "正在获取公告数据";
|
||||
annoData.value = await GenshinOper.Announcement.get.list();
|
||||
loadingTitle.value = "正在转换公告数据";
|
||||
const listCards = GenshinOper.Announcement.card(annoData.value);
|
||||
const activityCard = listCards.filter(item => item.type_label === "活动公告");
|
||||
const newsCard = listCards.filter(item => item.type_label === "游戏公告");
|
||||
annoCards.value = {
|
||||
activity: activityCard,
|
||||
game: newsCard,
|
||||
};
|
||||
console.log(annoCards.value);
|
||||
tab.value = "activity";
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
function switchNews() {
|
||||
router.push("/news");
|
||||
}
|
||||
|
||||
async function toPost(item: AnnoListCard) {
|
||||
const path = router.resolve({
|
||||
name: "游戏内公告",
|
||||
params: {
|
||||
anno_id: item.id,
|
||||
},
|
||||
}).href;
|
||||
createTGWindow(path, "游戏内公告", item.title, 960, 720, false);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.anno-grid {
|
||||
font-family: Genshin, serif;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
|
||||
grid-gap: 20px;
|
||||
}
|
||||
|
||||
.anno-card {
|
||||
border-radius: 10px;
|
||||
background: #faf7e8;
|
||||
color: #546d8b;
|
||||
}
|
||||
|
||||
.anno-cover {
|
||||
height: 130px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.anno-cover :hover {
|
||||
transform: scale(1.1);
|
||||
transition: all 0.3s linear;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.anno-cover img {
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
height: 130px;
|
||||
transition: all 0.3s linear;
|
||||
}
|
||||
|
||||
/* switch */
|
||||
.switch-btn {
|
||||
font-family: Genshin, serif;
|
||||
background: #ffca0a;
|
||||
height: 40px;
|
||||
margin-right: 10px;
|
||||
margin-top: 5px;
|
||||
color: #546d8b;
|
||||
}
|
||||
</style>
|
||||
@@ -1,3 +1,10 @@
|
||||
/**
|
||||
* @file router index.ts
|
||||
* @description 路由入口
|
||||
* @author BTMuli<bt-muli@outlook.com>
|
||||
* @since Alpha
|
||||
*/
|
||||
|
||||
import { createRouter, createWebHistory } from "vue-router";
|
||||
import routes from "./routes";
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
* @file router modules main.ts
|
||||
* @description 主路由模块
|
||||
* @author BTMuli<bt-muli@outlook.com>
|
||||
* @since Alpha
|
||||
* @since Alpha v0.1.1
|
||||
*/
|
||||
|
||||
// 信息展示
|
||||
import Announcements from "../../pages/Announcements.vue";
|
||||
import Home from "../../pages/Home.vue";
|
||||
import News from "../../pages/News.vue";
|
||||
import GCG from "../../pages/GCG.vue";
|
||||
@@ -25,6 +26,11 @@ const mainRoutes = [
|
||||
name: "成就",
|
||||
component: Achievements,
|
||||
},
|
||||
{
|
||||
path: "/announcements",
|
||||
name: "公告",
|
||||
component: Announcements,
|
||||
},
|
||||
{
|
||||
path: "/config",
|
||||
name: "设置",
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
* @file router modules sub.ts
|
||||
* @description 子路由模块,用于二级窗口
|
||||
* @author BTMuli<bt-muli@outlook.com>
|
||||
* @since Alpha
|
||||
* @since Alpha v0.1.1
|
||||
*/
|
||||
// 帖子相关
|
||||
import TPost from "../../views/t-post.vue";
|
||||
import TPostJson from "../../views/t-post-json.vue";
|
||||
// 抽奖
|
||||
import TLottery from "../../views/t-lottery.vue";
|
||||
// 游戏内公告
|
||||
import TAnno from "../../views/t-anno.vue";
|
||||
|
||||
const subRoutes = [
|
||||
{
|
||||
@@ -26,6 +28,11 @@ const subRoutes = [
|
||||
name: "抽奖详情",
|
||||
component: TLottery,
|
||||
},
|
||||
{
|
||||
path: "/anno/:anno_id",
|
||||
name: "游戏内公告",
|
||||
component: TAnno,
|
||||
},
|
||||
];
|
||||
|
||||
export default subRoutes;
|
||||
|
||||
76
src/views/t-anno.vue
Normal file
76
src/views/t-anno.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div v-if="loading" class="loading">
|
||||
<t-loading :title="loadingTitle" :empty="loadingEmpty" />
|
||||
</div>
|
||||
<div v-else class="anno-body">
|
||||
<div class="anno-title">{{ annoData.title }}</div>
|
||||
<div class="anno-subtitle">{{ annoData.subtitle }}</div>
|
||||
<img :src="annoData.banner" alt="cover" class="mys-post-img" />
|
||||
<div v-html="annoHtml" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
// vue
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import TLoading from "../components/t-loading.vue";
|
||||
// plugins
|
||||
import GenshinOper from "../plugins/Genshin";
|
||||
// interface
|
||||
import { AnnoContentItem } from "../plugins/Genshin/interface/announcement";
|
||||
|
||||
// loading
|
||||
const loading = ref(true as boolean);
|
||||
const loadingTitle = ref("正在加载");
|
||||
const loadingEmpty = ref(false as boolean);
|
||||
|
||||
// 数据
|
||||
const anno_id = Number(useRoute().params.anno_id);
|
||||
const annoData = ref({} as AnnoContentItem);
|
||||
const annoHtml = ref("");
|
||||
|
||||
onMounted(async () => {
|
||||
// 检查数据
|
||||
if (!anno_id) {
|
||||
loadingEmpty.value = true;
|
||||
loadingTitle.value = "未找到数据";
|
||||
return;
|
||||
}
|
||||
// 获取数据
|
||||
loadingTitle.value = "正在获取数据...";
|
||||
try {
|
||||
annoData.value = await GenshinOper.Announcement.get.content(anno_id);
|
||||
loadingTitle.value = "正在渲染数据...";
|
||||
annoHtml.value = annoData.value.content;
|
||||
} catch (error) {
|
||||
loadingEmpty.value = true;
|
||||
loadingTitle.value = "公告不存在或解析失败";
|
||||
return;
|
||||
}
|
||||
setInterval(() => {
|
||||
loading.value = false;
|
||||
}, 200);
|
||||
});
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
/* todo 完善样式 */
|
||||
.anno-body {
|
||||
margin: 20px auto;
|
||||
width: 800px;
|
||||
font-family: "Genshin-Light", serif;
|
||||
}
|
||||
|
||||
.anno-title {
|
||||
font-family: Genshin, serif;
|
||||
color: #5b738f;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.anno-subtitle {
|
||||
font-size: 16px;
|
||||
color: #a1aeb6;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user