♻️ 重构链接识别处理

This commit is contained in:
BTMuli
2023-12-13 18:03:08 +08:00
parent e9d1d70d36
commit c2306ed5d7
5 changed files with 123 additions and 84 deletions

View File

@@ -14,9 +14,9 @@
</template>
<script lang="ts" setup>
import { toRaw } from "vue";
import { useRouter } from "vue-router";
import { isMysPost } from "../../utils/toolFunc";
import { parseLink } from "../../utils/linkParser";
import showSnackbar from "../func/snackbar";
interface TpLinkCard {
insert: {
@@ -41,22 +41,22 @@ interface TpLinkCardProps {
}
const props = defineProps<TpLinkCardProps>();
const router = useRouter();
console.log("tpLinkCard", props.data.insert.link_card.card_id, toRaw(props.data).insert.link_card);
async function toLink() {
const link = props.data.insert.link_card.landing_url;
if (isMysPost(link)) {
await router.push({
name: "帖子详情",
params: {
post_id: link.split("/").pop(),
},
const res = await parseLink(link);
if (res === true) return;
if (res === false) {
showSnackbar({
text: `未知链接:${link}`,
color: "error",
timeout: 3000,
});
} else {
window.open(link);
return;
}
window.open(res);
}
</script>
<style lang="css" scoped>

View File

@@ -22,12 +22,10 @@
</template>
<script lang="ts" setup>
import { onMounted, ref, StyleValue, toRaw } from "vue";
import { useRouter } from "vue-router";
import { getEmojis } from "../../plugins/Mys/request/getEmojis";
import TGClient from "../../utils/TGClient";
import { isColorSimilar, isMysPost } from "../../utils/toolFunc";
import showConfirm from "../func/confirm";
import { parseLink } from "../../utils/linkParser";
import { isColorSimilar } from "../../utils/toolFunc";
import showSnackbar from "../func/snackbar";
interface TpText {
@@ -46,7 +44,6 @@ interface TpTextProps {
const props = defineProps<TpTextProps>();
const mode = ref<string>("text");
const router = useRouter();
const localEmojis = ref(localStorage.getItem("emojis"));
const emojis = ref<TpText[]>([]);
@@ -122,46 +119,17 @@ async function toLink() {
if (!props.data.attributes) return;
if (!props.data.attributes.link) return;
const link = props.data.attributes.link;
if (isMysPost(link)) {
await router.push({
name: "帖子详情",
params: {
post_id: link.split("/").pop(),
},
const res = await parseLink(link);
if (res === true) return;
if (res === false) {
showSnackbar({
text: `未知链接:${link}`,
color: "error",
timeout: 3000,
});
} else if (isMysAct(link)) {
const resOpen = await showConfirm({
title: "采用内置 JSBridge",
text: "取消则使用外部浏览器打开",
});
if (resOpen) {
const resType = await showConfirm({
title: "采用宽屏模式?",
text: "取消则使用默认竖屏",
});
if (resType) {
await TGClient.open("web_act", link);
} else {
await TGClient.open("web_act_thin", link);
}
} else {
window.open(link);
}
} else {
window.open(props.data.attributes.link);
return;
}
}
function isMysAct(url: string): boolean {
const link = new URL(url);
const prefix = ["act.mihoyo.com", "mhyurl.cn", "webstatic.mihoyo.com", "qaa.miyoushe.com"];
if (prefix.includes(link.hostname)) {
if (link.hostname == "webstatic.mihoyo.com") {
return link.pathname.includes("event");
}
return true;
}
return false;
window.open(res);
}
// 解析表情链接

View File

@@ -1,14 +1,16 @@
/**
* @file utils/TGClient.ts
* @desc 负责米游社客户端的 callback 处理
* @since Beta v0.3.7
* @since Beta v0.3.8
*/
import { event, invoke } from "@tauri-apps/api";
import type { Event } from "@tauri-apps/api/event";
import { WebviewWindow } from "@tauri-apps/api/window";
import { appWindow, WebviewWindow } from "@tauri-apps/api/window";
import { parseLink } from "./linkParser";
import { getDeviceInfo } from "./toolFunc";
import showSnackbar from "../components/func/snackbar";
import { useAppStore } from "../store/modules/app";
import { useUserStore } from "../store/modules/user";
import TGConstant from "../web/constant/TGConstant";
@@ -29,7 +31,7 @@ interface InvokeArg {
/**
* @class TGClient
* @since Beta v0.3.7
* @since Beta v0.3.8
* @description 米游社客户端
*/
class TGClient {
@@ -457,33 +459,40 @@ class TGClient {
/**
* @func pushPage
* @since Beta v0.3.7
* @since Beta v0.3.8
* @desc 打开米游社客户端的页面
* @param {unknown} payload - 请求参数
* @returns {void} - 无返回值
*/
async pushPage(payload: any): Promise<void> {
const url: string = payload.page;
if (url.startsWith("mihoyobbs://article/")) {
const urlBBS = url.replace("mihoyobbs://article/", "https://m.miyoushe.com/ys/#/article/");
await this.pushPage({ page: urlBBS });
return;
} else if (url.startsWith("mihoyobbs://webview?link=")) {
const urlWv = url.replace("mihoyobbs://webview?link=", "");
// 解析经过编码作为参数的链接
const urlReal = decodeURIComponent(urlWv);
await this.pushPage({ page: urlReal });
const url = payload.page;
const res = await parseLink(url, true);
if (!res) {
await appWindow.setFocus();
showSnackbar({
text: `未知链接:${url}`,
color: "error",
timeout: 3000,
});
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, 3000);
});
await this.window?.setFocus();
return;
}
this.route.push(url);
console.log(`[pushPage] ${url}`);
if (typeof res !== "string") return;
this.route.push(res);
console.log(`[pushPage] ${res}`);
const executeJS = `javascript:(function(){
window.location.href = '${url}';
window.location.href = '${res}';
})();`;
await invoke("execute_js", { label: "mhy_client", js: executeJS });
await this.loadJSBridge();
await this.hideSideBar();
await this.hideOverlay();
await this.window?.setFocus();
}
/**

74
src/utils/linkParser.ts Normal file
View File

@@ -0,0 +1,74 @@
/**
* @file src/utils/linkParser.ts
* @description 处理链接
* @since Beta v0.3.8
*/
import TGClient from "./TGClient";
import { createPost } from "./TGWindow";
import showConfirm from "../components/func/confirm";
/**
* @function parseLink
* @description 处理链接
* @param {string} link - 链接
* @param {boolean} useInner - 是否采用内置 JSBridge 打开
* @returns {Promise<boolean|string>} - 处理情况,或者转换后的链接
*/
export async function parseLink(
link: string,
useInner: boolean = false,
): Promise<boolean | string> {
console.warn("parseLink", link);
const url = new URL(link);
if (url.protocol !== "https:") {
if (url.protocol === "mihoyobbs:") {
if (url.pathname.startsWith("//article/")) {
const postId = url.pathname.split("/").pop();
if (!postId) return false;
createPost(postId);
return true;
}
if (url.pathname === "//webview" && url.search.startsWith("?link=")) {
return decodeURIComponent(url.search.replace("?link=", ""));
}
}
return false;
}
if (url.hostname === "bbs.mihoyo.com" || url.hostname === "www.miyoushe.com") {
if (url.pathname.includes("/article/")) {
const postId = url.pathname.split("/").pop();
if (typeof postId !== "string") return false;
createPost(postId);
return true;
}
}
const prefix = [
"m.miyoushe.com",
"act.mihoyo.com",
"mhyurl.cn",
"webstatic.mihoyo.com",
"bbs.mihoyo.com",
"qaa.miyoushe.com",
];
if (prefix.includes(url.hostname)) {
if (!useInner) {
const openCheck = await showConfirm({
title: "采用内置 JSBridge",
text: "取消则使用外部浏览器打开",
});
if (!openCheck) return url.href;
const typeCheck = await showConfirm({
title: "采用宽屏模式?",
text: "取消则使用默认竖屏",
});
if (typeCheck) {
await TGClient.open("web_act", link);
} else {
await TGClient.open("web_act_thin", link);
}
return true;
}
}
return url.href.toString();
}

View File

@@ -1,7 +1,7 @@
/**
* @file utils/toolFunc.ts
* @description 一些工具函数
* @since Beta v0.3.6
* @since Beta v0.3.8
*/
import { os, path } from "@tauri-apps/api";
@@ -177,15 +177,3 @@ export function isColorSimilar(colorBg: string, colorText: string): boolean {
: colorConvert.keyword.hex(<KEYWORD>colorText);
return score(hexText, hexBg) === "Fail";
}
/**
* @description 判断是否为 Mys 帖子
* @since Beta v0.3.7
* @param {string} url - 网址
* @returns {boolean} 是否为 Mys 帖子
*/
export function isMysPost(url: string): boolean {
const regBBS = /^https:\/\/bbs\.mihoyo\.com\/\w+\/article\/\d+$/;
const regMys = /^https:\/\/www\.miyoushe\.com\/\w+\/article\/\d+$/;
return regBBS.test(url) || regMys.test(url);
}