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

327 lines
7.9 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="supplier-category">
<!-- 品类销量排行 -->
<view class="chart-title">品类销量排行</view>
<view class="ranking-list">
<view v-for="(item, index) in categoryRanking" :key="index" class="ranking-item">
<view class="ranking-index"
:class="['rank-' + (index + 1), index === 0 ? 'rank-gold' : index === 1 ? 'rank-silver' : index === 2 ? 'rank-bronze' : '']">
{{ index + 1 }}</view>
<view class="ranking-content">
<text class="ranking-name">{{ item.name }}</text>
<view class="ranking-bar">
<view class="ranking-progress" :style="{ width: item.percentage + '%' }"></view>
</view>
</view>
<view class="ranking-value">
<text class="ranking-amount">¥{{ formatAmount(item.amount) }}</text>
<text class="ranking-percent">{{ item.percentage }}%</text>
</view>
</view>
</view>
<!-- 库存预警 -->
<view class="alert-cards">
<view class="alert-card-item slow">
<view class="alert-card-icon">📦</view>
<view class="alert-card-content">
<text class="alert-card-label">滞销品</text>
<text class="alert-card-value">{{ alertData.slowMoving || 0 }}</text>
</view>
</view>
<view class="alert-card-item shortage">
<view class="alert-card-icon"></view>
<view class="alert-card-content">
<text class="alert-card-label">缺货风险</text>
<text class="alert-card-value">{{ alertData.shortage || 0 }}</text>
</view>
</view>
</view>
<!-- 库存周转率 -->
<view class="chart-title">库存周转率</view>
<view class="chart-section">
<view class="chart-container">
<ChartLoading v-if="isLoading" text="数据加载中..." />
<QiunDataCharts v-else type="column" :opts="turnoverOpts" :chartData="turnoverData" :canvas2d="true"
:inScrollView="true" canvasId="turnoverChart" tooltipFormat="turnoverChart" />
</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,
categoryRanking: [
{ name: '食品饮料', amount: 1568000, percentage: 100 },
{ name: '日用百货', amount: 1285000, percentage: 82 },
{ name: '汽车用品', amount: 982000, percentage: 63 },
{ name: '文化用品', amount: 763000, percentage: 49 },
{ name: '其他商品', amount: 456000, percentage: 29 }
],
alertData: {
slowMoving: 23,
shortage: 5
}
}
},
props: {
selectTime: {
type: String,
default: ""
}
},
computed: {
// 库存周转率数据
turnoverData() {
return {
categories: ['食品', '日用', '汽车', '文化', '其他'],
series: [{
name: '周转天数',
data: [8, 12, 15, 18, 25]
}]
}
},
// 库存周转率配置
turnoverOpts() {
return {
color: ['#1890FF'],
padding: [15, 15, 15, 15],
dataLabel: true,
xAxis: {
disableGrid: true,
itemCount: 5,
fontSize: 10
},
yAxis: {
gridType: 'dash',
showTitle: true,
data: [{
min: 0,
title: '周转天数',
titleFontSize: 12,
titleOffsetY: -5
}]
},
legend: {
show: false
},
extra: {
column: {
type: 'group',
width: 15,
barBorderCircle: true
}
}
}
}
},
onReady() {
this.loadData()
},
methods: {
async loadData() {
this.isLoading = true
setTimeout(() => {
this.isLoading = false
}, 500)
},
// 格式化金额
formatAmount(amount) {
if (!amount && amount !== 0) return '0'
return Number(amount).toLocaleString('zh-CN')
}
}
}
</script>
<style scoped lang="less">
@text-primary: #333;
@text-secondary: #666;
@bg-white: #ffffff;
.supplier-category {
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-list {
background: @bg-white;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
margin-bottom: 24rpx;
}
.ranking-item {
display: flex;
align-items: center;
gap: 16rpx;
margin-bottom: 24rpx;
&:last-child {
margin-bottom: 0;
}
}
.ranking-index {
width: 48rpx;
height: 48rpx;
border-radius: 50%;
background: #E8E8E8;
color: @text-primary;
font-size: 24rpx;
font-weight: 600;
display: flex;
align-items: center;
justify-content: center;
&.rank-gold {
background: linear-gradient(135deg, #FFD700, #FFA500);
color: #fff;
}
&.rank-silver {
background: linear-gradient(135deg, #C0C0C0, #A8A8A8);
color: #fff;
}
&.rank-bronze {
background: linear-gradient(135deg, #CD7F32, #B8860B);
color: #fff;
}
}
.ranking-content {
flex: 1;
}
.ranking-name {
font-size: 26rpx;
color: @text-primary;
display: block;
margin-bottom: 8rpx;
}
.ranking-bar {
width: 100%;
height: 16rpx;
background: #F0F0F0;
border-radius: 8rpx;
overflow: hidden;
}
.ranking-progress {
height: 100%;
background: linear-gradient(90deg, #9B7EDE, #B794F4);
border-radius: 8rpx;
transition: width 0.3s ease;
}
.ranking-value {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.ranking-amount {
font-size: 26rpx;
font-weight: 600;
color: @text-primary;
}
.ranking-percent {
font-size: 22rpx;
color: @text-secondary;
}
.alert-cards {
display: flex;
gap: 24rpx;
margin-bottom: 24rpx;
}
.alert-card-item {
flex: 1;
background: @bg-white;
border-radius: 16rpx;
padding: 24rpx;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
text-align: center;
&.slow {
border-left: 6rpx solid #FAAD14;
}
&.shortage {
border-left: 6rpx solid #FF4D4F;
}
}
.alert-card-icon {
font-size: 48rpx;
margin-bottom: 12rpx;
}
.alert-card-content {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.alert-card-label {
font-size: 24rpx;
color: @text-secondary;
}
.alert-card-value {
font-size: 28rpx;
font-weight: 600;
color: @text-primary;
}
.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>