💄 修正类型,调整UI

This commit is contained in:
目棃
2024-08-21 19:54:32 +08:00
parent 8ab998e089
commit 3a320ed95b
5 changed files with 221 additions and 111 deletions

View File

@@ -62,7 +62,7 @@ html {
/*
* @description 侧边滚动条样式
* @since Beta v0.3.0
* @since Beta v0.5.3
*/
::-webkit-scrollbar {
width: 8px;
@@ -76,9 +76,9 @@ html {
::-webkit-scrollbar-thumb {
border-radius: 5px;
background: var(--common-shadow-2);
background: var(--tgc-od-white);
}
::-webkit-scrollbar-thumb:hover {
background: var(--common-shadow-4);
background: var(--tgc-od-orange);
}

View File

@@ -1,23 +1,19 @@
<template>
<div class="tua-ab-box">
<!-- 左侧角色武器天赋好感衣装名片 -->
<div class="tua-ab-top">
<TItembox v-model="avatarBox" />
<div class="tua-abt-right">
<TItembox 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 class="tua-abt-rt">
<TItembox v-model="weaponBox" :title="getWeaponTitle()" />
<div class="tua-abt-rtr">
<TuaRelicBox :model-value="relicsBox[0]" :position="1" />
<TuaRelicBox :model-value="relicsBox[1]" :position="2" />
</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 class="tua-abt-rb">
<TuaRelicBox :model-value="relicsBox[2]" :position="3" />
<TuaRelicBox :model-value="relicsBox[3]" :position="4" />
<TuaRelicBox :model-value="relicsBox[4]" :position="5" />
</div>
</div>
</div>
@@ -52,14 +48,18 @@
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 TuaRelicBox from "./tua-relic-box.vue";
interface TuaAvatarBoxProps {
modelValue: TGApp.Sqlite.Character.UserRole;
}
const props = defineProps<TuaAvatarBoxProps>();
const userStore = useUserStore();
type FixedLenArr<T, N extends number> = [T, ...T[]] & { length: N };
type AvatarRelics = FixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;
@@ -67,8 +67,8 @@ type AvatarRelics = FixedLenArr<TGApp.Game.Avatar.Relic | false, 5>;
const avatarBox = computed<TItemBoxData>(() => {
const avatar = props.modelValue.avatar;
return {
size: "130px",
height: "130px",
size: "100px",
height: "100px",
bg: `/icon/bg/${avatar.rarity}-Star.webp`,
icon: `/WIKI/character/${avatar.id}.webp`,
lt: `/icon/element/${getZhElement(avatar.element)}元素.webp`,
@@ -78,22 +78,24 @@ const avatarBox = computed<TItemBoxData>(() => {
innerText: avatar.name,
innerHeight: 30,
display: "inner",
clickable: true,
clickable: false,
};
});
const weaponBox = computed<TItemBoxData>(() => {
const weapon = props.modelValue.weapon;
return {
size: "40px",
height: "40px",
size: "65px",
height: "65px",
bg: `/icon/bg/${weapon.rarity}-Star.webp`,
icon: `/WIKI/weapon/${weapon.id}.webp`,
lt: `/icon/weapon/${weapon.type_name}.webp`,
ltSize: "15px",
innerText: "",
innerHeight: 0,
ltSize: "20px",
rt: weapon.affix_level.toString(),
rtSize: "20px",
innerText: weapon.name,
innerHeight: 20,
display: "inner",
clickable: true,
clickable: false,
};
});
const relicsBox = computed<AvatarRelics>(() => {
@@ -127,6 +129,18 @@ onMounted(async () => {
nameCard.value = "/source/nameCard/profile/原神·印象.webp";
}
});
function getWeaponTitle(): string {
const weapon = props.modelValue.weapon;
const title: string[] = [];
title.push(`${weapon.type_name} - ${weapon.name}`);
title.push(`${weapon.rarity}星 精炼${weapon.affix_level} Lv.${weapon.level}`);
const propMain = userStore.getProp(weapon.main_property.property_type);
title.push(`${propMain !== false ? propMain.name : "未知属性"} - ${weapon.main_property.final}`);
const propSub = userStore.getProp(weapon.sub_property.property_type);
title.push(`${propSub !== false ? propSub.name : "未知属性"} - ${weapon.sub_property.final}`);
return title.join("\n");
}
</script>
<style lang="css" scoped>
.tua-ab-box {
@@ -144,59 +158,38 @@ onMounted(async () => {
display: flex;
width: 100%;
align-items: center;
justify-content: space-between;
justify-content: center;
column-gap: 10px;
}
.tua-abt-right {
display: grid;
padding: 5px;
gap: 5px;
grid-template-columns: repeat(2, 40px);
}
.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%;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 5px;
background: var(--box-bg-3);
justify-content: space-between;
row-gap: 5px;
}
img {
width: 100%;
height: 100%;
border-radius: 5px;
object-fit: cover;
}
.tua-abt-rt {
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 5px;
}
.tua-abt-rtr {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
row-gap: 5px;
}
.tua-abt-rb {
display: flex;
align-items: center;
justify-content: space-between;
column-gap: 5px;
}
.tua-abl-bottom {

View File

@@ -0,0 +1,110 @@
<template>
<div class="tua-relic-box" :title="getRelicTitle()">
<div class="tua-relic-bg">
<img
:src="`/icon/bg/${props.modelValue.rarity}-Star.webp`"
v-if="props.modelValue !== false"
:alt="`relic${props.position}`"
/>
</div>
<div class="tua-relic-icon">
<img
:src="`/icon/relic/${props.position}.webp`"
:alt="`relic${props.position}`"
v-if="props.modelValue === false"
class="empty"
/>
<img :src="props.modelValue.icon" :alt="props.modelValue.name" v-else />
</div>
</div>
</template>
<script lang="ts" setup>
import { useUserStore } from "../../store/modules/user.js";
interface TuaRelicBoxProps {
modelValue: TGApp.Game.Avatar.Relic | false;
position: number;
}
const props = defineProps<TuaRelicBoxProps>();
const userStore = useUserStore();
function getRelicPosName(): string {
switch (props.position) {
case 1:
return "生之花";
case 2:
return "死之羽";
case 3:
return "时之沙";
case 4:
return "空之杯";
case 5:
return "理之冠";
default:
return "未知";
}
}
function getRelicTitle(): string {
const posName = getRelicPosName();
if (props.modelValue === false) return `${posName}:未装备`;
const relicProps: string[] = [];
const mainProp = userStore.getProp(props.modelValue.main_property.property_type);
relicProps.push(
`主词条:${mainProp === false ? "未知属性" : mainProp.name} ${props.modelValue.main_property.value}`,
);
relicProps.push("副词条:");
for (const relicProp of props.modelValue.sub_property_list) {
const subProp = userStore.getProp(relicProp.property_type);
relicProps.push(
` ${subProp === false ? "未知属性" : subProp.name} ${relicProp.value}(+${relicProp.times})`,
);
}
return `${posName}\n${props.modelValue.name} Lv.${props.modelValue.level}\n${relicProps.join("\n")}`;
}
</script>
<style lang="css" scoped>
.tua-relic-box {
position: relative;
width: 30px;
height: 30px;
border-radius: 5px;
}
.tua-relic-icon {
position: relative;
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
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;
}
}
</style>

View File

@@ -1,5 +1,27 @@
<template>
<ToLoading v-model="loading" :title="loadingTitle" :subtitle="loadingSub" />
<v-app-bar>
<template #title>
<span v-if="user"> {{ user.nickname }}({{ user.gameUid }})</span>
<span v-else> 暂无数据 </span>
</template>
<template #append>
<div class="uc-top-btns">
<v-btn @click="refresh()" rounded variant="outlined" v-model:loading="loadData">
<template #prepend>
<v-icon>mdi-refresh</v-icon>
</template>
刷新
</v-btn>
<v-btn @click="share()" rounded variant="outlined" v-model:loading="loadShare">
<template #prepend>
<v-icon>mdi-share</v-icon>
</template>
分享
</v-btn>
</div>
</template>
</v-app-bar>
<div class="uc-box">
<div class="uc-top">
<div class="uc-top-title" @click="switchOld">
@@ -8,24 +30,7 @@
</span>
<span v-else> 暂无数据 </span>
</div>
<div class="uc-top-btns" data-html2canvas-ignore>
<v-btn class="uc-top-btn" @click="refresh()">
<template #prepend>
<v-icon>mdi-refresh</v-icon>
</template>
刷新
</v-btn>
<v-btn class="uc-top-btn" @click="share()">
<template #prepend>
<v-icon>mdi-share</v-icon>
</template>
分享
</v-btn>
</div>
</div>
<div class="uc-content">
<div class="uc-left">
<div class="ucl-top"></div>
<div class="uc-grid">
<TuaAvatarBox
v-for="(role, index) in roleList"
@@ -35,8 +40,6 @@
/>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from "pinia";
@@ -57,6 +60,8 @@ const user = ref<TGApp.Sqlite.Account.Game>();
// loading
const loading = ref<boolean>(false);
const loadData = ref<boolean>(false);
const loadShare = ref<boolean>(false);
const loadingTitle = ref<string>();
const loadingSub = ref<string>();
@@ -80,8 +85,10 @@ onMounted(async () => {
await TGLogger.Info("[Character][onMounted] 进入角色页面");
loadingTitle.value = "正在获取角色数据";
loading.value = true;
loadData.value = true;
await load();
loading.value = false;
loadData.value = false;
});
function switchOld(): void {
@@ -114,12 +121,14 @@ async function refresh(): Promise<void> {
await TGLogger.Info(`[Character][refreshRoles][${user.value.gameUid}] 正在更新角色数据`);
loadingTitle.value = "正在获取角色列表";
loading.value = true;
loadData.value = true;
if (!userStore.cookie.value) {
showSnackbar({
text: "请先登录",
color: "error",
});
loading.value = false;
loadData.value = false;
return;
}
const cookie = {
@@ -137,6 +146,7 @@ async function refresh(): Promise<void> {
`[Character][refreshRoles][${user.value.gameUid}] ${listRes.retcode} ${listRes.message}`,
);
loading.value = false;
loadData.value = false;
return;
}
const idList = listRes.map((i) => i.id.toString());
@@ -153,6 +163,7 @@ async function refresh(): Promise<void> {
`[Character][refreshRoles][${user.value.gameUid}] ${res.retcode} ${res.message}`,
);
loading.value = false;
loadData.value = false;
return;
}
userStore.propMap.value = res.property_map;
@@ -164,6 +175,7 @@ async function refresh(): Promise<void> {
);
await load();
loading.value = false;
loadData.value = false;
}
async function share(): Promise<void> {
@@ -174,9 +186,11 @@ async function share(): Promise<void> {
loadingTitle.value = "正在生成图片";
loadingSub.value = `${fileName}.png`;
loading.value = true;
loadShare.value = true;
await generateShareImg(fileName, rolesBox);
loadingSub.value = "";
loading.value = false;
loadShare.value = false;
await TGLogger.Info(`[Character][shareRoles][${user.value.gameUid}] 生成分享图片成功`);
}
@@ -226,20 +240,13 @@ function selectRole(role: TGApp.Sqlite.Character.UserRole): void {
.uc-top-btns {
display: flex;
align-items: center;
gap: 15px;
}
.uc-top-btn {
border-radius: 5px;
background: var(--tgc-btn-1);
color: var(--btn-text);
font-family: var(--font-text);
align-content: center;
column-gap: 10px;
}
.uc-grid {
display: grid;
grid-gap: 10px;
grid-gap: 15px;
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
</style>

View File

@@ -208,7 +208,7 @@ declare namespace TGApp.Game.Avatar {
* @property {RelicSet} set - 圣遗物套装
* @property {string} pos_name - 圣遗物位置名称
* @property {RelicProp} main_property - 圣遗物主属性
* @property {RelicProp[]} sub_properties - 圣遗物副属性
* @property {RelicProp[]} sub_property_list - 圣遗物副属性
* @return Relic
*/
interface Relic {
@@ -221,7 +221,7 @@ declare namespace TGApp.Game.Avatar {
set: RelicSet;
pos_name: string;
main_property: RelicProp;
sub_properties: RelicProp[];
sub_property_list: RelicProp[];
}
/**