Skip to content

Commit 158a02b

Browse files
✨ 补齐 v1 tetrio rank
1 parent b0b5a39 commit 158a02b

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed

src/pages/v1/tetrio/rank/index.vue

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<script lang="ts" setup>
2+
import { asyncComputed } from '@vueuse/core';
3+
import { isNonNullish } from 'remeda';
4+
import { z } from 'zod';
5+
import { Rank, ValidRank } from '~/types/rank';
6+
7+
const data = useData(
8+
z
9+
.object({
10+
items: z.record(
11+
ValidRank,
12+
z.object({
13+
trending: z.number(),
14+
require_tr: z.number(),
15+
players: z.number(),
16+
}),
17+
),
18+
updated_at: z.coerce.date(),
19+
})
20+
.readonly(),
21+
);
22+
23+
const colorMappings: Record<
24+
Rank,
25+
{
26+
readonly background: string;
27+
readonly text: string;
28+
}
29+
> = {
30+
'x+': {
31+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #D946EF 0%, #F5CFFE 100%)',
32+
text: '#8E23B4CC',
33+
},
34+
x: {
35+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #D946EF 0%, #F5CFFE 100%)',
36+
text: '#8E23B4CC',
37+
},
38+
u: {
39+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #F04444 0%, #FECBCA 100%)',
40+
text: '#7F1D1CCC',
41+
},
42+
ss: {
43+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #E9B308 0%, #FEF18B 100%)',
44+
text: '#723F12CC',
45+
},
46+
's+': {
47+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #E9B308 0%, #FEF18B 100%)',
48+
text: '#723F12CC',
49+
},
50+
s: {
51+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #E9B308 0%, #FEF18B 100%)',
52+
text: '#723F12CC',
53+
},
54+
's-': {
55+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #E9B308 0%, #FEF18B 100%)',
56+
text: '#723F12CC',
57+
},
58+
'a+': {
59+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #23C55E 0%, #BBF7D1 100%)',
60+
text: '#15532ECC',
61+
},
62+
a: {
63+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #23C55E 0%, #BBF7D1 100%)',
64+
text: '#15532ECC',
65+
},
66+
'a-': {
67+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #23C55E 0%, #BBF7D1 100%)',
68+
text: '#15532ECC',
69+
},
70+
'b+': {
71+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #3B82F6 0%, #BFDCFE 100%)',
72+
text: '#1F3A8B',
73+
},
74+
b: {
75+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #3B82F6 0%, #BFDCFE 100%)',
76+
text: '#1F3A8B',
77+
},
78+
'b-': {
79+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #3B82F6 0%, #BFDCFE 100%)',
80+
text: '#1F3A8B',
81+
},
82+
'c+': {
83+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #A755F7 0%, #EAD5FF 100%)',
84+
text: '#571C86',
85+
},
86+
c: {
87+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #A755F7 0%, #EAD5FF 100%)',
88+
text: '#571C86',
89+
},
90+
'c-': {
91+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #A755F7 0%, #EAD5FF 100%)',
92+
text: '#571C86',
93+
},
94+
'd+': {
95+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #64748B 0%, #E1E8F0 100%)',
96+
text: '#0F172A',
97+
},
98+
d: {
99+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #64748B 0%, #E1E8F0 100%)',
100+
text: '#0F172A',
101+
},
102+
z: {
103+
background: 'radial-gradient(95.42% 572.5% at 4.58% 17.5%, #737373 0%, #E5E5E5 100%)',
104+
text: '#171717',
105+
},
106+
};
107+
108+
const rankImageMap = asyncComputed(async () => {
109+
return Object.fromEntries(
110+
await Promise.all(
111+
Object.keys(data.items).map(async (rank) => {
112+
const name = rank.toLowerCase();
113+
114+
return [
115+
rank,
116+
await import(`~/assets/images/rank/${name}.svg?url`).then((module) => {
117+
return module.default;
118+
}),
119+
];
120+
}),
121+
),
122+
);
123+
}, {});
124+
</script>
125+
126+
<template>
127+
<div id="content" class="w-fit p-6.25 bg-[#f1f1f1]">
128+
<span class="font-template text-8.75 font-black">Rankings</span>
129+
130+
<div class="flex flex-col gap-2.5">
131+
<div
132+
v-for="(rank, name) in data.items"
133+
:style="{ backgroundImage: colorMappings[name].background }"
134+
class="w-150 h-25 rounded-7.5 relative shadow-[0_1.25rem_3rem_0_#00000026]"
135+
>
136+
<div v-if="rank !== undefined" class="p-6.25 flex gap-21.25 items-center">
137+
<div>
138+
<img
139+
v-if="isNonNullish(rankImageMap[name])"
140+
:alt="name"
141+
:src="rankImageMap[name]"
142+
class="w-12.5 h-12.5"
143+
/>
144+
</div>
145+
146+
<div :style="{ color: colorMappings[name].text }" class="font-template w-25 text-8 font-bold">
147+
{{ rank.trending > 0 ? '↑' : rank.trending < 0 ? '↓' : '→' }}{{ Math.abs(rank.trending) }}
148+
</div>
149+
150+
<div
151+
:style="{ color: colorMappings[name].text }"
152+
class="w-57.5 text-right leading-none absolute right-6.25"
153+
>
154+
<span class="font-template font-extrabold text-11.25">{{ rank.require_tr }}</span>
155+
<br />
156+
<span class="font-template text-7.5">{{ rank.players }} players</span>
157+
</div>
158+
</div>
159+
</div>
160+
</div>
161+
162+
<div class="font-template w-150 h-12.5 font-bold text-7.5 flex flex-col justify-center items-center">
163+
Updated on {{ data.updated_at.toLocaleString('zh-CN') }}
164+
</div>
165+
</div>
166+
</template>
167+
168+
<style lang="scss">
169+
@use '~/styles/v1';
170+
</style>

src/pages/v1/tetrio/rank/test.vue

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<script lang="ts" setup>
2+
import type { VNode } from 'vue';
3+
import V1TetrioRank from '~/pages/v1/tetrio/rank/index.vue';
4+
5+
const pages = ref<VNode[]>([]);
6+
7+
onMounted(async () => {
8+
window.__DATA__ = JSON.stringify({
9+
items: {
10+
'x+': { trending: 5, require_tr: 25000, players: 100 },
11+
x: { trending: -3, require_tr: 24000, players: 200 },
12+
u: { trending: 0, require_tr: 23000, players: 300 },
13+
},
14+
updated_at: new Date(),
15+
});
16+
17+
await nextTick();
18+
19+
const rendered = h(V1TetrioRank);
20+
21+
pages.value.push(rendered);
22+
23+
await nextTick();
24+
});
25+
</script>
26+
27+
<template>
28+
<div class="flex flex-col p-2 gap-2">
29+
<template v-for="page in pages">
30+
<Component :is="page" />
31+
</template>
32+
</div>
33+
</template>

0 commit comments

Comments
 (0)