💄 调整布局

This commit is contained in:
目棃
2024-08-17 11:58:47 +08:00
parent a109588326
commit 2f41679546
3 changed files with 280 additions and 258 deletions

View File

@@ -1,69 +1,48 @@
<template>
<div class="tua-ab-box">
<!-- 左侧角色武器天赋好感衣装名片 -->
<div class="tua-ab-left">
<div class="tua-abl-top">
<TItembox v-model="avatarBox" />
<TItembox v-model="weaponBox" />
</div>
<div class="tua-abl-mid">
<div class="tua-abl-fetter">
<img src="/icon/material/105.webp" alt="fetter" />
<span>{{ props.modelValue.avatar.fetter }}</span>
</div>
<div class="tua-abl-other">
<span v-if="!isFetterMax">
<v-icon>mdi-lock-outline</v-icon>
</span>
<span v-if="props.modelValue.costumes.length > 0">
<v-icon>mdi-tshirt-crew-outline</v-icon>
</span>
</div>
</div>
<div class="tua-abl-bottom">
<div class="tua-abl-bg">
<img v-if="nameCard !== false && isFetterMax" :src="nameCard" alt="nameCard" />
</div>
<div class="tua-abl-skills">
<div v-for="skill in skills" :key="skill.skill_id" class="tua-abl-skill">
<img :src="skill.icon" alt="skill" />
<span>Lv.{{ skill.level }}</span>
<div class="tua-ab-top">
<TuaItemBox v-model="avatarBox" />
<div class="tua-abt-right">
<TuaItemBox v-model="weaponBox" />
<div v-for="(relic, index) in relicsBox" :key="index" class="tua-relic-box">
<div class="tua-relic-bg">
<img :src="`/icon/bg/${relic.rarity}-Star.webp`" alt="bg" v-if="relic !== false" />
</div>
<div class="tua-relic-icon">
<img
:src="`/icon/relic/${index + 1}.webp`"
:alt="`relic${index + 1}`"
v-if="relic === false"
class="empty"
/>
<img :src="relic.icon" :alt="relic.name" v-else />
</div>
</div>
</div>
</div>
<!-- 右侧圣遗物及套装 -->
<div class="tua-ab-right">
<div v-for="(relic, index) in relicsBox" :key="index" class="tua-abr-relic">
<!-- 左侧icon 及等级 -->
<div class="tua-relic-left">
<div class="tua-rl-icon">
<img :src="`/icon/relic/${index + 1}.webp`" alt="relic" v-if="relic === false" />
<img :src="relic.icon" alt="relic" v-if="relic !== false" />
</div>
<div class="tua-rl-bg">
<img :src="`/icon/bg/${relic.rarity}-Star.webp`" alt="bg" v-if="relic !== false" />
</div>
<div :class="`tua-rl-relic rarity${relic.rarity}`" v-if="relic !== false">
{{ relic.level }}
</div>
</div>
<!-- 右侧数值及加成 -->
<div class="tua-relic-right">
<div class="tua-relic-name">
{{ relic === false ? getRelicName(index) : relic.main_property.value }}
</div>
<div class="tua-relic-prop" v-if="relic !== false">
<div v-if="getPropName(relic) !== false">
<img
v-if="getPropName(relic).icon !== ''"
:src="getPropName(relic).icon"
alt="prop"
:title="getPropName(relic).name"
/>
<span v-else>{{ getPropName(relic)?.name }}</span>
</div>
</div>
<div class="tua-abl-mid">
<div class="tua-abl-fetter">
<img src="/icon/material/105.webp" alt="fetter" />
<span>{{ props.modelValue.avatar.fetter }}</span>
</div>
<div class="tua-abl-other">
<span v-if="!isFetterMax">
<v-icon>mdi-lock-outline</v-icon>
</span>
<span v-if="props.modelValue.costumes.length > 0">
<v-icon>mdi-tshirt-crew-outline</v-icon>
</span>
</div>
</div>
<div class="tua-abl-bottom">
<div class="tua-abl-bg">
<img v-if="nameCard !== false && isFetterMax" :src="nameCard" alt="nameCard" />
</div>
<div class="tua-abl-skills">
<div v-for="skill in skills" :key="skill.skill_id" class="tua-abl-skill">
<img :src="skill.icon" alt="skill" />
<span>Lv.{{ skill.level }}</span>
</div>
</div>
</div>
@@ -73,58 +52,57 @@
import { computed, onMounted, ref } from "vue";
import TGSqlite from "../../plugins/Sqlite/index.js";
import { useUserStore } from "../../store/modules/user.js";
import { getZhElement } from "../../utils/toolFunc.js";
import TItembox, { TItemBoxData } from "../main/t-itembox.vue";
import TuaItemBox, { TuaItemBoxType } from "./tua-item-box.vue";
interface TuaAvatarBoxProps {
modelValue: TGApp.Sqlite.Character.UserRole;
}
const props = defineProps<TuaAvatarBoxProps>();
type FixedLenArr<T, N extends number> = [T, ...T[]] & { length: N };
type AvatarRelics = FixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;
const props = defineProps<TuaAvatarBoxProps>();
const userStore = useUserStore();
const avatarBox = computed<TItemBoxData>(() => {
const avatarBox = computed<TuaItemBoxType>(() => {
const avatar = props.modelValue.avatar;
return {
size: "100px",
height: "120px",
ltSize: "30px",
bg: `/icon/bg/${avatar.rarity}-Star.webp`,
icon: `/WIKI/character/${avatar.id}.webp`,
star: avatar.rarity,
type: "character",
id: avatar.id,
size: "130px",
lt: `/icon/element/${getZhElement(avatar.element)}元素.webp`,
ltSize: "30px",
rt: avatar.actived_constellation_num.toString() || "0",
rtSize: "20px",
innerText: `Lv.${avatar.level}`,
innerHeight: 20,
outerText: avatar.name,
outerHeight: 20,
display: "outer",
clickable: true,
};
});
const weaponBox = computed<TItemBoxData>(() => {
const weaponBox = computed<TuaItemBoxType>(() => {
const weapon = props.modelValue.weapon;
return {
size: "100px",
height: "120px",
ltSize: "30px",
bg: `/icon/bg/${weapon.rarity}-Star.webp`,
icon: `/WIKI/weapon/${weapon.id}.webp`,
star: weapon.rarity,
type: "weapon",
id: weapon.id,
size: "40px",
lt: `/icon/weapon/${weapon.type_name}.webp`,
ltSize: "15px",
rt: weapon.affix_level.toString() || "0",
rtSize: "20px",
innerText: `Lv.${weapon.level}`,
innerHeight: 20,
outerText: weapon.name,
outerHeight: 20,
display: "outer",
rtSize: "15px",
clickable: true,
};
});
const relicsBox = computed<AvatarRelics>(() => {
const relics = props.modelValue.relics;
return [
relics.find((i) => i.pos === 1) || false,
relics.find((i) => i.pos === 2) || false,
relics.find((i) => i.pos === 3) || false,
relics.find((i) => i.pos === 4) || false,
relics.find((i) => i.pos === 5) || false,
];
});
const isFetterMax = computed<boolean>(() => {
if (props.modelValue.avatar.id === 10000005 || props.modelValue.avatar.id === 10000007) {
return true;
@@ -134,16 +112,6 @@ const isFetterMax = computed<boolean>(() => {
const skills = computed<TGApp.Game.Avatar.Skill[]>(() => {
return props.modelValue.skills.filter((skill) => skill.skill_type === 1);
});
const relicsBox = computed<AvatarRelics>(() => {
const relics = props.modelValue.relics;
return [
relics.find((relic) => relic.pos === 1) || false,
relics.find((relic) => relic.pos === 2) || false,
relics.find((relic) => relic.pos === 3) || false,
relics.find((relic) => relic.pos === 4) || false,
relics.find((relic) => relic.pos === 5) || false,
];
});
const nameCard = ref<string | false>(false);
@@ -156,63 +124,96 @@ onMounted(async () => {
nameCard.value = "/source/nameCard/profile/原神·印象.webp";
}
});
function getRelicName(pos: number): string {
const nameList = ["生之花", "死之羽", "时之沙", "空之杯", "理之冠"];
return nameList[pos];
}
function getPropName(relic: TGApp.Game.Avatar.Relic): TGApp.Game.Avatar.PropMapItem | false {
return userStore.getProp(relic.main_property.property_type);
}
</script>
<style lang="css" scoped>
.tua-ab-box {
position: relative;
display: flex;
width: fit-content;
flex-direction: column;
padding: 5px;
border: 1px inset var(--common-shadow-2);
border-radius: 5px;
background: var(--box-bg-2);
column-gap: 5px;
transition: all 0.3s;
}
.tua-ab-left {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
row-gap: 5px;
}
.tua-abl-top {
.tua-ab-top {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
}
.tua-abt-right {
display: flex;
width: 85px;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 5px;
}
.tua-relic-box {
position: relative;
width: 40px;
height: 40px;
border-radius: 5px;
}
.tua-relic-icon {
position: relative;
width: 40px;
height: 40px;
border-radius: 5px;
img {
width: 100%;
height: 100%;
border-radius: 5px;
object-fit: cover;
}
.empty {
padding: 5px;
}
}
.tua-relic-bg {
position: absolute;
top: 0;
left: 0;
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
border-radius: 5px;
background: var(--box-bg-3);
img {
width: 100%;
height: 100%;
border-radius: 5px;
object-fit: cover;
}
}
.tua-abl-mid {
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;
}
.tua-abl-fetter {
display: flex;
align-items: center;
justify-content: flex-start;
column-gap: 5px;
gap: 5px;
img {
width: 20px;
@@ -221,14 +222,6 @@ function getPropName(relic: TGApp.Game.Avatar.Relic): TGApp.Game.Avatar.PropMapI
}
}
.tua-abl-other {
display: flex;
align-items: center;
justify-content: flex-end;
color: var(--box-text-4);
column-gap: 5px;
}
.tua-abl-bottom {
position: relative;
width: 100%;
@@ -305,125 +298,4 @@ function getPropName(relic: TGApp.Game.Avatar.Relic): TGApp.Game.Avatar.PropMapI
font-size: 12px;
}
}
.tua-ab-right {
display: grid;
column-gap: 5px;
grid-template-columns: repeat(2, 1fr);
}
.tua-abr-relic {
display: flex;
width: 120px;
align-items: center;
justify-content: space-between;
column-gap: 5px;
}
.tua-relic-left {
position: relative;
width: 60px;
height: 60px;
border-radius: 50%;
background: rgb(50 56 68/50%);
}
.tua-rl-icon {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
:nth-child(1) {
padding: 5px;
}
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.tua-rl-bg {
overflow: hidden;
width: 100%;
height: 100%;
border-radius: 50%;
background: var(--box-bg-3);
img {
width: 100%;
height: 100%;
}
}
.tua-rl-relic {
position: absolute;
right: -4px;
bottom: -4px;
display: flex;
width: 24px;
height: 24px;
align-items: center;
justify-content: center;
border-radius: 50%;
box-shadow: 0 0 5px var(--tgc-dark-1);
color: var(--tgc-white-1);
font-family: var(--font-title);
font-size: 12px;
line-height: 1;
text-shadow: 0 0 5px var(--tgc-dark-1);
}
.tua-rl-relic.rarity0 {
background: var(--tgc-od-white);
}
.tua-rl-relic.rarity1 {
background: var(--tgc-od-white);
}
.tua-rl-relic.rarity2 {
background: var(--tgc-od-green);
}
.tua-rl-relic.rarity3 {
background: var(--tgc-od-blue);
}
.tua-rl-relic.rarity4 {
background: var(--tgc-od-purple);
}
.tua-rl-relic.rarity5 {
background: var(--tgc-od-orange);
}
.tua-relic-right {
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: center;
}
.tua-relic-name {
color: var(--box-text-4);
font-family: var(--font-title);
font-size: 16px;
}
.tua-relic-prop {
display: inline-flex;
color: var(--box-text-4);
font-size: 12px;
img {
width: 20px;
height: 20px;
filter: invert(0.5) contrast(1) drop-shadow(0 0 5px var(--common-shadow-4));
object-fit: contain;
}
}
</style>

View File

@@ -0,0 +1,145 @@
<template>
<div
class="tua-item-box"
:style="{
width: modelValue.size,
height: modelValue.size,
cursor: modelValue.clickable ? 'pointer' : 'default',
}"
>
<div
class="tib-bg"
:style="{
width: modelValue.size,
height: modelValue.size,
}"
>
<img :src="`/icon/bg/${props.modelValue.star}-Star.webp`" alt="bg" />
</div>
<div
class="tib-icon"
:style="{
width: modelValue.size,
height: modelValue.size,
}"
>
<img :src="`/WIKI/${props.modelValue.type}/${props.modelValue.id}.webp`" alt="icon" />
</div>
<div
class="tib-cover"
:style="{
width: modelValue.size,
height: modelValue.size,
}"
>
<div
class="tib-lt"
:style="{
width: modelValue.ltSize,
height: modelValue.ltSize,
}"
>
<img :src="modelValue.lt" alt="lt" />
</div>
<div
class="tib-rt"
:style="{
width: modelValue.rtSize,
height: modelValue.rtSize,
}"
>
{{ modelValue.rt }}
</div>
</div>
</div>
</template>
<script lang="ts" setup>
export interface TuaItemBoxType {
star: number;
type: "character" | "weapon";
id: number;
size: string;
lt: string;
ltSize: string;
rt: string;
rtSize: string;
clickable: boolean;
}
interface TuaItemBoxProps {
modelValue: TuaItemBoxType;
}
const props = defineProps<TuaItemBoxProps>();
</script>
<style lang="css" scoped>
.tua-item-box {
position: relative;
}
.tib-bg {
position: absolute;
top: 0;
left: 0;
overflow: hidden;
border-radius: 5px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.tib-icon {
position: relative;
overflow: hidden;
border-radius: 5px;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.tib-cover {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 5px;
}
.tib-lt {
position: absolute;
top: 3%;
left: 3%;
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.tib-rt {
position: absolute;
top: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgb(0 0 0 / 40%);
border-bottom-left-radius: 5px;
border-top-right-radius: 5px;
color: var(--tgc-white-1);
font-family: var(--font-title);
}
</style>

View File

@@ -23,13 +23,18 @@
</v-btn>
</div>
</div>
<div class="uc-grid">
<TuaAvatarBox
v-for="(role, index) in roleList"
:key="index"
:model-value="role"
@click="selectRole(role)"
/>
<div class="uc-content">
<div class="uc-left">
<div class="ucl-top"></div>
<div class="uc-grid">
<TuaAvatarBox
v-for="(role, index) in roleList"
:key="index"
:model-value="role"
@click="selectRole(role)"
/>
</div>
</div>
</div>
</div>
</template>
@@ -235,6 +240,6 @@ function selectRole(role: TGApp.Sqlite.Character.UserRole): void {
.uc-grid {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
</style>