mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-10 08:58:15 +08:00
✨ 支持 post&anno share
This commit is contained in:
@@ -30,7 +30,8 @@
|
||||
"https://hk4e-api.mihoyo.com/*",
|
||||
"https://passport-api.mihoyo.com/*",
|
||||
"https://passport-api-v4.mihoyo.com/*",
|
||||
"https://act-webstatic.mihoyo.com/*"
|
||||
"https://act-webstatic.mihoyo.com/*",
|
||||
"https://sdk-webstatic.mihoyo.com/*"
|
||||
]
|
||||
},
|
||||
"shell": {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/*
|
||||
* @file assets css post-parser.css
|
||||
* @description 游戏公告解析 css
|
||||
* @since Alpha v0.1.1
|
||||
* @author BTMuli <bt-muli@outlook.com
|
||||
* @since Alpha v0.2.0
|
||||
*/
|
||||
|
||||
.anno-body {
|
||||
margin: 20px auto;
|
||||
margin: 0 auto;
|
||||
width: 800px;
|
||||
font-family: "Genshin-Light", serif;
|
||||
font-family: var(--font-text);
|
||||
}
|
||||
|
||||
.anno-title {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/*
|
||||
* @file assets css post-parser.css
|
||||
* @description 米游社解析 css
|
||||
* @since Alpha v0.1.3
|
||||
* @author BTMuli <bt-muli@outlook.com>
|
||||
* @since Alpha v0.2.0
|
||||
*/
|
||||
|
||||
.mys-post-body {
|
||||
margin: 20px auto;
|
||||
margin: 0 auto;
|
||||
width: 800px;
|
||||
font-family: "Genshin-Light", serif;
|
||||
font-family: var(--font-text);
|
||||
color: var(--post-default-text);
|
||||
}
|
||||
|
||||
|
||||
48
src/components/main/t-shareBtn.vue
Normal file
48
src/components/main/t-shareBtn.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="share-box">
|
||||
<div class="share-btn" @click="shareContent()">
|
||||
<v-icon style="color:var(--theme-switch-icon)">
|
||||
mdi-share-variant
|
||||
</v-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
// utils
|
||||
import { generateShareImg } from "../../utils/TGShare";
|
||||
|
||||
interface TShareBtnProps {
|
||||
modelValue: HTMLElement;
|
||||
title: string;
|
||||
}
|
||||
|
||||
const props = defineProps<TShareBtnProps>();
|
||||
|
||||
async function shareContent () {
|
||||
await generateShareImg(props.title, props.modelValue);
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.share-box {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
border: var(--theme-switch-icon) 2px solid;
|
||||
}
|
||||
|
||||
.share-box:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.share-btn {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 5px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,7 @@
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<TSwitchTheme />
|
||||
<TShareBtn v-show="!loadingEmpty" v-model="annoRef" :title="annoTitle" />
|
||||
<TOLoading v-model="loading" :title="loadingTitle" :empty="loadingEmpty" />
|
||||
<div class="anno-body">
|
||||
<div class="anno-title">
|
||||
@@ -9,7 +10,7 @@
|
||||
<div class="anno-subtitle">
|
||||
{{ annoData.subtitle }}
|
||||
</div>
|
||||
<img v-if="annoData.banner !== ''" :src="annoData.banner" alt="cover" class="anno-img">
|
||||
<img v-if="annoData.banner !== ''" :src="annoBanner" alt="cover" class="anno-img">
|
||||
<div class="anno-content" v-html="annoHtml" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -19,21 +20,28 @@ import { ref, onMounted } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import TOLoading from "../components/overlay/to-loading.vue";
|
||||
import TSwitchTheme from "../components/main/t-switchTheme.vue";
|
||||
import TShareBtn from "../components/main/t-shareBtn.vue";
|
||||
// tauri
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
// plugins
|
||||
import TGRequest from "../web/request/TGRequest";
|
||||
import TGUtils from "../web/utils/TGUtils";
|
||||
import { saveImgLocal } from "../utils/TGShare";
|
||||
|
||||
// loading
|
||||
const loading = ref(true as boolean);
|
||||
const loadingTitle = ref("正在加载");
|
||||
const loadingEmpty = ref(false as boolean);
|
||||
|
||||
// share
|
||||
const annoRef = ref({} as HTMLElement);
|
||||
const annoTitle = ref("");
|
||||
|
||||
// 数据
|
||||
const annoId = Number(useRoute().params.anno_id);
|
||||
const annoData = ref({} as TGApp.BBS.Announcement.ContentItem);
|
||||
const annoHtml = ref("");
|
||||
const annoBanner = ref("");
|
||||
|
||||
onMounted(async () => {
|
||||
await appWindow.show();
|
||||
@@ -49,8 +57,13 @@ onMounted(async () => {
|
||||
try {
|
||||
annoData.value = await TGRequest.Anno.getContent(annoId);
|
||||
loadingTitle.value = "正在渲染数据...";
|
||||
annoHtml.value = TGUtils.Anno.parseContent(annoData.value.content);
|
||||
annoHtml.value = await TGUtils.Anno.parseContent(annoData.value.content);
|
||||
annoBanner.value = await saveImgLocal(annoData.value.banner);
|
||||
console.log(annoBanner.value);
|
||||
annoTitle.value = annoData.value.title;
|
||||
annoRef.value = document.querySelector(".anno-body") as HTMLElement;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
loadingEmpty.value = true;
|
||||
loadingTitle.value = "公告不存在或解析失败";
|
||||
return;
|
||||
|
||||
@@ -222,7 +222,7 @@ import MysOper from "../plugins/Mys";
|
||||
// utils
|
||||
import { createTGWindow } from "../utils/TGWindow";
|
||||
// interface
|
||||
import { NewsCard, NewsData } from "../plugins/Mys/interface/news";
|
||||
import { NewsCard } from "../plugins/Mys/interface/news";
|
||||
|
||||
// 路由
|
||||
const router = useRouter();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<TSwitchTheme />
|
||||
<TShareBtn v-show="!loadingEmpty" v-model="postRef" :title="postTitle" />
|
||||
<TOLoading v-model="loading" :empty="loadingEmpty" :title="loadingTitle" />
|
||||
<div class="mys-post-body" v-html="postHtml" />
|
||||
</template>
|
||||
@@ -9,21 +10,27 @@
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import TOLoading from "../components/overlay/to-loading.vue";
|
||||
import TSwitchTheme from "../components/main/t-switchTheme.vue";
|
||||
import TShareBtn from "../components/main/t-shareBtn.vue";
|
||||
// tauri
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
// plugins
|
||||
import MysOper from "../plugins/Mys";
|
||||
import TSwitchTheme from "../components/main/t-switchTheme.vue";
|
||||
|
||||
// loading
|
||||
const loading = ref(true as boolean);
|
||||
const loadingTitle = ref("正在加载");
|
||||
const loadingEmpty = ref(false as boolean);
|
||||
|
||||
// share
|
||||
const postRef = ref({} as HTMLElement);
|
||||
const postTitle = ref("");
|
||||
|
||||
// 数据
|
||||
const postId = Number(useRoute().params.post_id);
|
||||
const postHtml = ref("");
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
await appWindow.show();
|
||||
// 检查数据
|
||||
@@ -39,6 +46,8 @@ onMounted(async () => {
|
||||
const postData = await MysOper.Post.get(postId);
|
||||
loadingTitle.value = "正在渲染数据...";
|
||||
postHtml.value = MysOper.Post.parser(postData);
|
||||
postTitle.value = postData.post.subject;
|
||||
postRef.value = document.querySelector(".mys-post-body") as HTMLElement;
|
||||
await appWindow.setTitle(postData.post.subject);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
/**
|
||||
* @file web utils parseAnno.ts
|
||||
* @description 解析游戏内公告数据
|
||||
* @author BTMuli<bt-muli@outlook.com>
|
||||
* @since Alpha v0.1.5
|
||||
* @author BTMuli <bt-muli@outlook.com>
|
||||
* @since Alpha v0.2.0
|
||||
*/
|
||||
|
||||
import { decodeRegExp } from "./tools";
|
||||
import { saveImgLocal } from "../../utils/TGShare";
|
||||
|
||||
/**
|
||||
* @description 解析游戏内公告数据
|
||||
* @since Alpha v0.1.5
|
||||
* @since Alpha v0.2.0
|
||||
* @param {string} data 游戏内公告数据
|
||||
* @returns {string} 解析后的数据
|
||||
* @returns {Promise<string>} 解析后的数据
|
||||
*/
|
||||
export function parseAnnoContent (data: string): string {
|
||||
export async function parseAnnoContent(data: string): Promise<string> {
|
||||
const htmlBase = new DOMParser().parseFromString(data, "text/html");
|
||||
htmlBase.querySelectorAll("span").forEach((span) => {
|
||||
if (span.style.fontSize) {
|
||||
@@ -40,11 +41,16 @@ export function parseAnnoContent (data: string): string {
|
||||
});
|
||||
}
|
||||
});
|
||||
htmlBase.querySelectorAll("img").forEach((img) => {
|
||||
const imgList = Array.from(htmlBase.querySelectorAll("img"));
|
||||
for (const img of imgList) {
|
||||
img.style.maxWidth = "100%";
|
||||
img.style.borderRadius = "10px";
|
||||
img.style.margin = "10px 0";
|
||||
});
|
||||
const src = img.getAttribute("src");
|
||||
if (src) {
|
||||
img.setAttribute("src", await saveImgLocal(src));
|
||||
}
|
||||
}
|
||||
htmlBase.querySelectorAll("a").forEach((a) => {
|
||||
const span = htmlBase.createElement("i");
|
||||
span.classList.add("mdi", "mdi-link-variant", "anno-link-icon");
|
||||
|
||||
Reference in New Issue
Block a user