mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-13 09:28:14 +08:00
2
src/components/devCharacter/duc-detail-olb.vue
Normal file
2
src/components/devCharacter/duc-detail-olb.vue
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<template></template>
|
||||||
|
<script lang="ts" setup></script>
|
||||||
108
src/components/devCharacter/duc-detail-olt.vue
Normal file
108
src/components/devCharacter/duc-detail-olt.vue
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ddo-lt-box">
|
||||||
|
<div class="ddo-ltb-icon" :title="getTitle">
|
||||||
|
<TItemBox :model-value="boxData" />
|
||||||
|
</div>
|
||||||
|
<div class="ddo-ltb-info">
|
||||||
|
<span>{{ props.data.name }}</span>
|
||||||
|
<span>Lv.{{ props.data.level }}</span>
|
||||||
|
<span>{{ info }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
import TItemBox, { TItemBoxData } from "../main/t-itembox.vue";
|
||||||
|
|
||||||
|
type DucDetailOltProps =
|
||||||
|
| {
|
||||||
|
data: TGApp.Sqlite.Character.UserRole;
|
||||||
|
mode: "avatar";
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
data: TGApp.Sqlite.Character.RoleWeapon;
|
||||||
|
mode: "weapon";
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = defineProps<DucDetailOltProps>();
|
||||||
|
const getTitle = computed(() => {
|
||||||
|
if (props.mode === "avatar") {
|
||||||
|
return `${props.data.name}`;
|
||||||
|
} else {
|
||||||
|
// 按照长度折行,一行最多显示 10 个字
|
||||||
|
const descriptionList = props.data.description.split("");
|
||||||
|
return descriptionList.reduce((prev: string, cur: string, index: number) => {
|
||||||
|
if (index % 10 === 0) {
|
||||||
|
return `${prev}\n${cur}`;
|
||||||
|
} else {
|
||||||
|
return `${prev}${cur}`;
|
||||||
|
}
|
||||||
|
}, "");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const boxData = computed<TItemBoxData>(() => {
|
||||||
|
if (props.mode === "avatar") {
|
||||||
|
return {
|
||||||
|
bg: `/icon/bg/${props.data.star}-Star.webp`,
|
||||||
|
icon: `/WIKI/character/icon/${props.data.cid}.webp`,
|
||||||
|
size: "100px",
|
||||||
|
height: "100px",
|
||||||
|
display: "inner",
|
||||||
|
innerHeight: 0,
|
||||||
|
innerText: "",
|
||||||
|
lt: `/icon/element/${props.data.element}.webp`,
|
||||||
|
ltSize: "30px",
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
bg: `/icon/bg/${props.data.star}-Star.webp`,
|
||||||
|
icon: `/WIKI/weapon/icon/${props.data.id}.webp`,
|
||||||
|
size: "100px",
|
||||||
|
height: "100px",
|
||||||
|
display: "inner",
|
||||||
|
innerHeight: 0,
|
||||||
|
innerText: "",
|
||||||
|
lt: `/icon/weapon/${props.data.type}.webp`,
|
||||||
|
ltSize: "30px",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const info = computed(() => {
|
||||||
|
if (props.mode === "avatar") {
|
||||||
|
return `好感 ${props.data.fetter}`;
|
||||||
|
} else {
|
||||||
|
return `精炼 ${props.data.affix}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.ddo-lt-box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
column-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ddo-ltb-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
color: var(--tgc-white-1);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ddo-ltb-info :nth-child(1) {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-family: var(--font-title);
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ddo-ltb-info :not(:nth-child(1)) {
|
||||||
|
font-family: var(--font-text);
|
||||||
|
font-size: 16px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
2
src/components/devCharacter/duc-detail-ort.vue
Normal file
2
src/components/devCharacter/duc-detail-ort.vue
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<template></template>
|
||||||
|
<script lang="ts" setup></script>
|
||||||
179
src/components/devCharacter/duc-detail-overlay.vue
Normal file
179
src/components/devCharacter/duc-detail-overlay.vue
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
<template>
|
||||||
|
<TOverlay v-model="visible" hide :to-click="onOverlayCancel" blur-val="20px">
|
||||||
|
<div class="duc-do-box">
|
||||||
|
<!-- 左侧箭头 -->
|
||||||
|
<div class="duc-arrow-left" @click="handleClick('left')">
|
||||||
|
<img src="../../assets/icons/arrow-right.svg" alt="left" />
|
||||||
|
</div>
|
||||||
|
<!-- 中间内容 -->
|
||||||
|
<div class="duc-do-container">
|
||||||
|
<img :src="nameCard" class="duc-doc-bg" v-if="nameCard !== false" alt="bg" />
|
||||||
|
<div class="duc-doc-bgc" />
|
||||||
|
<!-- 左上角色跟武器 -->
|
||||||
|
<div class="duc-doc-lt">
|
||||||
|
<DucDetailOlt :data="props.dataVal" mode="avatar" />
|
||||||
|
<DucDetailOlt :data="JSON.parse(props.dataVal.weapon)" mode="weapon" />
|
||||||
|
</div>
|
||||||
|
<!-- 右下天赋 -->
|
||||||
|
<div class="duc-doc-rb">
|
||||||
|
<DucDetailOrt :data="JSON.parse(props.dataVal.talent)" />
|
||||||
|
</div>
|
||||||
|
<!-- 左下命座 -->
|
||||||
|
<div class="duc-doc-lb">
|
||||||
|
<DucDetailOlb :data="JSON.parse(props.dataVal.constellation)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧箭头 -->
|
||||||
|
<div class="duc-arrow-right" @click="handleClick('right')">
|
||||||
|
<img src="../../assets/icons/arrow-right.svg" alt="right" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TOverlay>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, onMounted, onUpdated, ref } from "vue";
|
||||||
|
|
||||||
|
import DucDetailOlb from "./duc-detail-olb.vue";
|
||||||
|
import DucDetailOlt from "./duc-detail-olt.vue";
|
||||||
|
import DucDetailOrt from "./duc-detail-ort.vue";
|
||||||
|
import TGSqlite from "../../plugins/Sqlite";
|
||||||
|
import TOverlay from "../main/t-overlay.vue";
|
||||||
|
|
||||||
|
interface DucDetailOverlayProps {
|
||||||
|
modelValue: boolean;
|
||||||
|
dataVal: TGApp.Sqlite.Character.UserRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
type DucDetailOverlayEmits = {
|
||||||
|
(e: "update:modelValue", value: boolean): void;
|
||||||
|
(e: "clickL"): void;
|
||||||
|
(e: "clickR"): void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const props = defineProps<DucDetailOverlayProps>();
|
||||||
|
const emits = defineEmits<DucDetailOverlayEmits>();
|
||||||
|
const visible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (value) => {
|
||||||
|
emits("update:modelValue", value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 渲染数据
|
||||||
|
const nameCard = ref<string | false>(false);
|
||||||
|
|
||||||
|
function onOverlayCancel() {
|
||||||
|
visible.value = false;
|
||||||
|
emits("update:modelValue", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClick(pos: "left" | "right") {
|
||||||
|
pos === "left" ? emits("clickL") : emits("clickR");
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadData();
|
||||||
|
});
|
||||||
|
onUpdated(async () => {
|
||||||
|
await loadData();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function loadData(): Promise<void> {
|
||||||
|
if (!props.modelValue) return;
|
||||||
|
if (props.dataVal.cid !== 10000005 && props.dataVal.cid !== 10000007) {
|
||||||
|
const role = await TGSqlite.getAppCharacter(props.dataVal.cid);
|
||||||
|
nameCard.value = `/source/nameCard/profile/${role.nameCard}.webp`;
|
||||||
|
}
|
||||||
|
// resetData();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.duc-do-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
column-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-arrow-left,
|
||||||
|
.duc-arrow-right {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .duc-arrow-left,
|
||||||
|
.dark .duc-arrow-right {
|
||||||
|
filter: invert(11%) sepia(73%) saturate(11%) hue-rotate(139deg) brightness(97%) contrast(81%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-arrow-left img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-arrow-right img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-do-container {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 50vw;
|
||||||
|
border-radius: 5px;
|
||||||
|
aspect-ratio: 21 / 10;
|
||||||
|
background: var(--box-bg-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-doc-bg {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-doc-bgc {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgb(0 0 0 / 20%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-doc-lt {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 5px;
|
||||||
|
row-gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-doc-rb {
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
bottom: 20px;
|
||||||
|
width: 100px;
|
||||||
|
height: 300px;
|
||||||
|
background: var(--common-shadow-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.duc-doc-lb {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 20px;
|
||||||
|
width: 300px;
|
||||||
|
height: 80px;
|
||||||
|
background: var(--common-shadow-2);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -38,14 +38,20 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ToUcDetail v-model="visible" :data-val="dataVal" />
|
<!-- <ToUcDetail v-model="visible" :data-val="dataVal" />-->
|
||||||
|
<DucDetailOverlay
|
||||||
|
v-model="visible"
|
||||||
|
@clickL="clickOverlay('left')"
|
||||||
|
@clickR="clickOverlay('right')"
|
||||||
|
:data-val="dataVal"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
|
||||||
|
import DucDetailOverlay from "../../components/devCharacter/duc-detail-overlay.vue";
|
||||||
import showSnackbar from "../../components/func/snackbar";
|
import showSnackbar from "../../components/func/snackbar";
|
||||||
import ToLoading from "../../components/overlay/to-loading.vue";
|
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||||
import ToUcDetail from "../../components/userCharacter/tuc-detail-overlay.vue";
|
|
||||||
import TucRoleBox from "../../components/userCharacter/tuc-role-box.vue";
|
import TucRoleBox from "../../components/userCharacter/tuc-role-box.vue";
|
||||||
import TGSqlite from "../../plugins/Sqlite";
|
import TGSqlite from "../../plugins/Sqlite";
|
||||||
import { useUserStore } from "../../store/modules/user";
|
import { useUserStore } from "../../store/modules/user";
|
||||||
@@ -69,6 +75,24 @@ const roleCookie = computed(() => userStore.getCookieGroup4());
|
|||||||
// overlay
|
// overlay
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const dataVal = ref<TGApp.Sqlite.Character.UserRole>(<TGApp.Sqlite.Character.UserRole>{});
|
const dataVal = ref<TGApp.Sqlite.Character.UserRole>(<TGApp.Sqlite.Character.UserRole>{});
|
||||||
|
const selectIndex = ref(0);
|
||||||
|
|
||||||
|
function clickOverlay(pos: "left" | "right") {
|
||||||
|
if (pos === "left") {
|
||||||
|
if (selectIndex.value === 0) {
|
||||||
|
selectIndex.value = roleList.value.length - 1;
|
||||||
|
} else {
|
||||||
|
selectIndex.value -= 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (selectIndex.value === roleList.value.length - 1) {
|
||||||
|
selectIndex.value = 0;
|
||||||
|
} else {
|
||||||
|
selectIndex.value += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataVal.value = roleList.value[selectIndex.value];
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
loadingTitle.value = "正在获取角色数据";
|
loadingTitle.value = "正在获取角色数据";
|
||||||
@@ -86,6 +110,7 @@ async function loadRole(): Promise<void> {
|
|||||||
return a.cid - b.cid;
|
return a.cid - b.cid;
|
||||||
});
|
});
|
||||||
roleList.value = roleData;
|
roleList.value = roleData;
|
||||||
|
dataVal.value = roleData[selectIndex.value];
|
||||||
isEmpty.value = false;
|
isEmpty.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,8 +199,8 @@ function getUpdateTime(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function selectRole(role: TGApp.Sqlite.Character.UserRole): void {
|
function selectRole(role: TGApp.Sqlite.Character.UserRole): void {
|
||||||
console.log(role);
|
|
||||||
dataVal.value = role;
|
dataVal.value = role;
|
||||||
|
selectIndex.value = roleList.value.indexOf(role);
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -13,34 +13,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1>角色详情(beta)</h1>
|
|
||||||
<div class="test-item">
|
|
||||||
<div class="role-box">
|
|
||||||
{{ JSON.stringify(roleItem, null, 2) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup></script>
|
||||||
import { onMounted, ref } from "vue";
|
|
||||||
|
|
||||||
import TGSqlite from "../../plugins/Sqlite";
|
|
||||||
import { useUserStore } from "../../store/modules/user";
|
|
||||||
|
|
||||||
const visible = ref<boolean>(false);
|
|
||||||
const userStore = useUserStore();
|
|
||||||
|
|
||||||
const roleItem = ref<TGApp.Sqlite.Character.UserRole>();
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
const user = userStore.getCurAccount();
|
|
||||||
const roleData = await TGSqlite.getUserCharacter(user.gameUid);
|
|
||||||
if (roleData !== false) {
|
|
||||||
roleItem.value = roleData[0];
|
|
||||||
}
|
|
||||||
visible.value = false;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<style lang="css" scoped>
|
<style lang="css" scoped>
|
||||||
.test-box {
|
.test-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -91,15 +66,4 @@ onMounted(async () => {
|
|||||||
.test-4 {
|
.test-4 {
|
||||||
background: var(--box-bg-4);
|
background: var(--box-bg-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.role-box {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 5px;
|
|
||||||
background: var(--box-bg-1);
|
|
||||||
color: var(--box-text-1);
|
|
||||||
gap: 10px;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user