Files
loreal-survey/src/views/Report.vue
T
2025-07-13 14:50:33 +08:00

279 lines
7.2 KiB
Vue

<script setup lang="ts">
import imgs from '../assets/imgs'
import Tags from '../components/Tags.vue'
import { DimensionColors, DimensionName, findTraitDimension, GamePageDimensionColors, TraitName, } from '../config';
import { useI18n } from 'vue-i18n'
import type { MessageSchema } from '../locates'
import Graph from '../components/Graph.vue';
import { computed, ComputedRef } from 'vue';
const { t } = useI18n<{ message: MessageSchema }>({ useScope: 'global' })
import lang from '../locates'
const props = defineProps<{
result: Record<DimensionName, number>,
trait: Record<TraitName, number>,
graph: {
name_en: string;
name_zh: string;
value: number;
color: string;
iconUrl: string;
}[],
rarity: number,
username: string,
topFiveTraits: TraitName[],
}>()
defineEmits<{
next: [],
}>()
const topDimension: ComputedRef<DimensionName> = computed(() =>
Object.entries(props.result).sort(([, a], [, b]) => b - a)[0][0] as DimensionName
)
const topTwoDimensions = computed(() => {
const dimensions = Object.entries(props.result)
const sortedDimensions = dimensions.sort((a, b) => b[1] - a[1])
return sortedDimensions.slice(0, 2)
})
const topFiveTraits = computed(() => {
const traits = props.trait
const filteredTraits = Object.entries(traits).filter(([trait]) => {
const dimension = findTraitDimension(trait as TraitName)
return topTwoDimensions.value.some((d) => d[0] === dimension)
})
const sortedTraits = filteredTraits.sort((a, b) => b[1] - a[1])
return sortedTraits.slice(0, 5) as [[TraitName, number], ...[TraitName, number][]]
})
function jumpZh() {
window.location.href = 'weixin://dl/business/?appid=wxe6d33a608a6fd9a5&path=pages/brandstorm/index&query=promotionId=9'
}
function jumpEn() {
window.location.href = 'https://brandstorm.loreal.com'
}
</script>
<template>
<div class="report page">
<!-- <LightGrow class="bg" :shapes="lightProps" :animation-duration="4"
:blur-amount="60" background="#000" :screen-shadow="{
color: '#000',
left: 10, right: 10, top: 10, bottom: 10, blur: 32
}" :filter="'saturate(1.5)'"/> -->
<img :src="imgs.report[topDimension]" alt="" draggable="false"
class="growing-bg" />
<!-- <img :src="t('report.top')" alt="" class="top-title" /> -->
<div class="title" :lang="$i18n.locale">
<span class="pre">{{ username }}{{ t('report.title') }}</span>
<span class="dim">{{
lang.en.questionData.DimensionName[topDimension] }}</span>
</div>
<div class="left-title">
<img :src="imgs.icons[topDimension]" alt="">
<span v-if="$i18n.locale === 'zh'" class="zh-title"
v-for="c in lang.zh_CN.questionData.DimensionName[topDimension].split('')">
{{ c }}</span>
<span v-if="$i18n.locale === 'en'" class="en-title">
{{ lang.en.questionData.DimensionName[topDimension] }}
</span>
</div>
<div class="right-top">
<Graph class="graph" :dimensions="graph" :label-radius="110"
:score-radio="1" :style="{ fontSize: '0.8rem' }"
:icons-filter="'grayscale(100%) brightness(2)'" />
<div class="description">
<p :lang="$i18n.locale"
v-for="para in t(`report.dimDescription.${topDimension}`).split('\n\n')">
{{ para }}
</p>
</div>
</div>
<div class="bottom">
<Tags :top-five-traits="topFiveTraits" :username="t('you')"
:border-color="DimensionColors[topDimension]"
:rarity="rarity" />
<div class="imgs">
<img class="left" :src="t('report.bottomLeft')" alt=""
@click="$i18n.locale == 'zh' ? jumpZh() : jumpEn()">
<div class="right" @click="$emit('next')">
<img :src="t('report.bottomRight')" alt="" class="botton" />
<div :style="{
maskImage: `url(${imgs.report.bottomRightShutter})`,
backgroundColor: GamePageDimensionColors[topDimension]
}"></div>
<img :src="imgs.icons[topDimension]" alt=""
class="dim-icon">
</div>
</div>
</div>
<!-- <img class="share-mask" :src="t('report.shareMask')"
v-if="showShareMask" @click="showShareMask = false" alt="" />
-->
</div>
</template>
<style lang="scss" scoped>
@use '../mixin.scss' as *;
.report.page {
overflow: hidden;
}
.title {
.dim {
margin-inline-start: .3em;
font-size: 1.05em;
}
&:lang(en) {
.dim {
font-size: 1.2em;
margin-inline-start: .4em;
}
.pre {
font-style: italic;
}
}
position: absolute;
top: 5%;
font-size: 1.38rem;
left: 6%;
width: max-content;
}
.right-top {
position: absolute;
top: 7.5%;
left: 27.5%;
width: 65%;
}
.graph {
position: relative;
width: 100%;
}
.description {
width: 100%;
position: relative;
top: -.25rem;
p {
margin: 0;
margin-block-end: 1lh;
text-indent: 2em;
text-wrap: pretty;
&:lang(zh) {
@include font(.80rem, 1.45, pre-wrap);
}
&:lang(en) {
@include font(.80rem, 1.43, pre-wrap);
}
}
}
.bottom {
@include abs-pos(50%, -6.5%);
width: 82%;
display: flex;
flex-direction: column;
align-items: center;
gap: 2.6rem;
.imgs {
width: 100%;
height: 7.0rem;
display: flex;
justify-content: space-around;
align-items: flex-end;
.left {
height: 100%;
}
.right {
height: 100%;
position: relative;
aspect-ratio: 574/411;
&>div {
height: 100%;
width: 100%;
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
}
}
.dim-icon {
position: absolute;
width: 22%;
top: 27.2%;
left: 50%;
transform: translate(-50%, -50%);
}
.botton{
position: absolute;
inset: 0;
height: 100%;
width: 100%;
}
}
&>img {
width: 85%;
}
}
.left-title {
position: absolute;
top: 9.7%;
left: 2.8%;
height: max-content;
display: flex;
flex-direction: column;
align-items: center;
span.zh-title {
font-size: 4rem;
height: 4rem;
}
span.en-title {
font-size: 3.1rem;
writing-mode: vertical-rl;
margin-inline-start: .5rem;
}
img {
display: inline-block;
width: 6.6rem;
height: 6rem;
object-fit: cover;
}
}
.share-mask {
position: absolute;
object-fit: cover;
object-position: top;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99;
}
</style>