mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-04-25 22:29:42 +08:00
✨ 剧诗页新增绘想游迹&月谕圣牌浮窗
This commit is contained in:
147
src/components/userCombat/tuc-ov-char.vue
Normal file
147
src/components/userCombat/tuc-ov-char.vue
Normal file
@@ -0,0 +1,147 @@
|
||||
<!-- 绘想游迹浮窗 -->
|
||||
<template>
|
||||
<TOverlay v-model="visible">
|
||||
<div v-if="props.data" :class="{ share: isShare }" class="tuc-ovc-box">
|
||||
<div class="tuc-ovc-top">
|
||||
<div class="tuc-ovc-title" @click="share()">
|
||||
<img alt="char" src="/UI/combat/charMaster.webp" />
|
||||
<span>绘想游迹</span>
|
||||
</div>
|
||||
<div class="tuc-ovc-append">
|
||||
<span>已完成</span>
|
||||
<span>{{ finish }}/{{ total }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tuc-ovc-list">
|
||||
<TucOvcItem v-for="(item, idx) in props.data" :key="idx" :item />
|
||||
</div>
|
||||
<div class="tuc-ovc-share">
|
||||
<span>UID {{ props.uid }}</span>
|
||||
<span>|</span>
|
||||
<span>TeyvatGuide v{{ version }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import gameEnum from "@enum/game.js";
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
import { generateShareImg } from "@utils/TGShare.js";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
|
||||
import TucOvcItem from "./tuc-ovc-item.vue";
|
||||
|
||||
type TucOvCharProps = { data: Array<TGApp.Game.Combat.CharMaster>; uid: string | undefined };
|
||||
|
||||
const visible = defineModel<boolean>();
|
||||
const props = defineProps<TucOvCharProps>();
|
||||
|
||||
const isShare = ref<boolean>(false);
|
||||
const version = ref<string>("");
|
||||
const finish = computed<number>(
|
||||
() => props.data.filter((i) => i.status === gameEnum.combat.charMasterStat.DONE).length,
|
||||
);
|
||||
const total = computed<number>(() => props.data.length);
|
||||
|
||||
onMounted(async () => {
|
||||
version.value = await getVersion();
|
||||
});
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const element = document.querySelector<HTMLElement>(".tuc-ovc-box");
|
||||
if (element === null) {
|
||||
showSnackbar.warn("未获取到分享内容");
|
||||
return;
|
||||
}
|
||||
const fileName = `绘想游迹_${props.uid}_${new Date().getTime()}.png`;
|
||||
await showLoading.start("正在生成分享图", fileName);
|
||||
isShare.value = true;
|
||||
await generateShareImg(fileName, element, 1.2, true);
|
||||
isShare.value = false;
|
||||
await showLoading.end();
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuc-ovc-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 800px;
|
||||
max-height: 600px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
border-radius: 8px;
|
||||
background: var(--app-page-bg);
|
||||
gap: 8px;
|
||||
|
||||
&.share {
|
||||
overflow-y: auto;
|
||||
|
||||
.tuc-ovc-list {
|
||||
overflow-y: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovc-top {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tuc-ovc-title {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 8px;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
|
||||
img {
|
||||
height: 32px;
|
||||
padding: 2px;
|
||||
border-radius: 50%;
|
||||
background: var(--tgc-od-orange);
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovc-append {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.tuc-ovc-list {
|
||||
position: relative;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
padding-right: 4px;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tuc-ovc-share {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
right: 4px;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 2px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
@@ -83,7 +83,7 @@ async function share(): Promise<void> {
|
||||
showSnackbar.error("未获取到分享内容");
|
||||
return;
|
||||
}
|
||||
const fileName = `真境剧诗_${new Date().getTime()}.png`;
|
||||
const fileName = `真境剧诗统计_${new Date().getTime()}.png`;
|
||||
await showLoading.start("正在生成分享图", fileName);
|
||||
isShare.value = true;
|
||||
await generateShareImg(fileName, element, 1.2, true);
|
||||
|
||||
129
src/components/userCombat/tuc-ov-tarot.vue
Normal file
129
src/components/userCombat/tuc-ov-tarot.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<!-- 月谕圣牌浮窗 -->
|
||||
<template>
|
||||
<TOverlay v-model="visible">
|
||||
<div v-if="data" :class="{ share: isShare }" class="tuc-ovt-box">
|
||||
<div class="tuc-ovt-top">
|
||||
<div class="tuc-ovt-title" @click="share()">月谕圣牌</div>
|
||||
<div class="tuc-ovt-append">
|
||||
<span>已解锁:</span>
|
||||
<span>{{ finish }}/{{ total }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tuc-ovt-list">
|
||||
<TucOvtItem v-for="(item, index) in data.list" :key="index" :item />
|
||||
</div>
|
||||
<div class="tuc-ovt-share">
|
||||
<span>UID {{ props.uid }}</span>
|
||||
<span>|</span>
|
||||
<span>TeyvatGuide v{{ version }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</TOverlay>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import TOverlay from "@comp/app/t-overlay.vue";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import TucOvtItem from "@comp/userCombat/tuc-ovt-item.vue";
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
import { generateShareImg } from "@utils/TGShare.js";
|
||||
import { computed, nextTick, onMounted, ref } from "vue";
|
||||
|
||||
type TucOvTarotProps = { data: TGApp.Game.Combat.TarotState | undefined; uid: string | undefined };
|
||||
|
||||
const visible = defineModel<boolean>();
|
||||
const props = defineProps<TucOvTarotProps>();
|
||||
|
||||
const isShare = ref<boolean>(false);
|
||||
const version = ref<string>("");
|
||||
const finish = computed<number>(() => props.data?.curr_num ?? 0);
|
||||
const total = computed(() => props.data?.total_num ?? 22);
|
||||
|
||||
onMounted(async () => {
|
||||
version.value = await getVersion();
|
||||
});
|
||||
|
||||
async function share(): Promise<void> {
|
||||
const element = document.querySelector<HTMLElement>(".tuc-ovt-box");
|
||||
if (element === null) {
|
||||
showSnackbar.warn("未获取到分享内容");
|
||||
return;
|
||||
}
|
||||
const fileName = `月谕圣牌_${props.uid}_${new Date().getTime()}.png`;
|
||||
await showLoading.start("正在生成分享图", fileName);
|
||||
isShare.value = true;
|
||||
await nextTick();
|
||||
await generateShareImg(fileName, element, 1.2, true);
|
||||
isShare.value = false;
|
||||
await showLoading.end();
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuc-ovt-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 800px;
|
||||
max-height: 600px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--common-shadow-2);
|
||||
border-radius: 4px;
|
||||
background: var(--app-page-bg);
|
||||
gap: 8px;
|
||||
|
||||
&.share {
|
||||
overflow-y: auto;
|
||||
|
||||
.tuc-ovt-list {
|
||||
overflow-y: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovt-top {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tuc-ovt-title {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.tuc-ovt-append {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 8px;
|
||||
}
|
||||
|
||||
.tuc-ovt-list {
|
||||
position: relative;
|
||||
display: grid;
|
||||
width: 100%;
|
||||
padding-right: 4px;
|
||||
gap: 16px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tuc-ovt-share {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
right: 4px;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
column-gap: 2px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
99
src/components/userCombat/tuc-ovc-item.vue
Normal file
99
src/components/userCombat/tuc-ovc-item.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<!-- 绘想游迹项 -->
|
||||
<template>
|
||||
<div
|
||||
:class="{ locked: props.item.status === gameEnum.combat.charMasterStat.LOCK }"
|
||||
class="tuc-ovci-box"
|
||||
>
|
||||
<img alt="bg" class="tuc-ovci-bg" src="/UI/combat/charBg.webp" />
|
||||
<img :src="props.item.icon" alt="icon" class="tuc-ovci-icon" />
|
||||
<img alt="front" class="tuc-ovci-front" src="/UI/combat/charFront.webp" />
|
||||
<div class="tuc-ovci-stat">
|
||||
<template v-if="props.item.status === gameEnum.combat.charMasterStat.DONE">
|
||||
<img alt="finish" src="/UI/combat/charFinish.webp" />
|
||||
</template>
|
||||
<template v-if="props.item.status === gameEnum.combat.charMasterStat.LOCK">
|
||||
<img alt="finish" src="/UI/combat/charLock.webp" />
|
||||
</template>
|
||||
</div>
|
||||
<span class="tuc-ovci-title">{{ props.item.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import gameEnum from "@enum/game.js";
|
||||
|
||||
type TucOvcItemProps = { item: TGApp.Game.Combat.CharMaster };
|
||||
const props = defineProps<TucOvcItemProps>();
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuc-ovci-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 100%;
|
||||
aspect-ratio: 327 / 600;
|
||||
|
||||
&.locked {
|
||||
.tuc-ovci-icon {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovci-bg {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tuc-ovci-icon {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 3%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.tuc-ovci-front {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tuc-ovci-stat {
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 30%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovci-title {
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
color: #a67754;
|
||||
font-family: var(--font-title);
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
41
src/components/userCombat/tuc-ovt-item.vue
Normal file
41
src/components/userCombat/tuc-ovt-item.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<!-- 月谕圣牌项 -->
|
||||
<template>
|
||||
<div class="tuc-ovti-box" @click="console.log(props.item)">
|
||||
<div class="tuc-ovti-icon">
|
||||
<img v-if="!props.item.is_unlock" alt="lock" src="/UI/combat/tarotDefault.webp" />
|
||||
<img v-else :alt="props.item.name" :src="props.item.icon" />
|
||||
</div>
|
||||
<div class="tuc-ovti-name">{{ props.item.name }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
type TucOvtItemProps = { item: TGApp.Game.Combat.TarotCard };
|
||||
|
||||
const props = defineProps<TucOvtItemProps>();
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tuc-ovti-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
row-gap: 12px;
|
||||
}
|
||||
|
||||
.tuc-ovti-icon {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
flex-shrink: 0;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.tuc-ovti-name {
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user