mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-12 09:18:14 +08:00
♻️ 基础组件封装
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tgn-container">
|
<div class="tgn-container">
|
||||||
<div v-for="navItem in nav" :key="navItem.id" class="tgn-nav" @click="toNav(navItem)">
|
<div v-for="navItem in nav" :key="navItem.id" class="tgn-nav" @click="toNav(navItem)">
|
||||||
<img alt="navIcon" :src="navItem.icon" />
|
<TMiImg alt="navIcon" :src="navItem.icon" :ori="true" />
|
||||||
<span>{{ navItem.name }}</span>
|
<span>{{ navItem.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="props.modelValue === 2 && hasNav" class="tgn-nav">
|
<div v-if="props.modelValue === 2 && hasNav" class="tgn-nav">
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import showDialog from "@comp/func/dialog.js";
|
import showDialog from "@comp/func/dialog.js";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import Mys from "@Mys/index.js";
|
import Mys from "@Mys/index.js";
|
||||||
|
|||||||
42
src/components/app/t-mi-img.vue
Normal file
42
src/components/app/t-mi-img.vue
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<img
|
||||||
|
:src="localUrl"
|
||||||
|
:alt="props.alt"
|
||||||
|
:title="props.title"
|
||||||
|
v-if="localUrl"
|
||||||
|
@click="emits('click')"
|
||||||
|
:class="props.class"
|
||||||
|
/>
|
||||||
|
<v-progress-circular v-else indeterminate color="primary" size="25" />
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, onUnmounted, ref } from "vue";
|
||||||
|
|
||||||
|
import { useAppStore } from "@/store/modules/app.js";
|
||||||
|
import { saveImgLocal } from "@/utils/TGShare.js";
|
||||||
|
|
||||||
|
type TMiImgProps = {
|
||||||
|
src: string;
|
||||||
|
alt: string;
|
||||||
|
title?: string;
|
||||||
|
class?: string;
|
||||||
|
ori?: boolean;
|
||||||
|
};
|
||||||
|
type TMiImgEmits = {
|
||||||
|
(e: "click"): void;
|
||||||
|
};
|
||||||
|
const props = defineProps<TMiImgProps>();
|
||||||
|
const emits = defineEmits<TMiImgEmits>();
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const localUrl = ref<string>();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const link = props.ori ? props.src : appStore.getImageUrl(props.src);
|
||||||
|
localUrl.value = await saveImgLocal(link);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -1,13 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div :id="`anno_card_${props.modelValue.id}`" class="anno-card">
|
<div :id="`anno_card_${props.modelValue.id}`" class="anno-card">
|
||||||
<div class="anno-cover" :title="props.modelValue.title" @click="createAnno">
|
<div class="anno-cover" :title="props.modelValue.title" @click="createAnno">
|
||||||
<img :src="localBanner" alt="cover" v-if="localBanner" />
|
<TMiImg :src="props.modelValue.banner" alt="cover" :ori="true" />
|
||||||
<v-progress-circular
|
|
||||||
color="primary"
|
|
||||||
:indeterminate="true"
|
|
||||||
v-else-if="props.modelValue.banner !== ''"
|
|
||||||
/>
|
|
||||||
<img src="/source/UI/defaultCover.webp" alt="cover" v-else />
|
|
||||||
<div class="anno-info">
|
<div class="anno-info">
|
||||||
<div class="anno-time">
|
<div class="anno-time">
|
||||||
<v-icon>mdi-clock-time-four-outline</v-icon>
|
<v-icon>mdi-clock-time-four-outline</v-icon>
|
||||||
@@ -19,55 +13,22 @@
|
|||||||
{{ parseTitle(props.modelValue.subtitle) }}
|
{{ parseTitle(props.modelValue.subtitle) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="anno-label" :title="`标签:${props.modelValue.tagLabel}`">
|
<div class="anno-label" :title="`标签:${props.modelValue.tagLabel}`">
|
||||||
<img :src="localTag" alt="tag" v-if="localTag" />
|
<TMiImg :src="props.modelValue.tagIcon" alt="tag" :ori="true" />
|
||||||
<v-icon v-else>mdi-tag</v-icon>
|
|
||||||
<span>{{ props.modelValue.tagLabel }}</span>
|
<span>{{ props.modelValue.tagLabel }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="anno-id">{{ props.modelValue.id }}</div>
|
<div class="anno-id">{{ props.modelValue.id }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
|
||||||
|
|
||||||
import TGLogger from "@/utils/TGLogger.js";
|
import TGLogger from "@/utils/TGLogger.js";
|
||||||
import { generateShareImg, saveImgLocal } from "@/utils/TGShare.js";
|
import { generateShareImg } from "@/utils/TGShare.js";
|
||||||
import { createTGWindow } from "@/utils/TGWindow.js";
|
import { createTGWindow } from "@/utils/TGWindow.js";
|
||||||
|
|
||||||
type TAnnoCardProps = { region: string; modelValue: TGApp.App.Announcement.ListCard; lang: string };
|
type TAnnoCardProps = { region: string; modelValue: TGApp.App.Announcement.ListCard; lang: string };
|
||||||
const props = defineProps<TAnnoCardProps>();
|
const props = defineProps<TAnnoCardProps>();
|
||||||
const localBanner = ref<string>();
|
|
||||||
const localTag = ref<string>();
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
if (props.modelValue.banner !== "") {
|
|
||||||
localBanner.value = await saveImgLocal(props.modelValue.banner);
|
|
||||||
}
|
|
||||||
localTag.value = await saveImgLocal(props.modelValue.tagIcon);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
async () => {
|
|
||||||
if (localBanner.value && localBanner.value.startsWith("blob:")) {
|
|
||||||
URL.revokeObjectURL(localBanner.value);
|
|
||||||
localBanner.value = undefined;
|
|
||||||
}
|
|
||||||
if (props.modelValue.banner !== "") {
|
|
||||||
localBanner.value = await saveImgLocal(props.modelValue.banner);
|
|
||||||
}
|
|
||||||
if (localTag.value && localTag.value.startsWith("blob:")) {
|
|
||||||
URL.revokeObjectURL(localTag.value);
|
|
||||||
localTag.value = undefined;
|
|
||||||
}
|
|
||||||
localTag.value = await saveImgLocal(props.modelValue.tagIcon);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (localBanner.value) URL.revokeObjectURL(localBanner.value);
|
|
||||||
if (localTag.value) URL.revokeObjectURL(localTag.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
function parseTitle(title: string): string {
|
function parseTitle(title: string): string {
|
||||||
const dom = new DOMParser().parseFromString(title, "text/html");
|
const dom = new DOMParser().parseFromString(title, "text/html");
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
<TOverlay v-model="visible" blur-val="5px">
|
<TOverlay v-model="visible" blur-val="5px">
|
||||||
<div class="toab-container" v-if="props.data">
|
<div class="toab-container" v-if="props.data">
|
||||||
<div class="toab-img">
|
<div class="toab-img">
|
||||||
<img :src="props.data.take_picture[Number(props.choice)]" alt="顶部图像" />
|
<TMiImg :ori="true" :src="props.data.take_picture[Number(props.choice)]" alt="顶部图像" />
|
||||||
<div class="toab-dialog" v-show="showText">
|
<div class="toab-dialog" v-show="showText">
|
||||||
<div v-for="(item, index) in textParse" :key="index" class="toab-dialog-item">
|
<div v-for="(item, index) in textParse" :key="index" class="toab-dialog-item">
|
||||||
<div class="toab-dialog-item-icon" v-if="item.icon" :title="item.name">
|
<div class="toab-dialog-item-icon" v-if="item.icon" :title="item.name">
|
||||||
<img :src="item.icon" alt="对白头像" />
|
<TMiImg :src="item.icon" alt="对白头像" :ori="true" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="item.name !== '未知'" class="toab-dialog-item-name">
|
<div v-else-if="item.name !== '未知'" class="toab-dialog-item-name">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
</TOverlay>
|
</TOverlay>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import TOverlay from "@comp/app/t-overlay.vue";
|
import TOverlay from "@comp/app/t-overlay.vue";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import { fetch } from "@tauri-apps/plugin-http";
|
import { fetch } from "@tauri-apps/plugin-http";
|
||||||
|
|||||||
@@ -6,20 +6,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="tcb-top-active" v-else>
|
<div class="tcb-top-active" v-else>
|
||||||
<span>今天是</span>
|
<span>今天是</span>
|
||||||
<img
|
<TMiImg
|
||||||
v-for="i in cur"
|
v-for="i in cur"
|
||||||
:key="i.role_id"
|
:key="i.role_id"
|
||||||
class="tcb-cur"
|
class="tcb-cur"
|
||||||
:alt="i.name"
|
:alt="i.name"
|
||||||
:src="i.head_icon"
|
:src="i.head_icon"
|
||||||
:title="i.name"
|
:title="i.name"
|
||||||
|
:ori="true"
|
||||||
/>
|
/>
|
||||||
<span>的生日哦~</span>
|
<span>的生日哦~</span>
|
||||||
<img @click="toBirth(true)" src="/source/UI/act_birthday.png" alt="empty" class="active" />
|
<img @click="toBirth(true)" src="/source/UI/act_birthday.png" alt="empty" class="active" />
|
||||||
</div>
|
</div>
|
||||||
<div>即将到来:{{ next[0].role_birthday }}</div>
|
<div>即将到来:{{ next[0].role_birthday }}</div>
|
||||||
<div v-for="i in next" :key="i.role_id" class="tcb-item">
|
<div v-for="i in next" :key="i.role_id" class="tcb-item">
|
||||||
<img :src="i.head_icon" :alt="i.name" @click="toBirth(i)" :title="i.name" />
|
<TMiImg :src="i.head_icon" :alt="i.name" @click="toBirth(i)" :title="i.name" :ori="true" />
|
||||||
<div class="tcb-item-info">
|
<div class="tcb-item-info">
|
||||||
<span>{{ i.name }} 所属:{{ i.belong === "" ? "未知" : i.belong }}</span>
|
<span>{{ i.name }} 所属:{{ i.belong === "" ? "未知" : i.belong }}</span>
|
||||||
<span>{{ parseDesc(i.introduce) }}</span>
|
<span>{{ parseDesc(i.introduce) }}</span>
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import TSAvatarBirth from "@Sqlite/modules/avatarBirth.js";
|
import TSAvatarBirth from "@Sqlite/modules/avatarBirth.js";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { onBeforeMount, ref, shallowRef } from "vue";
|
import { onBeforeMount, ref, shallowRef } from "vue";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<div class="pool-grid">
|
<div class="pool-grid">
|
||||||
<div v-for="pool in poolSelect" :key="pool.postId" class="pool-card">
|
<div v-for="pool in poolSelect" :key="pool.postId" class="pool-card">
|
||||||
<div class="pool-cover" @click="createPost(pool.postId, pool.title)">
|
<div class="pool-cover" @click="createPost(pool.postId, pool.title)">
|
||||||
<img :src="pool.cover" alt="cover" />
|
<TMiImg :src="pool.cover" alt="cover" :ori="true" />
|
||||||
</div>
|
</div>
|
||||||
<div class="pool-bottom">
|
<div class="pool-bottom">
|
||||||
<div class="pool-character">
|
<div class="pool-character">
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
v-if="character.info"
|
v-if="character.info"
|
||||||
:model-value="getCBox(character.info)"
|
:model-value="getCBox(character.info)"
|
||||||
/>
|
/>
|
||||||
<img v-else :src="character.icon" alt="character" />
|
<TMiImg v-else :src="character.icon" alt="character" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -56,6 +56,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TItembox, { type TItemBoxData } from "@comp/app/t-itemBox.vue";
|
import TItembox, { type TItemBoxData } from "@comp/app/t-itemBox.vue";
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import Mys from "@Mys/index.js";
|
import Mys from "@Mys/index.js";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="top">
|
<div class="top">
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div class="left" @click="openPosition(props.position)">
|
<div class="left" @click="openPosition(props.position)">
|
||||||
<img :src="props.position.icon" alt="icon" />
|
<TMiImg :src="props.position.icon" alt="icon" />
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="title">{{ props.position.title }}</div>
|
<div class="title">{{ props.position.title }}</div>
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import type { PositionItem } from "@comp/pageHome/ph-comp-position.vue";
|
import type { PositionItem } from "@comp/pageHome/ph-comp-position.vue";
|
||||||
|
|
||||||
@@ -102,6 +103,7 @@ async function openPosition(card: TGApp.Plugins.Mys.Position.RenderCard): Promis
|
|||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
background: var(--box-bg-2);
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div :title="getAuthorDesc()">{{ getAuthorDesc() }}</div>
|
<div :title="getAuthorDesc()">{{ getAuthorDesc() }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tpa-img">
|
<div class="tpa-img">
|
||||||
<img :src="props.data.avatar_url" alt="avatar" class="tpa-icon" />
|
<img :src="avatarUrl" alt="avatar" class="tpa-icon" v-if="avatarUrl" />
|
||||||
<img
|
<img
|
||||||
:src="props.data.pendant"
|
:src="props.data.pendant"
|
||||||
alt="pendant"
|
alt="pendant"
|
||||||
@@ -28,11 +28,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue";
|
import { computed, onMounted, onUnmounted, ref } from "vue";
|
||||||
|
|
||||||
|
import { useAppStore } from "@/store/modules/app.js";
|
||||||
|
import { saveImgLocal } from "@/utils/TGShare.js";
|
||||||
|
|
||||||
type TpAvatarProps = { data: TGApp.Plugins.Mys.User.Post; position: "left" | "right" };
|
type TpAvatarProps = { data: TGApp.Plugins.Mys.User.Post; position: "left" | "right" };
|
||||||
|
|
||||||
const props = defineProps<TpAvatarProps>();
|
const props = defineProps<TpAvatarProps>();
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const avatarUrl = ref<string>();
|
||||||
|
const pendantUrl = ref<string>();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
avatarUrl.value = await saveImgLocal(appStore.getImageUrl(props.data.avatar_url));
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (avatarUrl.value) URL.revokeObjectURL(avatarUrl.value);
|
||||||
|
if (pendantUrl.value) URL.revokeObjectURL(pendantUrl.value);
|
||||||
|
});
|
||||||
|
|
||||||
function getAuthorDesc(): string {
|
function getAuthorDesc(): string {
|
||||||
if (props.data.certification.label !== "") return props.data.certification.label;
|
if (props.data.certification.label !== "") return props.data.certification.label;
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tp-emo-box" title="自定义表情" v-if="localUrl !== undefined">
|
<div class="tp-emo-box" title="自定义表情">
|
||||||
<img :src="localUrl" :alt="props.data.insert.custom_emoticon.hash" />
|
<TMiImg
|
||||||
|
:src="props.data.insert.custom_emoticon.url"
|
||||||
|
:alt="props.data.insert.custom_emoticon.hash"
|
||||||
|
:ori="true"
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
class="tp-emo-info"
|
class="tp-emo-info"
|
||||||
v-if="props.data.insert.custom_emoticon.size.width > 100"
|
v-if="props.data.insert.custom_emoticon.size.width > 100"
|
||||||
@@ -10,16 +14,13 @@
|
|||||||
自定义表情
|
自定义表情
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="tp-emo-load" :title="getImageUrl()">
|
|
||||||
<v-progress-circular :indeterminate="true" color="primary" size="small" />
|
|
||||||
<span>加载中...</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import { onMounted, onUnmounted, ref, shallowRef } from "vue";
|
import { shallowRef } from "vue";
|
||||||
|
|
||||||
import { getImageBuffer, saveCanvasImg, saveImgLocal } from "@/utils/TGShare.js";
|
import { getImageBuffer, saveCanvasImg } from "@/utils/TGShare.js";
|
||||||
import { bytesToSize } from "@/utils/toolFunc.js";
|
import { bytesToSize } from "@/utils/toolFunc.js";
|
||||||
|
|
||||||
type TpCustomEmoticon = {
|
type TpCustomEmoticon = {
|
||||||
@@ -37,27 +38,10 @@ type TpCustomEmoticon = {
|
|||||||
type TpEmoticonProps = { data: TpCustomEmoticon };
|
type TpEmoticonProps = { data: TpCustomEmoticon };
|
||||||
|
|
||||||
const props = defineProps<TpEmoticonProps>();
|
const props = defineProps<TpEmoticonProps>();
|
||||||
const localUrl = ref<string>();
|
|
||||||
const buffer = shallowRef<Uint8Array | null>(null);
|
const buffer = shallowRef<Uint8Array | null>(null);
|
||||||
|
|
||||||
console.log("tp-emoticon", props.data.insert.custom_emoticon);
|
console.log("tp-emoticon", props.data.insert.custom_emoticon);
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
const link = getImageUrl();
|
|
||||||
localUrl.value = await saveImgLocal(link);
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
function getImageUrl(): string {
|
|
||||||
const img = props.data.insert.custom_emoticon.url;
|
|
||||||
const append = "?x-oss-process=image/format,png";
|
|
||||||
if (img.endsWith(".gif")) return img;
|
|
||||||
return img + append;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function download(): Promise<void> {
|
async function download(): Promise<void> {
|
||||||
const image = props.data.insert.custom_emoticon.url;
|
const image = props.data.insert.custom_emoticon.url;
|
||||||
if (buffer.value === null) buffer.value = await getImageBuffer(image);
|
if (buffer.value === null) buffer.value = await getImageBuffer(image);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tp-link-card-box">
|
<div class="tp-link-card-box">
|
||||||
<img :src="cover" alt="cover" @click="toLink()" v-if="cover" />
|
<TMiImg :src="props.data.insert.link_card.cover" alt="cover" @click="toLink()" />
|
||||||
<div class="tp-link-card-content">
|
<div class="tp-link-card-content">
|
||||||
<span>{{ props.data.insert.link_card.title }}</span>
|
<span>{{ props.data.insert.link_card.title }}</span>
|
||||||
<div v-if="props.data.insert.link_card.price" class="tp-link-card-price">
|
<div v-if="props.data.insert.link_card.price" class="tp-link-card-price">
|
||||||
@@ -11,13 +11,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import { computed, onMounted, onUnmounted, ref, toRaw } from "vue";
|
import { computed, toRaw } from "vue";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
import { useAppStore } from "@/store/modules/app.js";
|
|
||||||
import { parseLink, parsePost } from "@/utils/linkParser.js";
|
import { parseLink, parsePost } from "@/utils/linkParser.js";
|
||||||
import { saveImgLocal } from "@/utils/TGShare.js";
|
|
||||||
|
|
||||||
type TpLinkCard = {
|
type TpLinkCard = {
|
||||||
insert: {
|
insert: {
|
||||||
@@ -40,9 +39,7 @@ type TpLinkCardProps = { data: TpLinkCard };
|
|||||||
|
|
||||||
const props = defineProps<TpLinkCardProps>();
|
const props = defineProps<TpLinkCardProps>();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const appStore = useAppStore();
|
|
||||||
|
|
||||||
const cover = ref<string>();
|
|
||||||
const btnText = computed<string>(() => {
|
const btnText = computed<string>(() => {
|
||||||
if (!props.data.insert.link_card.button_text || props.data.insert.link_card.button_text === "") {
|
if (!props.data.insert.link_card.button_text || props.data.insert.link_card.button_text === "") {
|
||||||
return "详情";
|
return "详情";
|
||||||
@@ -50,15 +47,6 @@ const btnText = computed<string>(() => {
|
|||||||
return props.data.insert.link_card.button_text;
|
return props.data.insert.link_card.button_text;
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
const coverLink = appStore.getImageUrl(props.data.insert.link_card.cover);
|
|
||||||
cover.value = await saveImgLocal(coverLink);
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (cover.value) URL.revokeObjectURL(cover.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("tpLinkCard", props.data.insert.link_card.card_id, toRaw(props.data).insert.link_card);
|
console.log("tpLinkCard", props.data.insert.link_card.card_id, toRaw(props.data).insert.link_card);
|
||||||
|
|
||||||
async function toLink(): Promise<void> {
|
async function toLink(): Promise<void> {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<div class="ab-draw-grid">
|
<div class="ab-draw-grid">
|
||||||
<div v-for="item in selectedItem" :key="item.op_id" class="ab-draw">
|
<div v-for="item in selectedItem" :key="item.op_id" class="ab-draw">
|
||||||
<div class="ab-draw-cover" @click="showImg(item)">
|
<div class="ab-draw-cover" @click="showImg(item)">
|
||||||
<img :src="item.unread_picture[Number(isAether)]" :alt="item.word_text" />
|
<TMiImg :src="item.unread_picture[Number(isAether)]" :alt="item.word_text" />
|
||||||
<div class="ab-draw-hide" />
|
<div class="ab-draw-hide" />
|
||||||
<v-icon class="ab-draw-icon">mdi-magnify</v-icon>
|
<v-icon class="ab-draw-icon">mdi-magnify</v-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
<ToArcBrith v-model="showOverlay" :data="current" :choice="isAether" />
|
<ToArcBrith v-model="showOverlay" :data="current" :choice="isAether" />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import ToArcBrith from "@comp/pageArchive/to-arcBrith.vue";
|
import ToArcBrith from "@comp/pageArchive/to-arcBrith.vue";
|
||||||
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<v-app-bar>
|
<v-app-bar>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<div class="post-topic-top" v-if="topicInfo">
|
<div class="post-topic-top" v-if="topicInfo">
|
||||||
<img :src="topicInfo.topic.cover" alt="cover" />
|
<TMiImg :src="topicInfo.topic.cover" alt="cover" :ori="true" />
|
||||||
<div class="post-topic-info">
|
<div class="post-topic-info">
|
||||||
<span>{{ topicInfo.topic.name }}({{ topic }})</span>
|
<span>{{ topicInfo.topic.name }}({{ topic }})</span>
|
||||||
<span :title="topicInfo.topic.desc">{{ topicInfo.topic.desc }}</span>
|
<span :title="topicInfo.topic.desc">{{ topicInfo.topic.desc }}</span>
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import TGameNav from "@comp/app/t-gameNav.vue";
|
import TGameNav from "@comp/app/t-gameNav.vue";
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import TPostCard from "@comp/app/t-postcard.vue";
|
import TPostCard from "@comp/app/t-postcard.vue";
|
||||||
import showLoading from "@comp/func/loading.js";
|
import showLoading from "@comp/func/loading.js";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<div class="tp-post-meta">
|
<div class="tp-post-meta">
|
||||||
<div class="mpm-forum" v-if="postData.forum" @click="toForum(postData.forum)">
|
<div class="mpm-forum" v-if="postData.forum" @click="toForum(postData.forum)">
|
||||||
<img :src="getGameIcon(postData.forum.game_id)" alt="gameIcon" />
|
<img :src="getGameIcon(postData.forum.game_id)" alt="gameIcon" />
|
||||||
<img :src="postData.forum.icon" alt="forumIcon" />
|
<TMiImg :src="postData.forum.icon" alt="forumIcon" :ori="true" />
|
||||||
<span>{{ postData.forum.name }}</span>
|
<span>{{ postData.forum.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mpm-item" :title="`浏览数:${postData?.stat?.view_num}`">
|
<div class="mpm-item" :title="`浏览数:${postData?.stat?.view_num}`">
|
||||||
@@ -83,6 +83,7 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import TPinWin from "@comp/app/t-pinWin.vue";
|
import TPinWin from "@comp/app/t-pinWin.vue";
|
||||||
import TShareBtn from "@comp/app/t-shareBtn.vue";
|
import TShareBtn from "@comp/app/t-shareBtn.vue";
|
||||||
import TSwitchTheme from "@comp/app/t-switchTheme.vue";
|
import TSwitchTheme from "@comp/app/t-switchTheme.vue";
|
||||||
|
|||||||
Reference in New Issue
Block a user