ylj20011123 24cb57ea15 update
2025-11-25 11:30:18 +08:00

311 lines
8.5 KiB
Vue

<template>
<view class="supplier-ranking">
<!-- 供应商销量TOP10 -->
<view class="chart-title">供应商销量TOP10</view>
<view class="ranking-cards">
<view v-for="(item, index) in supplierRanking" :key="index" class="ranking-card">
<view class="ranking-medal">
<text v-if="index < 3" class="medal-icon">{{ getMedalIcon(index) }}</text>
<text v-else class="medal-number">{{ index + 1 }}</text>
</view>
<view class="ranking-info">
<text class="ranking-supplier-name">{{ item.name }}</text>
<view class="ranking-data-row">
<view class="data-group">
<text class="data-label">销售额:</text>
<text class="data-value sales">¥{{ item.sales }}</text>
<view class="data-growth" :class="item.growth >= 0 ? 'growth-up' : 'growth-down'">
<text class="growth-arrow">{{ item.growth >= 0 ? '↑' : '↓' }}</text>
<text class="growth-value">{{ Math.abs(item.growth) }}%</text>
</view>
</view>
<view class="data-divider"></view>
<view class="data-group">
<text class="data-label">销量:</text>
<text class="data-value quantity">{{ item.quantity }}</text>
<view class="data-growth" :class="item.quantityGrowth >= 0 ? 'growth-up' : 'growth-down'">
<text class="growth-arrow">{{ item.quantityGrowth >= 0 ? '↑' : '↓' }}</text>
<text class="growth-value">{{ Math.abs(item.quantityGrowth) }}%</text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 品类销量TOP5 -->
<view class="chart-title">品类销量TOP5</view>
<view class="chart-section">
<view class="chart-container">
<ChartLoading v-if="isLoading" text="数据加载中..." />
<QiunDataCharts v-else type="column" :opts="categoryRankOpts" :chartData="categoryRankData"
:canvas2d="true" :inScrollView="true" canvasId="categoryRankChart"
tooltipFormat="categoryRankChart" />
</view>
</view>
</view>
</template>
<script>
import QiunDataCharts from './qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue'
import ChartLoading from './ChartLoading.vue'
export default {
components: {
QiunDataCharts,
ChartLoading
},
data() {
return {
isLoading: false,
supplierRanking: [
{ name: '优质食品供应商', sales: '186.5万', growth: 15.6, quantity: '12,580件', quantityGrowth: 18.2 },
{ name: '日用百货批发商', sales: '158.2万', growth: 12.3, quantity: '9,856件', quantityGrowth: 10.5 },
{ name: '汽车用品专营店', sales: '142.8万', growth: 8.7, quantity: '8,234件', quantityGrowth: 6.8 },
{ name: '文化用品供应商', sales: '128.5万', growth: -2.1, quantity: '7,652件', quantityGrowth: -1.5 },
{ name: '特色商品供应商', sales: '115.3万', growth: 18.9, quantity: '6,890件', quantityGrowth: 22.3 },
{ name: '进口食品供应商', sales: '98.6万', growth: 6.5, quantity: '5,432件', quantityGrowth: 8.2 },
{ name: '地方特产供应商', sales: '86.2万', growth: 22.4, quantity: '4,876件', quantityGrowth: 25.6 },
{ name: '快消品批发商', sales: '75.8万', growth: 4.2, quantity: '4,123件', quantityGrowth: 3.8 },
{ name: '品牌代理商', sales: '68.5万', growth: -5.3, quantity: '3,654件', quantityGrowth: -6.2 },
{ name: '综合供应商', sales: '56.3万', growth: 9.8, quantity: '3,012件', quantityGrowth: 11.5 }
]
}
},
props: {
selectTime: {
type: String,
default: ""
}
},
computed: {
// 品类销量TOP5数据
categoryRankData() {
return {
categories: ['食品饮料', '日用百货', '汽车用品', '文化用品', '其他商品'],
series: [{
name: '销量',
data: [12580, 9856, 8234, 7652, 5432]
}]
}
},
// 品类销量配置
categoryRankOpts() {
return {
color: ['#9B7EDE'],
padding: [15, 15, 15, 15],
dataLabel: false,
xAxis: {
disableGrid: true,
itemCount: 5,
fontSize: 10,
scrollShow: true
},
yAxis: {
gridType: 'dash',
showTitle: true,
data: [{
min: 0,
title: '销量(件)',
titleFontSize: 12,
titleOffsetY: -5
}]
},
legend: {
show: false
},
extra: {
column: {
type: 'group',
width: 15,
barBorderCircle: true,
linearType: 'custom',
customColor: ['#9B7EDE', '#B794F4']
}
}
}
}
},
onReady() {
this.loadData()
},
methods: {
async loadData() {
this.isLoading = true
setTimeout(() => {
this.isLoading = false
}, 500)
},
getMedalIcon(index) {
const medals = ['🥇', '🥈', '🥉']
return medals[index] || ''
}
}
}
</script>
<style scoped lang="less">
@text-primary: #333;
@text-secondary: #666;
@bg-white: #ffffff;
.supplier-ranking {
width: 100%;
}
.section-title {
font-size: 30rpx;
font-weight: 600;
color: @text-primary;
margin-bottom: 12rpx;
}
.chart-title {
font-size: 30rpx;
font-weight: 600;
color: @text-primary;
margin-bottom: 12rpx;
}
.ranking-cards {
background: @bg-white;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
margin-bottom: 24rpx;
}
.ranking-card {
display: flex;
align-items: center;
gap: 16rpx;
padding: 16rpx 0;
border-bottom: 1rpx solid #F0F0F0;
&:last-child {
border-bottom: none;
}
}
.ranking-medal {
width: 56rpx;
height: 56rpx;
display: flex;
align-items: center;
justify-content: center;
}
.medal-icon {
font-size: 40rpx;
}
.medal-number {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
background: #F0F0F0;
color: @text-secondary;
font-size: 24rpx;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
}
.ranking-info {
flex: 1;
}
.ranking-supplier-name {
font-size: 26rpx;
color: @text-primary;
display: block;
margin-bottom: 8rpx;
}
.ranking-data-row {
display: flex;
align-items: center;
gap: 16rpx;
}
.data-group {
display: flex;
align-items: center;
gap: 6rpx;
flex: 1;
}
.data-label {
font-size: 22rpx;
color: @text-secondary;
}
.data-value {
font-size: 22rpx;
font-weight: 600;
&.sales {
color: #9B7EDE;
}
&.quantity {
color: #1890FF;
}
}
.data-divider {
width: 1rpx;
height: 24rpx;
background: #E8E8E8;
}
.data-growth {
display: flex;
align-items: center;
gap: 2rpx;
padding: 2rpx 6rpx;
border-radius: 4rpx;
font-size: 18rpx;
&.growth-up {
background: rgba(82, 196, 26, 0.1);
color: #52C41A;
}
&.growth-down {
background: rgba(255, 77, 79, 0.1);
color: #FF4D4F;
}
}
.growth-arrow {
font-size: 16rpx;
}
.growth-value {
font-weight: 600;
}
.chart-section {
background: @bg-white;
border-radius: 16rpx;
padding: 24rpx 24rpx 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
margin-bottom: 32rpx;
}
.chart-container {
width: 100%;
height: 400rpx;
margin-bottom: 20rpx;
}
</style>