完成深渊数据渲染

This commit is contained in:
BTMuli
2023-06-02 16:37:41 +08:00
parent 13e565612e
commit bb2fe8cf46
10 changed files with 496 additions and 44 deletions

BIN
public/icon/star/Abyss.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,30 @@
<template>
<TItemBox :data="character as Record<string,string|number>" size="70px" display="inner" model-value="abyss-detail" />
</template>
<script lang="ts" setup>
// vue
import { onMounted, ref } from "vue";
import TItemBox from "../main/t-itembox.vue";
// utils
import TGSqlite from "../../plugins/Sqlite";
interface TibAbyssDetailProps {
modelValue: TGApp.Sqlite.Abyss.CharacterInfo
}
export interface TibAbyssDetailAvatar extends TGApp.Sqlite.Character.AppData {
value: number,
}
const props = defineProps<TibAbyssDetailProps>();
const character = ref({} as TibAbyssDetailAvatar);
onMounted(async () => {
const res = await TGSqlite.getAppCharacter(props.modelValue.id);
character.value = {
...res,
value: props.modelValue.level,
} as TibAbyssDetailAvatar;
});
</script>

View File

@@ -0,0 +1,30 @@
<template>
<TItemBox :data="character as Record<string,string|number>" size="80px" model-value="abyss-overview" display="inner" />
</template>
<script lang="ts" setup>
// vue
import { onMounted, ref } from "vue";
import TItemBox from "../main/t-itembox.vue";
// utils
import TGSqlite from "../../plugins/Sqlite";
interface TibAbyssOverviewProps {
modelValue: TGApp.Sqlite.Abyss.Character;
}
export interface TibAbyssOverviewAvatar extends TGApp.Sqlite.Character.AppData {
value: number,
}
const props = defineProps<TibAbyssOverviewProps>();
const character = ref({} as TibAbyssOverviewAvatar);
onMounted(async () => {
const res = await TGSqlite.getAppCharacter(props.modelValue.id);
character.value = {
...res,
value: props.modelValue.value,
} as TibAbyssOverviewAvatar;
});
</script>

View File

@@ -39,6 +39,9 @@
<script lang="ts" setup> <script lang="ts" setup>
// vue // vue
import { computed, ComputedRef } from "vue"; import { computed, ComputedRef } from "vue";
// types
import { TibAbyssOverviewAvatar } from "../itembox/tib-abyss-overview.vue";
import { TibAbyssDetailAvatar } from "../itembox/tib-abyss-detail.vue";
interface TItemBoxProps { interface TItemBoxProps {
modelValue: string modelValue: string
@@ -60,12 +63,8 @@ interface TItemBoxCard {
const props = defineProps<TItemBoxProps>(); const props = defineProps<TItemBoxProps>();
const getSize = computed(() => {
return props.size === "100px" ? "30px" : "40px";
});
const getHeight = computed(() => { const getHeight = computed(() => {
return props.display === "inner" ? props.size : `${props.size.slice(0, -2) + 20}px`; return props.display === "inner" ? props.size : `${Number(props.size.slice(0, -2)) + 20}px`;
}); });
const card: ComputedRef<TItemBoxCard> = computed(() => { const card: ComputedRef<TItemBoxCard> = computed(() => {
@@ -105,6 +104,22 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
lt: cardData.weaponIcon, lt: cardData.weaponIcon,
innerText: cardData.name, innerText: cardData.name,
} as TItemBoxCard; } as TItemBoxCard;
case "abyss-overview":
cardData = props.data as TibAbyssOverviewAvatar;
return {
bg: `/icon/bg/${cardData.star}-Star.webp`,
icon: `/WIKI/character/icon/${cardData.id}.webp`,
lt: `/icon/element/${cardData.element}元素.webp`,
innerText: cardData.value,
} as TItemBoxCard;
case "abyss-detail":
cardData = props.data as TibAbyssDetailAvatar;
return {
bg: `/icon/bg/${cardData.star}-Star.webp`,
icon: `/WIKI/character/icon/${cardData.id}.webp`,
lt: `/icon/element/${cardData.element}元素.webp`,
innerText: `Lv.${cardData.value}`,
} as TItemBoxCard;
} }
}); });
@@ -128,8 +143,8 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
} }
.tib-bg img { .tib-bg img {
width: 100%; width: v-bind(size);
height: 100%; height: v-bind(size);
object-fit: cover; object-fit: cover;
} }
@@ -142,8 +157,8 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
} }
.tib-icon img { .tib-icon img {
width: 100%; width: v-bind(size);
height: 100%; height: v-bind(size);
object-fit: cover; object-fit: cover;
} }
@@ -164,16 +179,16 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: v-bind(getSize); width: 30px;
height: v-bind(getSize); height: 30px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.tib-lt img { .tib-lt img {
width: calc(v-bind(getSize) - 10px); width: 20px;
height: calc(v-bind(getSize) - 10px); height: 20px;
object-fit: cover; object-fit: cover;
} }
@@ -182,7 +197,7 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: v-bind(getSize); height: 20px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@@ -190,14 +205,31 @@ const card: ComputedRef<TItemBoxCard> = computed(() => {
border-bottom-left-radius: 5px; border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
color: #fff; color: #fff;
font-size: calc(v-bind(getSize) / 3); font-size: 8px;
text-shadow: 0 0 5px #000; text-shadow: 0 0 5px #000;
font-family: Genshin, serif; font-family: Genshin, serif;
} }
.tib-inner img { .tib-inner img {
width: calc(v-bind(getSize) / 1.5); width: 20px;
height: calc(v-bind(getSize) / 1.5); height: 20px;
margin-right: 5px; margin-right: 5px;
} }
.tib-outer {
position: absolute;
bottom: 0;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
width: 100%;
height: 20px;
background: rgb(0 0 0/ 20%);
display: flex;
justify-content: center;
align-items: center;
font-family: Genshin, serif;
color: #fff;
font-size: 8px;
text-shadow: 0 0 5px #000;
}
</style> </style>

