🐛 修复一堆bug

This commit is contained in:
目棃
2024-09-06 11:23:19 +08:00
parent 8e995283ea
commit 599f9273e2
23 changed files with 102 additions and 492 deletions

View File

@@ -23,10 +23,10 @@ const themeGet = computed({
appStore.theme = value;
},
});
let themeListener: UnlistenFn;
let themeListener: UnlistenFn | null = null;
onMounted(() => {
themeListener = listenOnTheme();
onMounted(async () => {
themeListener = await listenOnTheme();
});
async function switchTheme(): Promise<void> {
@@ -34,14 +34,19 @@ async function switchTheme(): Promise<void> {
await event.emit("readTheme", themeGet.value);
}
function listenOnTheme(): UnlistenFn {
return event.listen("readTheme", (e: Event<string>) => {
async function listenOnTheme(): Promise<UnlistenFn> {
return await event.listen("readTheme", (e: Event<string>) => {
const theme = e.payload;
themeGet.value = theme === "default" ? "default" : "dark";
});
}
onUnmounted(() => themeListener());
onUnmounted(() => {
if (themeListener !== null) {
themeListener();
themeListener = null;
}
});
</script>
<style lang="css" scoped>
.switch-box {

View File

@@ -1,5 +1,5 @@
<template>
<TOverlay v-model="visible" hide :to-click="onCancel" blur-val="20px">
<TOverlay v-model="visible" :hide="true" :to-click="onCancel" blur-val="20px">
<div class="tolc-box">
<div class="tolc-title">兑换码</div>
<v-list-item v-for="(item, index) in props.data" :key="index">
@@ -34,10 +34,7 @@ interface ToLiveCodeProps {
type ToLiveCodeEmits = (e: "update:modelValue", value: boolean) => void;
const props = withDefaults(defineProps<ToLiveCodeProps>(), {
data: <TGApp.BBS.Navigator.CodeData[]>[],
modelValue: false,
});
const props = withDefaults(defineProps<ToLiveCodeProps>(), { modelValue: false });
const emits = defineEmits<ToLiveCodeEmits>();
const visible = computed<boolean>({

View File

@@ -2,13 +2,12 @@
<div class="tp-video-box">
<!-- todo https://socialsisteryi.github.io/bilibili-API-collect/docs/video/videostream_url.html#%E8%A7%86%E9%A2%91%E4%BC%B4%E9%9F%B3%E9%9F%B3%E8%B4%A8%E4%BB%A3%E7%A0%81 -->
<iframe
ref="videoRef"
class="tp-video-container"
data-html2canvas-ignore
:src="props.data.insert.video"
:allowfullscreen="true"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
sandbox="allow-forms allow-same-origin allow-popups allow-presentation allow-scripts"
:id="`tp-video-${props.data.insert.video}`"
>
</iframe>
<!-- todo 优化 -->
@@ -25,7 +24,7 @@
// https://artplayer.org/document/library/flv.html
// https://api.bilibili.com/x/player/playurl?avid=666064953&cid=1400018762&qn=64&otype=json
import { window as TauriWindow } from "@tauri-apps/api";
import { onBeforeMount, onMounted, ref } from "vue";
import { onBeforeMount, onMounted, onUnmounted, ref } from "vue";
import Bili from "../../plugins/Bili/index.js";
import { saveImgLocal } from "../../utils/TGShare.js";
@@ -51,7 +50,15 @@ onBeforeMount(async () => {
const url = new URL(props.data.insert.video);
const aid = url.searchParams.get("aid") ?? undefined;
const bvid = url.searchParams.get("bvid") ?? undefined;
videoData.value = await Bili.video.view(aid, bvid);
try {
videoData.value = await Bili.video.view(aid, bvid);
} catch (e) {
console.warn(e);
}
if (!videoData.value) {
console.error("videoData is null");
return;
}
const meta = videoData.value.dimension;
if (meta.width > meta.height) {
videoAspectRatio.value = meta.width / meta.height;
@@ -64,7 +71,10 @@ onMounted(async () => {
if (videoData.value && videoData.value.pic && !videoData.value.pic.startsWith("blob:")) {
videoData.value.pic = await saveImgLocal(videoData.value.pic);
}
videoRef.value?.addEventListener("fullscreenchange", async () => {
videoRef.value = <HTMLIFrameElement>(
document.getElementById(`tp-video-${props.data.insert.video}`)
);
videoRef.value.addEventListener("fullscreenchange", async () => {
if (document.fullscreenElement) {
await TauriWindow.getCurrentWindow().setFullscreen(true);
} else {
@@ -86,6 +96,12 @@ function getVideoTime(): string {
result += `${seconds.toString().padStart(2, "0")}`;
return result;
}
onUnmounted(() => {
if (videoData.value?.pic && videoData.value.pic.startsWith("blob:")) {
URL.revokeObjectURL(videoData.value.pic);
}
});
</script>
<style lang="css" scoped>
.tp-video-box {

View File

@@ -1,5 +1,5 @@
<template>
<TOverlay v-model="visible" hide :to-click="onCancel" blur-val="5px">
<TOverlay v-model="visible" :hide="true" :to-click="onCancel" blur-val="5px">
<div class="tpoc-box">
<div class="tpoc-top">
<span>{{ props.collection.collection_title }}</span>
@@ -84,7 +84,7 @@ const posts = ref<TpoCollectionItem[]>([]);
const router = useRouter();
onMounted(async () => {
const collectionPosts = await Mys.Collection.data(props.collection.collection_id);
const collectionPosts = await Mys.PostCollect(props.collection.collection_id);
const tempArr: TpoCollectionItem[] = [];
for (const postItem of collectionPosts) {
const post: TpoCollectionItem = {
@@ -92,8 +92,8 @@ onMounted(async () => {
title: postItem.post.subject,
created: postItem.post.created_at,
updated: postItem.post.updated_at,
comments: postItem.stat.reply_num,
likes: postItem.stat.like_num,
comments: postItem.stat === null ? 0 : postItem.stat.reply_num,
likes: postItem.stat === null ? 0 : postItem.stat.like_num,
};
tempArr.push(post);
}

View File

@@ -63,9 +63,9 @@ async function selectFile(): Promise<void> {
});
return;
}
filePath.value = file.path;
filePath.value = file;
try {
const data = await readTextFile(file.path);
const data = await readTextFile(file);
replyData.value = JSON.parse(data);
} catch (error) {
showSnackbar({

View File

@@ -1,260 +0,0 @@
<template>
<div class="tuc-rb-box">
<div class="tuc-rb-top">
<TItemBox v-model="avatarBox" />
<TItemBox v-model="weaponBox" />
</div>
<div class="tuc-rb-middle">
<div class="tuc-rbm-fetter">
<img src="/icon/material/105.webp" alt="fetter" />
<span>{{ props.modelValue.fetter }}</span>
</div>
<div class="tuc-rbm-other">
<span v-if="!showNameCard">
<v-icon>mdi-lock-outline</v-icon>
</span>
<span v-if="props.modelValue.costume !== '[]'">
<v-icon>mdi-tshirt-crew-outline</v-icon>
</span>
</div>
</div>
<div class="tuc-rb-bottom">
<div class="tuc-rbb-bg">
<img v-if="nameCard !== false && showNameCard" :src="nameCard" alt="nameCard" />
</div>
<div v-show="talents.length > 0" class="tuc-rbb-content">
<div v-for="talent in talents" :key="talent.pos" class="tuc-rbb-talent">
<img :src="talent.icon" alt="talent" />
<span>Lv.{{ talent.level }}</span>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref } from "vue";
import TGSqlite from "../../plugins/Sqlite/index.js";
import { saveImgLocal } from "../../utils/TGShare.js";
import TItemBox from "../main/t-itembox.vue";
interface TucRoleBoxProps {
modelValue: TGApp.Sqlite.Character.UserRole;
}
const props = defineProps<TucRoleBoxProps>();
const talents = ref<TGApp.Sqlite.Character.RoleTalent[]>([]);
const showNameCard = computed(() => {
if (props.modelValue.cid === 10000005 || props.modelValue.cid === 10000007) {
return true;
} else {
return props.modelValue.fetter === 10;
}
});
const avatarBox = computed(() => {
return {
size: "80px",
height: "100px",
ltSize: "30px",
bg: `/icon/bg/${props.modelValue.star}-Star.webp`,
icon: `/WIKI/character/${props.modelValue.cid}.webp`,
lt: `/icon/element/${props.modelValue.element}.webp`,
rt: props.modelValue.activeConstellation.toString() || "0",
rtSize: "20px",
innerText: `Lv.${props.modelValue.level}`,
innerHeight: 20,
outerText: getAvatarName(),
outerHeight: 20,
display: <const>"outer",
clickable: true,
};
});
const weaponBox = computed(() => {
const weapon = <TGApp.Sqlite.Character.RoleWeapon>JSON.parse(props.modelValue.weapon);
return {
size: "80px",
height: "100px",
ltSize: "30px",
bg: `/icon/bg/${weapon.star}-Star.webp`,
icon: `/WIKI/weapon/${weapon.id}.webp`,
lt: `/icon/weapon/${weapon.type}.webp`,
rt: weapon.affix.toString() || "0",
rtSize: "20px",
innerText: `Lv.${weapon.level}`,
innerHeight: 20,
outerText: weapon.name,
outerHeight: 20,
display: <const>"outer",
clickable: true,
};
});
const nameCard = ref<string | false>(false);
onMounted(async () => {
if (props.modelValue.cid !== 10000005 && props.modelValue.cid !== 10000007) {
const role = await TGSqlite.getAppCharacter(props.modelValue.cid);
nameCard.value = `/source/nameCard/profile/${role.nameCard}.webp`;
} else {
nameCard.value = "/source/nameCard/profile/原神·印象.webp";
}
if (props.modelValue.talent !== "" && props.modelValue.talent !== "[]") {
const talentsLocal: TGApp.Sqlite.Character.RoleTalent[] = JSON.parse(props.modelValue.talent);
talents.value = talentsLocal
.filter((talent) => talent.max === 10)
.sort((a, b) => a.pos - b.pos);
talents.value.map(async (talent) => {
talent.icon = await saveImgLocal(talent.icon);
});
} else {
console.error(props.modelValue.cid, props.modelValue.name, "天赋为空");
}
});
function getAvatarName(): string {
return props.modelValue.cid === 10000005
? "旅行者-空"
: props.modelValue.cid === 10000007
? "旅行者-荧"
: props.modelValue.name;
}
// 销毁
onUnmounted(() => {
talents.value.forEach((talent) => {
URL.revokeObjectURL(talent.icon);
});
});
</script>
<style lang="css" scoped>
.tuc-rb-box {
position: relative;
display: flex;
flex-direction: column;
padding: 5px;
border: 1px inset var(--common-shadow-2);
border-radius: 5px;
background: var(--box-bg-2);
cursor: pointer;
row-gap: 5px;
transition: all 0.3s;
}
.tuc-rb-top {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
}
.tuc-rb-middle {
display: flex;
width: 100%;
height: 30px;
align-items: center;
justify-content: space-between;
padding: 5px;
border-radius: 5px;
background: var(--box-bg-3);
font-family: var(--font-title);
font-size: 12px;
}
.tuc-rbm-fetter {
display: flex;
align-items: center;
justify-content: flex-start;
column-gap: 5px;
}
.tuc-rbm-fetter img {
width: 20px;
height: 20px;
object-fit: contain;
}
.tuc-rbm-other {
display: flex;
align-items: center;
justify-content: flex-end;
color: var(--box-text-4);
column-gap: 5px;
}
.tuc-rb-bottom {
position: relative;
width: 100%;
height: 80px;
align-items: center;
border-radius: 5px;
}
.tuc-rbb-bg {
position: absolute;
top: 0;
left: 0;
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
border-radius: 5px;
-webkit-backdrop-filter: blur(5px);
backdrop-filter: blur(5px);
background: var(--box-bg-3);
}
.tuc-rbb-bg img {
width: 100%;
height: 100%;
border-radius: 5px;
object-fit: fill;
}
.tuc-rbb-content {
position: relative;
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: space-between;
padding: 5px;
border-radius: 5px;
}
.tuc-rbb-talent {
display: flex;
width: 50px;
flex-direction: column;
align-items: center;
justify-content: flex-end;
row-gap: 5px;
}
.tuc-rbb-talent :first-child {
position: relative;
display: flex;
width: 40px;
height: 40px;
align-items: center;
justify-content: center;
padding: 5px;
border: 1px solid var(--box-bg-4);
border-radius: 50%;
background: var(--tgc-dark-7);
opacity: 0.8;
}
.tuc-rbb-talent :last-child {
display: flex;
align-items: center;
justify-content: center;
padding-right: 5px;
padding-left: 5px;
border-radius: 5px;
background: var(--box-bg-4);
color: var(--box-text-4);
font-family: var(--font-title);
font-size: 12px;
}
</style>

View File

@@ -51,7 +51,7 @@ interface TurWorldSubProps {
}
const props = defineProps<TurWorldSubProps>();
let themeListener: UnlistenFn;
let themeListener: UnlistenFn | null = null;
const bg = ref<string>();
const icon = ref<string>();
const iconLight = ref<string>();
@@ -59,7 +59,7 @@ const iconDark = ref<string>();
const offer = ref<string>();
onMounted(async () => {
themeListener = event.listen("readTheme", (e: Event<string>) => {
themeListener = await event.listen("readTheme", (e: Event<string>) => {
const theme = e.payload;
if (theme === "dark") {
icon.value = iconLight.value;
@@ -81,7 +81,10 @@ onMounted(async () => {
});
onUnmounted(() => {
themeListener();
if (themeListener !== null) {
themeListener();
themeListener = null;
}
const urlList = [iconLight.value, iconDark.value, offer.value];
urlList.forEach((url) => {
URL.revokeObjectURL(typeof url === "string" ? url : "");

View File

@@ -1,99 +0,0 @@
<template>
<v-card class="twg-box" @click="toWiki" :title.attr="props.data.name">
<img class="twg-border" src="/WIKI/GCG/bg/special.webp" alt="border" />
<img class="twg-cover" :src="props.data.icon" alt="cover" />
<div class="twg-name">
<span>{{ props.data.name }}</span>
</div>
</v-card>
</template>
<script lang="ts" setup>
import Mys from "../../plugins/Mys/index.js";
import { createTGWindow } from "../../utils/TGWindow.js";
import showSnackbar from "../func/snackbar.js";
interface TwgCardProps {
data: TGApp.App.GCG.WikiBriefInfo;
}
const props = defineProps<TwgCardProps>();
async function toWiki(): Promise<void> {
if (!props.data.contentId || props.data.contentId === 0) {
showSnackbar({
text: `卡牌 ${props.data.name} 暂无外部链接`,
color: "error",
});
return;
}
const url = Mys.Api.Obc.replace("{contentId}", props.data.contentId.toString());
await createTGWindow(
url,
"Sub_window",
`Content_${props.data.contentId} ${props.data.name}`,
1200,
800,
true,
);
}
</script>
<style lang="css" scoped>
.twg-box {
position: relative;
overflow: hidden;
width: 100%;
border-radius: 10px;
aspect-ratio: 7 / 12;
transition: all 0.3s;
}
.twg-cover {
position: absolute;
z-index: -1;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 10px;
object-fit: cover;
transition: all 0.3s;
}
.twg-box:hover .twg-cover {
transform: scale(1.2);
transition: all 0.5s;
}
.twg-border {
position: absolute;
top: 0;
left: 0;
overflow: hidden;
width: 100%;
height: 100%;
border-radius: 10px;
}
.twg-name {
position: absolute;
bottom: 0;
left: 0;
display: flex;
width: 100%;
align-items: center;
justify-content: center;
border-radius: 0 0 10px 10px;
background: rgb(0 0 0 / 50%);
color: white;
}
.twg-name span {
overflow: hidden;
margin: 0 10px;
font-size: 14px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
}
</style>