loreal-survey/src/views/ReportMask.vue
2025-07-29 07:47:22 +08:00

275 lines
7.1 KiB
Vue

<script setup lang="ts">
import imgs from '../assets/imgs'
import Tags from '../components/Tags.vue'
import { DimensionColors, DimensionName, findTraitDimension, 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(['back'])
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.includes('zh')" class="zh-title"
v-for="c in lang.zh_CN.questionData.DimensionName[topDimension].split('')">
{{ c }}</span>
<span v-else-if="$i18n.locale.includes('ja')" class="zh-title"
v-for="c in lang.ja.questionData.DimensionName[topDimension].split('')">
{{ c }}</span>
<span v-else 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)'"
:enableAnimation="false" />
<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="username" :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="showShareMask = true" :style="{
maskImage: `url(${t('report.bottomRight')})`,
backgroundImage: `linear-gradient(to bottom, ${GamePageDimensionColors[topDimension]}, ${GamePageDimensionColors[topDimension]} 60%, #fff 61%, #fff)`
}" />
</div> -->
<img :src="t('report.bottom')" alt="">
</div>
<img :src="imgs.back" alt="" class="back" @click="$emit('back')">
</div>
</template>
<style lang="scss" scoped>
@use '../mixin.scss' as *;
.back {
position: absolute;
left: 1.5rem;
bottom: 1.5rem;
width: 2.5rem;
height: 2.5rem;
}
.top-title {
@include abs-pos(50%, 5.5%);
width: 88%;
}
.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: 10.6%;
font-size: 1.38rem;
left: 6%;
width: max-content;
max-width: 90%;
}
.right-top {
position: absolute;
top: 14%;
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_CN"],
&[lang="zh_TW"] {
@include font(.80rem, 1.45, pre-wrap);
}
&[lang="en"] {
@include font(.80rem, 1.43, pre-wrap);
}
&[lang="ko"] {
@include font(.75rem, 1.43, pre-wrap);
}
&[lang="ja"] {
@include font(.75rem, 1.43, pre-wrap);
}
}
}
.bottom {
@include abs-pos(50%, -5.5%);
width: 82%;
display: flex;
flex-direction: column;
align-items: center;
gap: 2.2rem;
/* .imgs {
width: 100%;
height: 7rem;
display: flex;
justify-content: space-around;
align-items: flex-end;
.left {
height: 100%;
}
.right {
height: 100%;
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
aspect-ratio: 1/1.2;
}
} */
&>img {
width: 80%;
position: relative;
left: .5rem;
}
}
.left-title {
position: absolute;
top: 14.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: 2.9rem;
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>