mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-15 09:48:14 +08:00
feat(MysParse): 采用结构化内容进行渲染以支持视频播放
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-tabs v-model="tab" align-tabs="start" stacked>
|
<v-tabs v-model="tab" align-tabs="start">
|
||||||
<v-tab value="notice">公告</v-tab>
|
<v-tab value="notice">公告</v-tab>
|
||||||
<v-tab value="activity">活动</v-tab>
|
<v-tab value="activity">活动</v-tab>
|
||||||
<v-tab value="news">咨讯</v-tab>
|
<v-tab value="news">咨讯</v-tab>
|
||||||
</v-tabs>
|
</v-tabs>
|
||||||
<v-window v-model="tab" class="stick-window">
|
<v-window v-model="tab">
|
||||||
<v-window-item value="notice">
|
<v-window-item value="notice">
|
||||||
<div class="cards-grid">
|
<div class="cards-grid">
|
||||||
<v-card
|
<v-card
|
||||||
@@ -112,6 +112,7 @@ import {
|
|||||||
} from "../interface/MysPost";
|
} from "../interface/MysPost";
|
||||||
import { http, fs } from "@tauri-apps/api";
|
import { http, fs } from "@tauri-apps/api";
|
||||||
import { createTGWindow } from "../utils/TGWindow";
|
import { createTGWindow } from "../utils/TGWindow";
|
||||||
|
import { parseMys } from "../utils/MysParse";
|
||||||
|
|
||||||
// Store
|
// Store
|
||||||
const devStore = useDevStore();
|
const devStore = useDevStore();
|
||||||
@@ -182,19 +183,12 @@ async function toPost(post_id: string) {
|
|||||||
const post: MysPostType = await getPost(post_id).then(res => {
|
const post: MysPostType = await getPost(post_id).then(res => {
|
||||||
return res.data.post.post;
|
return res.data.post.post;
|
||||||
});
|
});
|
||||||
// 将内容转换为 html
|
// 解析 json
|
||||||
const postHtml = new DOMParser().parseFromString(post.content, "text/html");
|
const parseDoc = parseMys(post.structured_content);
|
||||||
// 用帖子标题替换 html 中的标题
|
// 将解析后的 doc 保存到 文件
|
||||||
postHtml.title = post.subject;
|
|
||||||
// 四周留白
|
|
||||||
postHtml.body.style.padding = "12%";
|
|
||||||
postHtml.querySelectorAll("img").forEach(img => {
|
|
||||||
img.style.width = "100%";
|
|
||||||
});
|
|
||||||
// 将 html 保存到 文件
|
|
||||||
await fs.writeTextFile(
|
await fs.writeTextFile(
|
||||||
`${appStore.dataPath.temp}\\${post.post_id}.html`,
|
`${appStore.dataPath.temp}\\${post_id}.html`,
|
||||||
postHtml.documentElement.outerHTML
|
parseDoc.documentElement.outerHTML
|
||||||
);
|
);
|
||||||
const postUrl = `file:\\\\\\${appStore.dataPath.temp}\\${post.post_id}.html`;
|
const postUrl = `file:\\\\\\${appStore.dataPath.temp}\\${post.post_id}.html`;
|
||||||
createTGWindow(postUrl, "MysPost", post.subject, 960, 720, false);
|
createTGWindow(postUrl, "MysPost", post.subject, 960, 720, false);
|
||||||
@@ -208,9 +202,9 @@ async function logPost(post_id: string) {
|
|||||||
`${appStore.dataPath.temp}\\${post_id}_log.json`,
|
`${appStore.dataPath.temp}\\${post_id}_log.json`,
|
||||||
JSON.stringify(post, null, 4)
|
JSON.stringify(post, null, 4)
|
||||||
);
|
);
|
||||||
const postUrl = `file:\\\\\\${appStore.dataPath.temp}\\${post_id}_log.json`;
|
const logUrl = `file:\\\\\\${appStore.dataPath.temp}\\${post_id}_log.json`;
|
||||||
// 打开窗口
|
// 打开窗口
|
||||||
createTGWindow(postUrl, "MysPostLog", post_id, 960, 720, false);
|
createTGWindow(logUrl, "MysPostLog", post_id, 960, 720, false);
|
||||||
}
|
}
|
||||||
async function getPost(post_id: string): Promise<ResponsePost> {
|
async function getPost(post_id: string): Promise<ResponsePost> {
|
||||||
return http
|
return http
|
||||||
@@ -227,12 +221,6 @@ async function getPost(post_id: string): Promise<ResponsePost> {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="css">
|
<style lang="css">
|
||||||
/* todo @media */
|
|
||||||
.stick-window {
|
|
||||||
height: 800px;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cards-grid {
|
.cards-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||||
|
|||||||
88
src/utils/MysParse.ts
Normal file
88
src/utils/MysParse.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* @file utils MysParse.ts
|
||||||
|
* @description 用于解析Mys数据的工具
|
||||||
|
* @author BTMuli<bt-muli@outlook.com>
|
||||||
|
* @since Alpha
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 解析Mys数据
|
||||||
|
* @param {string} data Mys数据
|
||||||
|
* @description 为了安全考虑,不会解析所有的属性,只会解析几个常用的属性
|
||||||
|
* @returns {Document} 解析后的 HTML 文档
|
||||||
|
*/
|
||||||
|
export function parseMys(data: string): Document {
|
||||||
|
// Json 化
|
||||||
|
let jsonData = JSON.parse(data);
|
||||||
|
while (typeof jsonData === "string") jsonData = JSON.parse(jsonData);
|
||||||
|
// 创建 HTML 文档
|
||||||
|
const doc = document.implementation.createHTMLDocument();
|
||||||
|
// 遍历 Json 数据
|
||||||
|
jsonData.forEach((item: any) => {
|
||||||
|
if (item.insert.image) {
|
||||||
|
// 创建 div
|
||||||
|
const div = document.createElement("div");
|
||||||
|
// 创建图片
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = item.insert.image;
|
||||||
|
// 设置图片属性
|
||||||
|
img.height = item.attributes.height; // 设置高度
|
||||||
|
img.width = item.attributes.width; // 设置宽度
|
||||||
|
// 如果宽度超过 800,将其设置为 800,图片自适应
|
||||||
|
if (img.width > 800) img.width = 800;
|
||||||
|
// 高度自适应
|
||||||
|
img.style.height = "auto";
|
||||||
|
// 插入图片
|
||||||
|
div.appendChild(img);
|
||||||
|
// 设置 div 属性
|
||||||
|
div.style.display = "center"; // 居中
|
||||||
|
div.style.margin = "20px auto"; // 设置 margin
|
||||||
|
// 插入 div
|
||||||
|
doc.body.appendChild(div);
|
||||||
|
} else if (item.insert.vod) {
|
||||||
|
// 创建 div
|
||||||
|
const div = document.createElement("div");
|
||||||
|
// 创建视频
|
||||||
|
const video = document.createElement("video");
|
||||||
|
// 设置一些属性
|
||||||
|
video.poster = item.insert.vod.cover; // 设置封面
|
||||||
|
video.height = item.insert.vod.resolutions[0].height; // 设置高度
|
||||||
|
video.width = item.insert.vod.resolutions[0].width; // 设置宽度
|
||||||
|
video.controls = true; // 设置 controls
|
||||||
|
// 获取 resolutions,将其作为 source
|
||||||
|
const resolutions = item.insert.vod.resolutions;
|
||||||
|
// 添加 source
|
||||||
|
const source = document.createElement("source");
|
||||||
|
source.src = resolutions[0].url;
|
||||||
|
source.type = resolutions[0].format === ".mp4" ? "video/mp4" : "video/webm";
|
||||||
|
video.appendChild(source);
|
||||||
|
// 添加 controls
|
||||||
|
video.controls = true;
|
||||||
|
// 插入 video
|
||||||
|
div.appendChild(video);
|
||||||
|
// 设置 div 属性
|
||||||
|
div.style.display = "center"; // 居中
|
||||||
|
div.style.margin = "20px auto"; // 设置 margin
|
||||||
|
// 插入 div
|
||||||
|
doc.body.appendChild(div);
|
||||||
|
} else if (typeof item.insert === "string") {
|
||||||
|
// 创建文本
|
||||||
|
const text = document.createElement("span");
|
||||||
|
// 设置文本属性
|
||||||
|
// 创建 style string
|
||||||
|
if (item.attributes) {
|
||||||
|
let styleString = "";
|
||||||
|
if (item.attributes.color) styleString += `color: ${item.attributes.color};`;
|
||||||
|
// 设置 style
|
||||||
|
text.style.cssText = styleString;
|
||||||
|
}
|
||||||
|
text.innerText = item.insert; // 设置文本
|
||||||
|
// 插入文本
|
||||||
|
doc.body.appendChild(text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// doc 宽度设为 800,居中
|
||||||
|
doc.body.style.width = "900px";
|
||||||
|
doc.body.style.margin = "20px auto";
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user