View File

@@ -0,0 +1,35 @@
<template>
<div class="tud-db-icons-grid">
<TibAbyssDetail
v-for="avatar in props.modelValue.characters"
:key="avatar.id" :model-value="avatar"
/>
</div>
<div class="tud-db-time">
{{ props.modelValue.time }}
</div>
</template>
<script lang="ts" setup>
import TibAbyssDetail from "../itembox/tib-abyss-detail.vue";
interface TuaDetailBattleProps {
modelValue: TGApp.Sqlite.Abyss.Battle
}
const props = defineProps<TuaDetailBattleProps>();
</script>
<style lang="css" scoped>
.tud-db-icons-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
margin-bottom: 10px;
}
.tud-db-time {
width: 100%;
text-align: left;
font-size: 12px;
color: #faf7e8;
}
</style>

View File

@@ -0,0 +1,25 @@
<template>
<div class="tud-dl-divider" />
<TuaDetailTitle :val="props.modelValue.winStar" :name="`第${props.modelValue.id}间`" />
<TuaDetailBattle :model-value="props.modelValue.upBattle" />
<TuaDetailBattle :model-value="props.modelValue.downBattle" />
</template>
<script lang="ts" setup>
// vue
import TuaDetailTitle from "./tua-detail-title.vue";
import TuaDetailBattle from "./tua-detail-battle.vue";
interface TuaDetailLevelProps {
modelValue: TGApp.Sqlite.Abyss.Level;
}
const props = defineProps<TuaDetailLevelProps>();
</script>
<style lang="css" scoped>
.tud-dl-divider {
border-radius: 5px;
width: 100%;
height: 2px;
background: rgb(255 255 255 / 50%);
}
</style>

View File

@@ -0,0 +1,65 @@
<template>
<div class="tud-t-box">
<div class="tud-t-title">
<slot name="title">
<span>{{ props.name }}</span>
</slot>
</div>
<div class="tud-t-val">
<img src="/icon/star/Abyss.webp" alt="Abyss">
<slot name="val">
<span>{{ props.val }}</span>
</slot>
</div>
</div>
</template>
<script lang="ts" setup>
// vue
import { computed, ComputedRef } from "vue";
interface TuaDetailTitleProps {
name: string;
val: number;
mode: "floor" | "level";
}
const props = withDefaults(defineProps<TuaDetailTitleProps>(), {
mode: "level",
});
const getFont: ComputedRef<string> = computed(() => {
return props.mode === "level" ? "Genshin-Light, serif" : "Genshin, serif";
});
</script>
<style lang="css" scoped>
.tud-t-box {
height: 30px;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
font-family: v-bind(getFont);
}
.tud-t-title {
font-size: 20px;
color: rgb(255 255 255 / 80%);
text-shadow: 0 0 10px rgb(0 0 0 / 80%);
}
.tud-t-val {
display: flex;
align-items: center;
font-family: Genshin-Light, serif;
font-size: 20px;
color: rgb(255 255 255 / 80%);
text-shadow: #fec90b 0 0 5px;
}
.tud-t-val img {
width: 20px;
height: 20px;
object-fit: cover;
margin-right: 5px;
}
</style>

