mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-12 09:18:14 +08:00
🚸 部分资源释放
This commit is contained in:
@@ -7,7 +7,9 @@
|
|||||||
@click="emits('click')"
|
@click="emits('click')"
|
||||||
:class="props.class"
|
:class="props.class"
|
||||||
/>
|
/>
|
||||||
<v-progress-circular v-else indeterminate color="primary" size="25" />
|
<div class="progress" v-else>
|
||||||
|
<v-progress-circular indeterminate color="primary" size="25" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted, ref, watch } from "vue";
|
import { onMounted, onUnmounted, ref, watch } from "vue";
|
||||||
@@ -22,9 +24,7 @@ type TMiImgProps = {
|
|||||||
class?: string;
|
class?: string;
|
||||||
ori?: boolean;
|
ori?: boolean;
|
||||||
};
|
};
|
||||||
type TMiImgEmits = {
|
type TMiImgEmits = (e: "click") => void;
|
||||||
(e: "click"): void;
|
|
||||||
};
|
|
||||||
const props = defineProps<TMiImgProps>();
|
const props = defineProps<TMiImgProps>();
|
||||||
const emits = defineEmits<TMiImgEmits>();
|
const emits = defineEmits<TMiImgEmits>();
|
||||||
|
|
||||||
@@ -42,6 +42,7 @@ watch(
|
|||||||
async () => {
|
async () => {
|
||||||
if (!props.src) return;
|
if (!props.src) return;
|
||||||
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
||||||
|
localUrl.value = undefined;
|
||||||
const link = props.ori ? props.src : appStore.getImageUrl(props.src);
|
const link = props.ori ? props.src : appStore.getImageUrl(props.src);
|
||||||
localUrl.value = await saveImgLocal(link);
|
localUrl.value = await saveImgLocal(link);
|
||||||
},
|
},
|
||||||
@@ -51,3 +52,13 @@ onUnmounted(() => {
|
|||||||
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
if (localUrl.value) URL.revokeObjectURL(localUrl.value);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.progress {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="tua-abl-skills">
|
<div class="tua-abl-skills">
|
||||||
<div v-for="skill in skills" :key="skill.skill_id" class="tua-abl-skill">
|
<div v-for="skill in skills" :key="skill.skill_id" class="tua-abl-skill">
|
||||||
<img :src="skill.icon" alt="skill" />
|
<TMiImg :ori="true" :src="skill.icon" alt="skill" />
|
||||||
<span>Lv.{{ skill.level }}</span>
|
<span>Lv.{{ skill.level }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,6 +46,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 TSUserAvatar from "@Sqlite/modules/userAvatar.js";
|
import TSUserAvatar from "@Sqlite/modules/userAvatar.js";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
class="tua-dcc-item"
|
class="tua-dcc-item"
|
||||||
:title="`${constellation.pos}命-${constellation.name}`"
|
:title="`${constellation.pos}命-${constellation.name}`"
|
||||||
>
|
>
|
||||||
<img :src="constellation.icon" alt="constellation" class="tua-dcc-icon" />
|
<TMiImg :ori="true" :src="constellation.icon" alt="constellation" class="tua-dcc-icon" />
|
||||||
<div v-if="!constellation.is_actived" class="tua-dcc-lock">
|
<div v-if="!constellation.is_actived" class="tua-dcc-lock">
|
||||||
<v-icon size="10px" color="var(--tgc-od-white)">mdi-lock</v-icon>
|
<v-icon size="10px" color="var(--tgc-od-white)">mdi-lock</v-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
|
|
||||||
type TuaDcConstellationsProps = { modelValue: Array<TGApp.Game.Avatar.Constellation> };
|
type TuaDcConstellationsProps = { modelValue: Array<TGApp.Game.Avatar.Constellation> };
|
||||||
|
|
||||||
const props = defineProps<TuaDcConstellationsProps>();
|
const props = defineProps<TuaDcConstellationsProps>();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
v-if="props.modelValue === false"
|
v-if="props.modelValue === false"
|
||||||
class="empty"
|
class="empty"
|
||||||
/>
|
/>
|
||||||
<img :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
<TMiImg :ori="true" :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tua-dcr-right">
|
<div class="tua-dcr-right">
|
||||||
@@ -59,6 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
|
||||||
import { useUserStore } from "@/store/modules/user.js";
|
import { useUserStore } from "@/store/modules/user.js";
|
||||||
@@ -188,8 +189,11 @@ function getPropSubStyle(
|
|||||||
|
|
||||||
.tua-dcr-icon {
|
.tua-dcr-icon {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
width: 36px;
|
width: 36px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
:title="skill.name"
|
:title="skill.name"
|
||||||
class="tua-dct-item"
|
class="tua-dct-item"
|
||||||
>
|
>
|
||||||
<img :src="skill.icon" alt="talent" class="tua-dct-icon" />
|
<TMiImg :ori="true" :src="skill.icon" alt="talent" class="tua-dct-icon" />
|
||||||
<div v-if="!skill.is_unlock" class="tua-dct-lock">
|
<div v-if="!skill.is_unlock" class="tua-dct-lock">
|
||||||
<v-icon size="10px" color="var(--tgc-od-white)">mdi-lock</v-icon>
|
<v-icon size="10px" color="var(--tgc-od-white)">mdi-lock</v-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
|
|
||||||
type TuaDcTalentsProps = { modelValue: Array<TGApp.Game.Avatar.Skill> };
|
type TuaDcTalentsProps = { modelValue: Array<TGApp.Game.Avatar.Skill> };
|
||||||
|
|
||||||
const props = defineProps<TuaDcTalentsProps>();
|
const props = defineProps<TuaDcTalentsProps>();
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tua-dc-container">
|
<div class="tua-dc-container">
|
||||||
<img :src="avatar" class="tua-dc-avatar" alt="avatar" />
|
<div class="tua-dc-avatar">
|
||||||
|
<TMiImg :src="props.modelValue.avatar.image" :ori="true" alt="avatar" />
|
||||||
|
</div>
|
||||||
<v-btn
|
<v-btn
|
||||||
class="tua-dc-share"
|
class="tua-dc-share"
|
||||||
prepend-icon="mdi-share-variant"
|
prepend-icon="mdi-share-variant"
|
||||||
@@ -73,9 +75,10 @@
|
|||||||
</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 TSUserAvatar from "@Sqlite/modules/userAvatar.js";
|
import TSUserAvatar from "@Sqlite/modules/userAvatar.js";
|
||||||
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
|
||||||
import TuaDcConstellations from "./tua-dc-constellations.vue";
|
import TuaDcConstellations from "./tua-dc-constellations.vue";
|
||||||
import TuaDcProp from "./tua-dc-prop.vue";
|
import TuaDcProp from "./tua-dc-prop.vue";
|
||||||
@@ -84,7 +87,7 @@ import TuaDcTalents from "./tua-dc-talents.vue";
|
|||||||
import TuaDcWeapon from "./tua-dc-weapon.vue";
|
import TuaDcWeapon from "./tua-dc-weapon.vue";
|
||||||
|
|
||||||
import { useUserStore } from "@/store/modules/user.js";
|
import { useUserStore } from "@/store/modules/user.js";
|
||||||
import { generateShareImg, saveImgLocal } from "@/utils/TGShare.js";
|
import { generateShareImg } from "@/utils/TGShare.js";
|
||||||
|
|
||||||
type fixedLenArr<T, N extends number> = [T, ...Array<T>] & { length: N };
|
type fixedLenArr<T, N extends number> = [T, ...Array<T>] & { length: N };
|
||||||
type RelicList = fixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;
|
type RelicList = fixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;
|
||||||
@@ -107,36 +110,13 @@ const propMain = computed<Array<TGApp.Game.Avatar.PropMapItem | false>>(() =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const bg = ref<string>("/WIKI/nameCard/profile/原神·印象.webp");
|
const bg = ref<string>("/WIKI/nameCard/profile/原神·印象.webp");
|
||||||
const avatar = ref<string>(props.modelValue.avatar.image);
|
|
||||||
const loading = ref<boolean>(false);
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => await loadData());
|
||||||
await loadData();
|
|
||||||
});
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (avatar.value.startsWith("blob:")) {
|
|
||||||
URL.revokeObjectURL(avatar.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
async () => {
|
|
||||||
if (avatar.value.startsWith("blob:")) {
|
|
||||||
URL.revokeObjectURL(avatar.value);
|
|
||||||
}
|
|
||||||
avatar.value = props.modelValue.avatar.image;
|
|
||||||
await loadData();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
async function loadData(): Promise<void> {
|
async function loadData(): Promise<void> {
|
||||||
const card = TSUserAvatar.getAvatarCard(props.modelValue.cid);
|
const card = TSUserAvatar.getAvatarCard(props.modelValue.cid);
|
||||||
bg.value = `url("/WIKI/nameCard/profile/${card}.webp")`;
|
bg.value = `url("/WIKI/nameCard/profile/${card}.webp")`;
|
||||||
if (!avatar.value.startsWith("blob:")) {
|
|
||||||
avatar.value = await saveImgLocal(props.modelValue.avatar.image);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function share(): Promise<void> {
|
async function share(): Promise<void> {
|
||||||
@@ -176,9 +156,18 @@ async function share(): Promise<void> {
|
|||||||
.tua-dc-avatar {
|
.tua-dc-avatar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: -80px;
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
width: 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tua-dc-rt {
|
.tua-dc-rt {
|
||||||
|
|||||||
@@ -14,11 +14,13 @@
|
|||||||
v-if="props.modelValue === false"
|
v-if="props.modelValue === false"
|
||||||
class="empty"
|
class="empty"
|
||||||
/>
|
/>
|
||||||
<img :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
<TMiImg :ori="true" :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
|
|
||||||
import { useUserStore } from "@/store/modules/user.js";
|
import { useUserStore } from "@/store/modules/user.js";
|
||||||
|
|
||||||
type TuaRelicBoxProps = { modelValue: TGApp.Game.Avatar.Relic | false; position: number };
|
type TuaRelicBoxProps = { modelValue: TGApp.Game.Avatar.Relic | false; position: number };
|
||||||
@@ -71,8 +73,11 @@ function getRelicTitle(): string {
|
|||||||
|
|
||||||
.tua-relic-icon {
|
.tua-relic-icon {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="duc-dolb-box">
|
<div class="duc-dolb-box">
|
||||||
<div
|
<div
|
||||||
v-for="constellation in constellations"
|
v-for="constellation in props.modelValue"
|
||||||
:key="constellation.pos"
|
:key="constellation.pos"
|
||||||
:title="constellation.name"
|
:title="constellation.name"
|
||||||
class="duc-dolb-item"
|
class="duc-dolb-item"
|
||||||
@@ -9,48 +9,18 @@
|
|||||||
<div v-if="!constellation.is_actived" class="duc-dolb-lock">
|
<div v-if="!constellation.is_actived" class="duc-dolb-lock">
|
||||||
<v-icon color="white">mdi-lock</v-icon>
|
<v-icon color="white">mdi-lock</v-icon>
|
||||||
</div>
|
</div>
|
||||||
<img class="duc-dolb-icon" :src="constellation.icon" alt="constellation" />
|
<div class="duc-dolb-icon">
|
||||||
|
<TMiImg :ori="true" :src="constellation.icon" alt="constellation" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted, shallowRef, watch } from "vue";
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
|
|
||||||
import { saveImgLocal } from "@/utils/TGShare.js";
|
|
||||||
|
|
||||||
type DucDetailOlbProps = { modelValue: Array<TGApp.Game.Avatar.Constellation> };
|
type DucDetailOlbProps = { modelValue: Array<TGApp.Game.Avatar.Constellation> };
|
||||||
|
|
||||||
const props = defineProps<DucDetailOlbProps>();
|
const props = defineProps<DucDetailOlbProps>();
|
||||||
const constellations = shallowRef<Array<TGApp.Game.Avatar.Constellation>>([]);
|
|
||||||
|
|
||||||
async function loadData() {
|
|
||||||
const tempConstellations = JSON.parse(JSON.stringify(props.modelValue));
|
|
||||||
for (const constellation of tempConstellations) {
|
|
||||||
if (constellation.icon.startsWith("blob:")) return;
|
|
||||||
constellation.icon = await saveImgLocal(constellation.icon);
|
|
||||||
}
|
|
||||||
constellations.value = tempConstellations;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => await loadData());
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
async () => {
|
|
||||||
for (const constellation of constellations.value) {
|
|
||||||
if (constellation.icon.startsWith("blob:")) {
|
|
||||||
URL.revokeObjectURL(constellation.icon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await loadData();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
onUnmounted(() => {
|
|
||||||
for (const constellation of constellations.value) {
|
|
||||||
if (constellation.icon.startsWith("blob:")) {
|
|
||||||
URL.revokeObjectURL(constellation.icon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.duc-dolb-box {
|
.duc-dolb-box {
|
||||||
@@ -75,6 +45,7 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
.duc-dolb-lock {
|
.duc-dolb-lock {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 54px;
|
width: 54px;
|
||||||
height: 54px;
|
height: 54px;
|
||||||
@@ -88,9 +59,20 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.duc-dolb-icon {
|
.duc-dolb-icon {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,54 +2,24 @@
|
|||||||
<div class="duc-dort-box">
|
<div class="duc-dort-box">
|
||||||
<div
|
<div
|
||||||
:title="talent.name"
|
:title="talent.name"
|
||||||
v-for="talent in talents"
|
v-for="talent in props.modelValue"
|
||||||
:key="talent.skill_id"
|
:key="talent.skill_id"
|
||||||
class="duc-dort-item"
|
class="duc-dort-item"
|
||||||
>
|
>
|
||||||
<span>{{ talent.name }}</span>
|
<span>{{ talent.name }}</span>
|
||||||
<img :src="talent.icon" alt="talent" />
|
<div class="duc-dort-icon">
|
||||||
|
<TMiImg :ori="true" :src="talent.icon" alt="talent" />
|
||||||
|
</div>
|
||||||
<span>Lv.{{ talent.level === 0 ? 1 : talent.level }}</span>
|
<span>Lv.{{ talent.level === 0 ? 1 : talent.level }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted, shallowRef, watch } from "vue";
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
|
|
||||||
import { saveImgLocal } from "@/utils/TGShare.js";
|
|
||||||
|
|
||||||
type DucDetailOrtProps = { modelValue: Array<TGApp.Game.Avatar.Skill> };
|
type DucDetailOrtProps = { modelValue: Array<TGApp.Game.Avatar.Skill> };
|
||||||
|
|
||||||
const props = defineProps<DucDetailOrtProps>();
|
const props = defineProps<DucDetailOrtProps>();
|
||||||
const talents = shallowRef<Array<TGApp.Game.Avatar.Skill>>([]);
|
|
||||||
|
|
||||||
async function loadData(): Promise<void> {
|
|
||||||
const tempTalent = JSON.parse(JSON.stringify(props.modelValue));
|
|
||||||
for (const talent of tempTalent) {
|
|
||||||
if (talent.icon.startsWith("blob:")) return;
|
|
||||||
talent.icon = await saveImgLocal(talent.icon);
|
|
||||||
}
|
|
||||||
talents.value = tempTalent;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => await loadData());
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
async () => {
|
|
||||||
for (const talent of talents.value) {
|
|
||||||
if (talent.icon.startsWith("blob:")) {
|
|
||||||
URL.revokeObjectURL(talent.icon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await loadData();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
onUnmounted(() => {
|
|
||||||
for (const talent of talents.value) {
|
|
||||||
if (talent.icon.startsWith("blob:")) {
|
|
||||||
URL.revokeObjectURL(talent.icon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="css" scoped>
|
<style lang="css" scoped>
|
||||||
.duc-dort-box {
|
.duc-dort-box {
|
||||||
@@ -61,17 +31,28 @@ onUnmounted(() => {
|
|||||||
.duc-dort-item {
|
.duc-dort-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
column-gap: 10px;
|
column-gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.duc-dort-item img {
|
.duc-dort-icon {
|
||||||
width: 40px;
|
position: relative;
|
||||||
height: 40px;
|
display: flex;
|
||||||
padding: 5px;
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 4px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
-webkit-backdrop-filter: blur(5px);
|
-webkit-backdrop-filter: blur(5px);
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: blur(5px);
|
||||||
background: rgba(0 0 0 /40%);
|
background: rgba(0 0 0 /40%);
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.duc-dort-item span {
|
.duc-dort-item span {
|
||||||
@@ -83,9 +64,4 @@ onUnmounted(() => {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
text-shadow: 0 0 5px rgba(0 0 0/40%);
|
text-shadow: 0 0 5px rgba(0 0 0/40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.duc-dort-item :nth-last-child(1) {
|
|
||||||
width: 48px;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<img :src="`/icon/bg/${props.modelValue.rarity}-Star.webp`" alt="bg" />
|
<img :src="`/icon/bg/${props.modelValue.rarity}-Star.webp`" alt="bg" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="props.modelValue" class="duc-dr-icon">
|
<div v-if="props.modelValue" class="duc-dr-icon">
|
||||||
<img :src="props.modelValue.icon" alt="relic" />
|
<TMiImg :ori="true" :src="props.modelValue.icon" alt="relic" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="props.modelValue !== false" class="duc-dr-level">
|
<div v-if="props.modelValue !== false" class="duc-dr-level">
|
||||||
{{ props.modelValue.level }}
|
{{ props.modelValue.level }}
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
|
|
||||||
type ducDetailRelicProps = { modelValue: TGApp.Game.Avatar.Relic | false; pos: number };
|
type ducDetailRelicProps = { modelValue: TGApp.Game.Avatar.Relic | false; pos: number };
|
||||||
@@ -61,8 +62,11 @@ const relicBg = computed<string>(() => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.duc-dr-icon img {
|
.duc-dr-icon img {
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tuc-dc-box">
|
<div class="tuc-dc-box">
|
||||||
<div v-if="!modelValue.is_actived" class="tuc-dc-lock">
|
<div v-if="!modelValue.is_actived" class="tuc-dc-lock">
|
||||||
<v-icon color="white"> mdi-lock </v-icon>
|
<v-icon color="white"> mdi-lock</v-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="tuc-dc-icon">
|
<div class="tuc-dc-icon">
|
||||||
<img :src="modelValue.icon" alt="constellation" />
|
<TMiImg :ori="true" :src="modelValue.icon" alt="constellation" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
|
|
||||||
defineProps<{ modelValue: TGApp.Game.Avatar.Constellation }>();
|
defineProps<{ modelValue: TGApp.Game.Avatar.Constellation }>();
|
||||||
</script>
|
</script>
|
||||||
<style lang="css" scoped>
|
<style lang="css" scoped>
|
||||||
@@ -34,8 +36,11 @@ defineProps<{ modelValue: TGApp.Game.Avatar.Constellation }>();
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tuc-dc-icon {
|
.tuc-dc-icon {
|
||||||
|
display: flex;
|
||||||
width: 54px;
|
width: 54px;
|
||||||
height: 54px;
|
height: 54px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
border: 1px solid rgb(0 0 0/20%);
|
border: 1px solid rgb(0 0 0/20%);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="tuc-do-box">
|
<div class="tuc-do-box">
|
||||||
<img :src="bg" alt="role" class="tuc-do-bg" />
|
<div class="tuc-do-bg">
|
||||||
|
<TMiImg :ori="true" :src="bg" alt="role" />
|
||||||
|
</div>
|
||||||
<div class="tuc-do-show">
|
<div class="tuc-do-show">
|
||||||
<div class="tuc-do-main">
|
<div class="tuc-do-main">
|
||||||
<div class="tuc-do-left">
|
<div class="tuc-do-left">
|
||||||
@@ -72,6 +74,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
||||||
|
|
||||||
import TucDetailConstellation from "./tuc-detail-constellation.vue";
|
import TucDetailConstellation from "./tuc-detail-constellation.vue";
|
||||||
@@ -160,12 +163,21 @@ function switchBg(): void {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
object-fit: v-bind(bgFit);
|
object-fit: v-bind(bgFit);
|
||||||
transform: translateY(v-bind(bgTransY));
|
transform: translateY(v-bind(bgTransY));
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tuc-do-costume {
|
.tuc-do-costume {
|
||||||
|
|||||||
@@ -7,11 +7,13 @@
|
|||||||
<img :src="`/icon/bg/${modelValue.rarity}-Star.webp`" alt="bg" />
|
<img :src="`/icon/bg/${modelValue.rarity}-Star.webp`" alt="bg" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="modelValue" class="tuc-dr-icon">
|
<div v-if="modelValue" class="tuc-dr-icon">
|
||||||
<img :src="modelValue.icon" alt="relic" />
|
<TMiImg :ori="true" :src="modelValue.icon" alt="relic" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
|
|
||||||
defineProps<{ modelValue: TGApp.Game.Avatar.Relic | false; pos: number }>();
|
defineProps<{ modelValue: TGApp.Game.Avatar.Relic | false; pos: number }>();
|
||||||
</script>
|
</script>
|
||||||
<style lang="css" scoped>
|
<style lang="css" scoped>
|
||||||
@@ -45,8 +47,11 @@ defineProps<{ modelValue: TGApp.Game.Avatar.Relic | false; pos: number }>();
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tuc-dr-icon img {
|
.tuc-dr-icon img {
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
<div class="tp-avatar-box">
|
<div class="tp-avatar-box">
|
||||||
<div v-if="props.position === 'right'" class="tpa-text">
|
<div v-if="props.position === 'right'" class="tpa-text">
|
||||||
<div>{{ props.data.nickname }}</div>
|
<div>{{ props.data.nickname }}</div>
|
||||||
<div :title="getAuthorDesc()">{{ getAuthorDesc() }}</div>
|
<div :title="authorDesc">{{ authorDesc }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tpa-img">
|
<div class="tpa-img">
|
||||||
<img :src="avatarUrl" alt="avatar" class="tpa-icon" v-if="avatarUrl" />
|
<TMiImg :ori="true" :src="props.data.avatar_url" alt="avatar" class="tpa-icon" />
|
||||||
<img
|
<TMiImg
|
||||||
|
:ori="true"
|
||||||
:src="props.data.pendant"
|
:src="props.data.pendant"
|
||||||
alt="pendant"
|
alt="pendant"
|
||||||
class="tpa-pendant"
|
class="tpa-pendant"
|
||||||
@@ -23,36 +24,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="props.position === 'left'" class="tpa-text">
|
<div v-if="props.position === 'left'" class="tpa-text">
|
||||||
<div>{{ props.data.nickname }}</div>
|
<div>{{ props.data.nickname }}</div>
|
||||||
<div :title="getAuthorDesc()">{{ getAuthorDesc() }}</div>
|
<div :title="authorDesc">{{ authorDesc }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onMounted, onUnmounted, ref } from "vue";
|
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||||
|
import { computed } 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 () => {
|
const authorDesc = computed<string>(() => {
|
||||||
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 {
|
|
||||||
if (props.data.certification.label !== "") return props.data.certification.label;
|
if (props.data.certification.label !== "") return props.data.certification.label;
|
||||||
return props.data.introduce;
|
return props.data.introduce;
|
||||||
}
|
});
|
||||||
|
|
||||||
const levelColor = computed<string>(() => {
|
const levelColor = computed<string>(() => {
|
||||||
const level = props.data.level_exp.level;
|
const level = props.data.level_exp.level;
|
||||||
|
|||||||
Reference in New Issue
Block a user