feat(dashboard): LevelDistribution 5个conic-gradient环形图
This commit is contained in:
parent
e2555dc015
commit
1dbdcc5e20
@ -5,12 +5,16 @@
|
|||||||
<!-- TOP 5 -->
|
<!-- TOP 5 -->
|
||||||
<TopFiveAssets :items="topFive || []" />
|
<TopFiveAssets :items="topFive || []" />
|
||||||
|
|
||||||
<!-- 后续 Task 11/12 在此追加 LevelDistribution / UpcomingUpgrades / RecentUpgrades -->
|
<!-- 等级分布 -->
|
||||||
|
<LevelDistribution :items="levels" />
|
||||||
|
|
||||||
|
<!-- 后续 Task 12 在此追加 UpcomingUpgrades / RecentUpgrades -->
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import TopFiveAssets from './TopFiveAssets.vue'
|
import TopFiveAssets from './TopFiveAssets.vue'
|
||||||
|
import LevelDistribution from './LevelDistribution.vue'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
topFive: { type: Array, default: () => [] },
|
topFive: { type: Array, default: () => [] },
|
||||||
|
|||||||
145
frontend/pages/dashboard/components/LevelDistribution.vue
Normal file
145
frontend/pages/dashboard/components/LevelDistribution.vue
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
<template>
|
||||||
|
<view class="level-distribution">
|
||||||
|
<text class="card-title">藏品等级分布</text>
|
||||||
|
<view v-if="!items || items.length === 0" class="empty-row">
|
||||||
|
<text class="empty-text">暂无数据</text>
|
||||||
|
</view>
|
||||||
|
<view v-else class="ring-row">
|
||||||
|
<view
|
||||||
|
v-for="item in items"
|
||||||
|
:key="item.level"
|
||||||
|
class="ring-cell"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="ring-outer"
|
||||||
|
:style="getRingStyle(item)"
|
||||||
|
>
|
||||||
|
<view class="ring-inner">
|
||||||
|
<text class="ring-count">{{ item.count }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="ring-label">{{ item.level }}</text>
|
||||||
|
<text class="ring-pct">{{ getPercent(item) }}%</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
items: { type: Array, default: () => [] }, // AssetLevelItem[]
|
||||||
|
})
|
||||||
|
|
||||||
|
function getPercent(item) {
|
||||||
|
if (!item.total) return 0
|
||||||
|
return Math.round((item.count / item.total) * 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRingStyle(item) {
|
||||||
|
const pct = getPercent(item)
|
||||||
|
const colorMap = {
|
||||||
|
UR: '#FF8A65, #FFD740',
|
||||||
|
SSR: '#FF5E9C, #FFB199',
|
||||||
|
SR: '#B17BFF, #FF8FE6',
|
||||||
|
R: '#5EDFFF, #6FA9FF',
|
||||||
|
N: '#C5C5C5, #8C8C8C',
|
||||||
|
}
|
||||||
|
const colors = colorMap[item.level] || '#999, #ccc'
|
||||||
|
// 占位 0 显示灰色环
|
||||||
|
if (pct === 0) {
|
||||||
|
return {
|
||||||
|
background: 'conic-gradient(rgba(255,255,255,0.1) 0deg, rgba(255,255,255,0.1) 360deg)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 渐变环:从顶部开始,pct% 处停止
|
||||||
|
return {
|
||||||
|
background: `conic-gradient(${colors} 0deg ${pct * 3.6}deg, rgba(255,255,255,0.1) ${pct * 3.6}deg 360deg)`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.level-distribution {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 17rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-cell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-outer {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
box-shadow: 0 0 12px rgba(255, 255, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-inner {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-count {
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #FFFABD;
|
||||||
|
font-family: 'Baloo Bhai', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-label {
|
||||||
|
margin-top: 8rpx;
|
||||||
|
font-size: 20rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-pct {
|
||||||
|
font-size: 18rpx;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
margin-top: 2rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-row {
|
||||||
|
height: 120rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user