View File

@@ -0,0 +1,32 @@
<template>
<div class="tuad-box">
<TuaDetailTitle :val="props.modelValue.winStar" :name="`第${props.modelValue.id}层`" mode="floor" />
<div class="tuad-index-box">
<TuaDetailLevel v-for="level in props.modelValue.levels" :key="level.id" :model-value="level" />
</div>
</div>
</template>
<script lang="ts" setup>
import TuaDetailTitle from "./tua-detail-title.vue";
import TuaDetailLevel from "./tua-detail-level.vue";
interface TuaDetailProps {
modelValue: TGApp.Sqlite.Abyss.Floor
}
const props = defineProps<TuaDetailProps>();
</script>
<style lang="css" scoped>
.tuad-box {
width: 100%;
margin-bottom: 10px;
border-radius: 5px;
background: rgb(0 0 0 / 10%);
padding: 10px;
}
.tuad-index-box {
width: 100%;
}
</style>

View File

@@ -0,0 +1,73 @@
<template>
<div class="tuao-box">
<div class="tuao-title">
<slot name="title">
{{ props.title }}
</slot>
</div>
<div v-if="props.valText" class="tuao-val-text">
<slot name="val-text">
{{ props.valText }}
</slot>
</div>
<div v-if="props.valIcons" class="tuao-val-icons">
<slot name="val-icons">
<TibAbyssOverview
v-for="avatar in JSON.parse(props.valIcons) as TGApp.Sqlite.Abyss.Character[]"
:key="avatar.id" :model-value="avatar"
/>
</slot>
</div>
</div>
</template>
<script lang="ts" setup>
// vue
import TibAbyssOverview from "../itembox/tib-abyss-overview.vue";
interface TAOProps {
title: string,
valText?: string | number,
valIcons?: string,
iconNum: number,
}
const props = withDefaults(defineProps<TAOProps>(), {
iconNum: 1,
});
</script>
<style lang="css" scoped>
.tuao-box {
width: 33%;
height: auto;
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
background: rgb(0 0 0 / 10%);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.tuao-title {
font-family: Genshin, serif;
font-size: 20px;
color: rgb(255 255 255 / 80%);
text-shadow: 0 0 10px rgb(0 0 0 / 80%);
}
.tuao-val-text {
font-family: Genshin-Light, serif;
font-size: 20px;
font-weight: bold;
margin-top: 10px;
color: rgb(255 255 255 / 80%);
text-shadow: #fec90b 0 0 5px;
}
.tuao-val-icons {
display: grid;
grid-template-columns: repeat(v-bind(iconNum), 1fr);
column-gap: 10px;
}
</style>

View File

@@ -1,29 +1,70 @@
<template> <template>
<ToLoading v-model="loading" :title="loadingTitle" /> <ToLoading v-model="loading" :title="loadingTitle" />
<v-tabs v-model="abyssTab" align-tabs="start" class="abyss-tab"> <v-tabs v-model="abyssTab" align-tabs="start" class="abyss-tab">
<v-tab value="record">
深渊统计
</v-tab>
<v-tab value="user"> <v-tab value="user">
深渊记录 深渊记录
</v-tab> </v-tab>
<v-tab value="record">
深渊统计
</v-tab>
<v-spacer />
<v-btn v-show="abyssTab==='user'" class="ua-btn" @click="getAbyssData">
<v-icon>mdi-refresh</v-icon>
<span>刷新</span>
</v-btn>
<v-btn v-show="abyssTab==='user'" class="ua-btn">
<v-icon>mdi-upload</v-icon>
<span>上传</span>
</v-btn>
</v-tabs> </v-tabs>
<v-window v-model="abyssTab"> <v-window v-model="abyssTab">
<v-window-item value="record">
<h1>胡桃深渊数据统计</h1>
</v-window-item>
<v-window-item value="user" class="user-window"> <v-window-item value="user" class="user-window">
<v-tabs v-model="userTab" direction="vertical" align-tabs="start" class="ua-tab"> <v-tabs v-model="userTab" direction="vertical" align-tabs="start" class="ua-tab">
<v-tab v-for="item in localAbyss" :key="item.id" :value="item.id" @click="toAbyss(item.id)"> <v-tab v-for="item in localAbyss" :key="item.id" :value="item.id" @click="toAbyss(item.id)">
{{ item.id }} {{ item.id }}
</v-tab> </v-tab>
</v-tabs> </v-tabs>
<v-window v-model="userTab" class="ua-window"> <v-window v-model="userTab" class="ua-window">
<v-window-item v-for="item in localAbyss" :key="item.id" :value="item.id"> <v-window-item v-for="item in localAbyss" :key="item.id" :value="item.id" class="ua-window-item">
<h1> {{ item.id }} </h1> <div class="uaw-title">
{{ JSON.stringify(curAbyss) }} <span>挑战回顾</span>
<span>更新于 {{ item.updated }}</span>
</div>
<div class="uaw-sub-title">
<img src="/src/assets/icons/arrow-right.svg" alt="character">
<span>统计周期 {{ item.startTime }} ~ {{ item.endTime }}</span>
</div>
<div class="uaw-o-box">
<TuaOverview title="战斗次数" :val-text="item.totalBattleTimes" />
<TuaOverview title="获得渊星" :val-text="item.totalStar" />
<TuaOverview title="最深抵达" :val-text="item.maxFloor" />
</div>
<div class="uaw-o-box">
<TuaOverview title="出战次数" :val-icons="item.revealRank" :icon-num="4" />
<TuaOverview title="最多击破" :val-icons="item.defeatRank" />
<TuaOverview title="最强一击" :val-icons="item.damageRank" />
</div>
<div class="uaw-o-box">
<TuaOverview title="最多承伤" :val-icons="item.takeDamageRank" />
<TuaOverview title="元素战技" :val-icons="item.normalSkillRank" />
<TuaOverview title="元素爆发" :val-icons="item.energySkillRank" />
</div>
<div class="uaw-sub-title">
<img src="/src/assets/icons/arrow-right.svg" alt="character">
<span>详情</span>
</div>
<div class="uaw-d-box">
<TuaDetail v-for="floor in JSON.parse(item.floors) as TGApp.Sqlite.Abyss.Floor[]" :model-value="floor" />
</div>
</v-window-item> </v-window-item>
</v-window> </v-window>
<div v-show="localAbyssID.length === 0" class="user-empty">
<img src="/source/UI/empty.webp" alt="empty">
<span>暂无数据请尝试刷新</span>
</div>
</v-window-item>
<v-window-item value="record">
<h1>胡桃深渊数据统计</h1>
</v-window-item> </v-window-item>
</v-window> </v-window>
</template> </template>
@@ -31,6 +72,8 @@
// vue // vue
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import ToLoading from "../../components/overlay/to-loading.vue"; import ToLoading from "../../components/overlay/to-loading.vue";
import TuaOverview from "../../components/userabyss/tua-overview.vue";
import TuaDetail from "../../components/userabyss/tua-detail.vue";
// store // store
import { useUserStore } from "../../store/modules/user"; import { useUserStore } from "../../store/modules/user";
// utils // utils
@@ -41,13 +84,11 @@ import TGSqlite from "../../plugins/Sqlite";
const userStore = useUserStore(); const userStore = useUserStore();
// loading // loading
const loading = ref(true); const loading = ref(true);
const loadAbyss = ref(false);
const loadingTitle = ref(""); const loadingTitle = ref("");
// data // data
const abyssNow = ref(true); const abyssTab = ref("user");
const abyssTab = ref(""); const userTab = ref(0);
const userTab = ref("");
const abyssCookie = ref({ const abyssCookie = ref({
cookie_token: "", cookie_token: "",
account_id: "", account_id: "",
@@ -72,21 +113,39 @@ onMounted(async () => {
ltoken: userStore.getCookieItem("ltoken"), ltoken: userStore.getCookieItem("ltoken"),
ltuid: userStore.getCookieItem("ltuid"), ltuid: userStore.getCookieItem("ltuid"),
}; };
await initAbyssData();
loading.value = false;
});
async function initAbyssData () {
localAbyss.value = await TGSqlite.getAbyss(); localAbyss.value = await TGSqlite.getAbyss();
localAbyss.value.forEach((item) => { localAbyss.value.forEach((item) => {
localAbyssID.value.push(item.id); localAbyssID.value.push(item.id);
}); });
curAbyss.value = localAbyss.value[0]; curAbyss.value = localAbyss.value[0];
loading.value = false; userTab.value = localAbyssID.value[0];
}); }
async function getAbyssData (): Promise<void> { async function getAbyssData (): Promise<void> {
loadAbyss.value = true; loadingTitle.value = "正在获取深渊数据";
const schedule = abyssNow.value ? "1" : "2"; loading.value = true;
console.log(schedule); if (localAbyssID.value.length < 2) {
const res = await TGRequest.User.byCookie.getAbyss(abyssCookie.value, schedule, user.value); loadingTitle.value = "正在获取上期深渊数据";
console.log(res); const resP = await TGRequest.User.byCookie.getAbyss(abyssCookie.value, "2", user.value);
loadAbyss.value = false; if (!resP.hasOwnProperty("retcode")) {
loadingTitle.value = "正在保存上期深渊数据";
await TGSqlite.saveAbyss(resP as TGApp.Game.Abyss.FullData);
}
}
loadingTitle.value = "正在获取本期深渊数据";
const res = await TGRequest.User.byCookie.getAbyss(abyssCookie.value, "1", user.value);
if (!res.hasOwnProperty("retcode")) {
loadingTitle.value = "正在保存本期深渊数据";
await TGSqlite.saveAbyss(res as TGApp.Game.Abyss.FullData);
}
loadingTitle.value = "正在加载深渊数据";
await initAbyssData();
loading.value = false;
} }
function toAbyss (id: number): void { function toAbyss (id: number): void {
@@ -100,6 +159,12 @@ function toAbyss (id: number): void {
color: var(--content-text-3); color: var(--content-text-3);
} }
.ua-btn {
margin-right: 5px;
background: #393b40;
color: #faf7e8;
}
.user-window { .user-window {
background: rgb(0 0 0 / 10%); background: rgb(0 0 0 / 10%);
display: flex; display: flex;
@@ -108,11 +173,20 @@ function toAbyss (id: number): void {
height: calc(100vh - 100px); height: calc(100vh - 100px);
} }
.ua-window { .user-empty {
padding: 10px; position: absolute;
width: calc(100% - 100px); top: calc(50vh - 200px);
height: 100%; left: calc(50vw - 400px);
overflow-y: auto; background: rgb(0 0 0 / 30%);
border-radius: 5px;
width: 800px;
height: 400px;
display: flex;
flex-direction: column;
align-items: center;
font-size: 1.5rem;
color: #faf7e8;
font-family: Genshin, serif;
} }
.ua-tab { .ua-tab {
@@ -121,4 +195,60 @@ function toAbyss (id: number): void {
width: 100px; width: 100px;
height: 100%; height: 100%;
} }
.ua-window {
padding: 10px;
width: calc(100% - 100px);
height: 100%;
}
.ua-window-item {
height: 100%;
padding: 10px;
overflow-y: auto;
border-radius: 5px;
box-shadow: 0 0 10px rgb(0 0 0 / 40%);
}
.uaw-title {
display: flex;
align-items: center;
justify-content: space-between;
color: rgb(255 255 255 / 80%);
text-shadow: 0 0 10px rgb(0 0 0 / 80%);
font-size: 20px;
font-family: Genshin, serif;
}
.uaw-sub-title {
background: rgb(0 0 0 / 20%);
display: flex;
align-items: center;
height: 30px;
padding: 0 10px;
margin: 5px 0;
border-radius: 5px;
font-family: Genshin-Light, serif;
color: rgb(255 255 255 / 80%);
text-shadow: 0 0 10px rgb(0 0 0 / 80%);
}
.uaw-sub-title img {
width: 20px;
height: 20px;
margin-right: 5px;
}
.uaw-o-box {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.uaw-d-box {
width: 100%;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 10px;
}
</style> </style>