update
This commit is contained in:
parent
43c76f2f6b
commit
24cb57ea15
@ -0,0 +1,326 @@
|
|||||||
|
<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>
|
||||||
@ -0,0 +1,281 @@
|
|||||||
|
<template>
|
||||||
|
<view class="supplier-cooperation">
|
||||||
|
<!-- 合作时长分布 -->
|
||||||
|
<view class="chart-title">合作时长分布</view>
|
||||||
|
<view class="chart-section">
|
||||||
|
<view class="chart-container">
|
||||||
|
<ChartLoading v-if="isLoading" text="数据加载中..." />
|
||||||
|
<QiunDataCharts v-else type="pie" :opts="durationPieOpts" :chartData="durationPieData" :canvas2d="true"
|
||||||
|
:inScrollView="true" canvasId="durationPieChart" tooltipFormat="durationPieChart" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 供应商依赖度 -->
|
||||||
|
<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="dependencyOpts" :chartData="dependencyData" :canvas2d="true"
|
||||||
|
:inScrollView="true" canvasId="dependencyChart" tooltipFormat="dependencyChart" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 合作统计卡片 -->
|
||||||
|
<view class="cooperation-cards">
|
||||||
|
<view class="cooperation-card long-term">
|
||||||
|
<view class="cooperation-icon">🤝</view>
|
||||||
|
<view class="cooperation-content">
|
||||||
|
<text class="cooperation-title">长期合作</text>
|
||||||
|
<view class="cooperation-value">
|
||||||
|
<text class="cooperation-number">{{ cooperationData.longTerm || 0 }}</text>
|
||||||
|
<text class="cooperation-unit">个</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cooperation-card new-supplier">
|
||||||
|
<view class="cooperation-icon">✨</view>
|
||||||
|
<view class="cooperation-content">
|
||||||
|
<text class="cooperation-title">新增供应商</text>
|
||||||
|
<view class="cooperation-value">
|
||||||
|
<text class="cooperation-number">{{ cooperationData.newSuppliers || 0 }}</text>
|
||||||
|
<text class="cooperation-unit">个</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</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,
|
||||||
|
cooperationData: {
|
||||||
|
longTerm: 68,
|
||||||
|
newSuppliers: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
selectTime: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
// 合作时长分布数据
|
||||||
|
durationPieData() {
|
||||||
|
return {
|
||||||
|
series: [{
|
||||||
|
data: [
|
||||||
|
{ name: '3年以上', value: 45 },
|
||||||
|
{ name: '1-3年', value: 38 },
|
||||||
|
{ name: '1年以内', value: 45 }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 合作时长分布配置
|
||||||
|
durationPieOpts() {
|
||||||
|
return {
|
||||||
|
color: ['#9B7EDE', '#52C41A', '#1890FF'],
|
||||||
|
padding: [15, 15, 15, 15],
|
||||||
|
dataLabel: false,
|
||||||
|
legend: {
|
||||||
|
show: true,
|
||||||
|
position: 'right',
|
||||||
|
float: 'center',
|
||||||
|
padding: 5,
|
||||||
|
margin: 10
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
pie: {
|
||||||
|
activeOpacity: 0.5,
|
||||||
|
activeRadius: 10,
|
||||||
|
offsetAngle: 0,
|
||||||
|
labelWidth: 0,
|
||||||
|
border: true,
|
||||||
|
borderWidth: 0,
|
||||||
|
borderColor: '#FFFFFF'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 供应商依赖度数据
|
||||||
|
dependencyData() {
|
||||||
|
return {
|
||||||
|
categories: ['供应商A', '供应商B', '供应商C', '供应商D', '供应商E'],
|
||||||
|
series: [{
|
||||||
|
name: '销售占比',
|
||||||
|
data: [28, 22, 18, 15, 12]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 供应商依赖度配置
|
||||||
|
dependencyOpts() {
|
||||||
|
return {
|
||||||
|
color: ['#FF8F6F'],
|
||||||
|
padding: [15, 15, 15, 15],
|
||||||
|
dataLabel: false,
|
||||||
|
xAxis: {
|
||||||
|
disableGrid: true,
|
||||||
|
itemCount: 5,
|
||||||
|
fontSize: 10
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
gridType: 'dash',
|
||||||
|
showTitle: true,
|
||||||
|
data: [{
|
||||||
|
min: 0,
|
||||||
|
max: 30,
|
||||||
|
title: '占比(%)',
|
||||||
|
titleFontSize: 12,
|
||||||
|
titleOffsetY: -5
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
column: {
|
||||||
|
type: 'group',
|
||||||
|
width: 15,
|
||||||
|
barBorderCircle: true,
|
||||||
|
linearType: 'custom',
|
||||||
|
customColor: ['#FF8F6F', '#FF6B45']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onReady() {
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async loadData() {
|
||||||
|
this.isLoading = true
|
||||||
|
setTimeout(() => {
|
||||||
|
this.isLoading = false
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
@text-primary: #333;
|
||||||
|
@text-secondary: #666;
|
||||||
|
@bg-white: #ffffff;
|
||||||
|
|
||||||
|
.supplier-cooperation {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cooperation-cards {
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cooperation-card {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 16rpx 24rpx;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24rpx;
|
||||||
|
|
||||||
|
&.long-term {
|
||||||
|
background: linear-gradient(135deg, #9B7EDE, #B794F4);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.new-supplier {
|
||||||
|
background: linear-gradient(135deg, #1890FF, #40A9FF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cooperation-icon {
|
||||||
|
font-size: 48rpx;
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cooperation-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cooperation-title {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cooperation-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cooperation-number {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cooperation-unit {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,265 @@
|
|||||||
|
<template>
|
||||||
|
<view class="supplier-overview">
|
||||||
|
<view class="section-title">供应链概览</view>
|
||||||
|
|
||||||
|
<!-- 核心KPI卡片 -->
|
||||||
|
<view class="metrics-row">
|
||||||
|
<view class="metric-card">
|
||||||
|
<text class="metric-value" style="color: #9B7EDE;">{{ kpiData.totalSuppliers || 0 }}</text>
|
||||||
|
<text class="metric-label">合作供应商/个</text>
|
||||||
|
</view>
|
||||||
|
<view class="metric-card">
|
||||||
|
<text class="metric-value" style="color: #52C41A;">{{ kpiData.avgDeliveryRate || 0 }}%</text>
|
||||||
|
<text class="metric-label">平均送达率</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="metrics-row">
|
||||||
|
<view class="metric-card">
|
||||||
|
<text class="metric-value" style="color: #1890FF;">{{ kpiData.inventoryTurnover || 0 }}</text>
|
||||||
|
<text class="metric-label">库存周转/天</text>
|
||||||
|
</view>
|
||||||
|
<view class="metric-card">
|
||||||
|
<text class="metric-value" style="color: #FF8F6F;">¥{{ formatMoney(kpiData.monthlyPurchase) }}</text>
|
||||||
|
<text class="metric-label">本月采购额</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 供应商类别分布 -->
|
||||||
|
<view class="chart-title">供应商类别分布</view>
|
||||||
|
<view class="chart-section">
|
||||||
|
<view class="chart-container">
|
||||||
|
<!-- 图表加载效果 -->
|
||||||
|
<ChartLoading v-if="isLoading" text="数据加载中..." />
|
||||||
|
<!-- 实际饼图 -->
|
||||||
|
<QiunDataCharts v-else type="pie" :opts="categoryPieOpts" :chartData="categoryPieData" :canvas2d="true"
|
||||||
|
:inScrollView="true" canvasId="supplierCategoryPie" tooltipFormat="supplierCategoryPie" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 预警提示 -->
|
||||||
|
<!-- <view class="alert-card">
|
||||||
|
<view class="alert-icon">⚠️</view>
|
||||||
|
<view class="alert-content">
|
||||||
|
<text class="alert-title">预警提示</text>
|
||||||
|
<view class="alert-value">
|
||||||
|
<text class="alert-number">{{ alertData.totalAlerts || 0 }}</text>
|
||||||
|
<text class="alert-unit">个异常</text>
|
||||||
|
</view>
|
||||||
|
</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,
|
||||||
|
kpiData: {
|
||||||
|
totalSuppliers: 128,
|
||||||
|
avgDeliveryRate: 95.6,
|
||||||
|
inventoryTurnover: 12,
|
||||||
|
monthlyPurchase: 2800000
|
||||||
|
},
|
||||||
|
alertData: {
|
||||||
|
totalAlerts: 3
|
||||||
|
},
|
||||||
|
categoryData: [
|
||||||
|
{ name: '食品供应商', value: 35 },
|
||||||
|
{ name: '日用品供应商', value: 28 },
|
||||||
|
{ name: '服务类供应商', value: 22 },
|
||||||
|
{ name: '设备供应商', value: 18 },
|
||||||
|
{ name: '其他', value: 25 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
selectTime: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
// 供应商类别饼图数据
|
||||||
|
categoryPieData() {
|
||||||
|
return {
|
||||||
|
series: [{
|
||||||
|
data: this.categoryData.filter(item => item.value > 0)
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 供应商类别饼图配置
|
||||||
|
categoryPieOpts() {
|
||||||
|
return {
|
||||||
|
color: ['#9B7EDE', '#52C41A', '#1890FF', '#FF8F6F', '#FAAD14'],
|
||||||
|
padding: [15, 15, 15, 15],
|
||||||
|
dataLabel: false,
|
||||||
|
legend: {
|
||||||
|
show: true,
|
||||||
|
position: 'right',
|
||||||
|
float: 'center',
|
||||||
|
padding: 5,
|
||||||
|
margin: 10
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
pie: {
|
||||||
|
activeOpacity: 0.5,
|
||||||
|
activeRadius: 10,
|
||||||
|
labelWidth: 0,
|
||||||
|
border: true,
|
||||||
|
borderWidth: 0,
|
||||||
|
borderColor: '#FFFFFF'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onReady() {
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async loadData() {
|
||||||
|
this.isLoading = true
|
||||||
|
// TODO: 实际API调用
|
||||||
|
setTimeout(() => {
|
||||||
|
this.isLoading = false
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 格式化金额,添加千分号
|
||||||
|
formatMoney(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-overview {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: @text-primary;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metrics-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-card {
|
||||||
|
flex: 1;
|
||||||
|
background: @bg-white;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 16rpx;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-label {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: @text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: @text-primary;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-card {
|
||||||
|
background: linear-gradient(135deg, #FF8F6F, #FF4D4F);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 16rpx 24rpx;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-icon {
|
||||||
|
font-size: 48rpx;
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-title {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-number {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-unit {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,297 @@
|
|||||||
|
<template>
|
||||||
|
<view class="supplier-performance">
|
||||||
|
<!-- 送达率趋势 -->
|
||||||
|
<view class="chart-title">送达率趋势</view>
|
||||||
|
<view class="chart-section">
|
||||||
|
<view class="chart-container">
|
||||||
|
<ChartLoading v-if="isLoading" text="数据加载中..." />
|
||||||
|
<QiunDataCharts v-else type="line" :opts="deliveryTrendOpts" :chartData="deliveryTrendData"
|
||||||
|
:canvas2d="true" :inScrollView="true" canvasId="deliveryTrendChart"
|
||||||
|
:tooltipFormat="formatDeliveryTooltip" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 供应商评分TOP10 -->
|
||||||
|
<view class="chart-title">供应商评分TOP10</view>
|
||||||
|
<view class="chart-section">
|
||||||
|
<view class="chart-container">
|
||||||
|
<ChartLoading v-if="isLoading" text="数据加载中..." />
|
||||||
|
<QiunDataCharts v-else type="bar" :opts="scoreRankOpts" :chartData="scoreRankData" :canvas2d="true"
|
||||||
|
:inScrollView="true" canvasId="scoreRankChart" tooltipFormat="scoreRankChart" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 绩效统计卡片 -->
|
||||||
|
<view class="performance-cards">
|
||||||
|
<view class="performance-card excellent">
|
||||||
|
<view class="performance-icon">✓</view>
|
||||||
|
<view class="performance-content">
|
||||||
|
<text class="performance-title">优秀供应商</text>
|
||||||
|
<view class="performance-value">
|
||||||
|
<text class="performance-number">{{ performanceData.excellent || 0 }}</text>
|
||||||
|
<text class="performance-unit">个</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="performance-card warning">
|
||||||
|
<view class="performance-icon">!</view>
|
||||||
|
<view class="performance-content">
|
||||||
|
<text class="performance-title">待改进</text>
|
||||||
|
<view class="performance-value">
|
||||||
|
<text class="performance-number">{{ performanceData.needImprovement || 0 }}</text>
|
||||||
|
<text class="performance-unit">个</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</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,
|
||||||
|
performanceData: {
|
||||||
|
excellent: 85,
|
||||||
|
needImprovement: 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
selectTime: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
// 送达率趋势数据
|
||||||
|
deliveryTrendData() {
|
||||||
|
return {
|
||||||
|
categories: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||||
|
series: [{
|
||||||
|
name: '送达率',
|
||||||
|
data: [92.5, 93.2, 94.1, 95.3, 94.8, 95.6, 96.2, 95.8, 96.5, 97.1, 96.8, 97.3]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 送达率趋势配置
|
||||||
|
deliveryTrendOpts() {
|
||||||
|
return {
|
||||||
|
color: ['#9B7EDE'],
|
||||||
|
padding: [15, 15, 15, 15],
|
||||||
|
dataLabel: false,
|
||||||
|
xAxis: {
|
||||||
|
disableGrid: true,
|
||||||
|
itemCount: 12,
|
||||||
|
fontSize: 10
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
gridType: 'dash',
|
||||||
|
showTitle: true,
|
||||||
|
data: [{
|
||||||
|
min: 90,
|
||||||
|
max: 100,
|
||||||
|
title: '送达率(%)',
|
||||||
|
titleFontSize: 12,
|
||||||
|
titleOffsetY: -5
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
line: {
|
||||||
|
type: 'curve',
|
||||||
|
width: 2,
|
||||||
|
activeType: 'hollow'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 供应商评分数据
|
||||||
|
scoreRankData() {
|
||||||
|
return {
|
||||||
|
categories: ['供应商A', '供应商B', '供应商C', '供应商D', '供应商E', '供应商F', '供应商G', '供应商H', '供应商I', '供应商J'],
|
||||||
|
series: [{
|
||||||
|
name: '综合评分',
|
||||||
|
data: [98, 96, 94, 92, 90, 88, 86, 84, 82, 80]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 供应商评分配置
|
||||||
|
scoreRankOpts() {
|
||||||
|
return {
|
||||||
|
color: ['#52C41A'],
|
||||||
|
padding: [15, 15, 15, 15],
|
||||||
|
dataLabel: true,
|
||||||
|
type: 'bar',
|
||||||
|
xAxis: {
|
||||||
|
boundaryGap: 'justify',
|
||||||
|
disableGrid: false,
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
splitNumber: 5,
|
||||||
|
fontSize: 10
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
data: [{
|
||||||
|
fontSize: 10
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
extra: {
|
||||||
|
bar: {
|
||||||
|
type: 'group',
|
||||||
|
width: 10,
|
||||||
|
barBorderCircle: true,
|
||||||
|
linearType: 'custom',
|
||||||
|
linearOpacity: 1,
|
||||||
|
customColor: ['#52C41A', '#73D13D']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onReady() {
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
async loadData() {
|
||||||
|
this.isLoading = true
|
||||||
|
setTimeout(() => {
|
||||||
|
this.isLoading = false
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 自定义tooltip格式
|
||||||
|
formatDeliveryTooltip(item, category, index, opts) {
|
||||||
|
if (item.data && category) {
|
||||||
|
return `${category} 送达率:${item.data}%`
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
@text-primary: #333;
|
||||||
|
@text-secondary: #666;
|
||||||
|
@bg-white: #ffffff;
|
||||||
|
|
||||||
|
.supplier-performance {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.performance-cards {
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.performance-card {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 16rpx 24rpx;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24rpx;
|
||||||
|
|
||||||
|
&.excellent {
|
||||||
|
background: linear-gradient(135deg, #52C41A, #73D13D);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
background: linear-gradient(135deg, #FF8F6F, #FF4D4F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.performance-icon {
|
||||||
|
font-size: 48rpx;
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.performance-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.performance-title {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.performance-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.performance-number {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.performance-unit {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,310 @@
|
|||||||
|
<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>
|
||||||
@ -125,6 +125,24 @@
|
|||||||
<FestivalRevenueSumInfo />
|
<FestivalRevenueSumInfo />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 供应链生态全景 -->
|
||||||
|
<view v-else-if="tab.key === 'supplierAnalysis'" class="tab-content">
|
||||||
|
<view id="supplier-overview" class="section-anchor"></view>
|
||||||
|
<SupplierOverview :selectTime="selectTime" />
|
||||||
|
|
||||||
|
<view id="supplier-performance" class="section-anchor"></view>
|
||||||
|
<SupplierPerformance :selectTime="selectTime" />
|
||||||
|
|
||||||
|
<view id="supplier-category" class="section-anchor"></view>
|
||||||
|
<SupplierCategory :selectTime="selectTime" />
|
||||||
|
|
||||||
|
<view id="supplier-ranking" class="section-anchor"></view>
|
||||||
|
<SupplierRanking :selectTime="selectTime" />
|
||||||
|
|
||||||
|
<view id="supplier-cooperation" class="section-anchor"></view>
|
||||||
|
<SupplierCooperation :selectTime="selectTime" />
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 商户电商生态全景 -->
|
<!-- 商户电商生态全景 -->
|
||||||
<view v-else-if="tab.key === 'mallOperation'" class="tab-content">
|
<view v-else-if="tab.key === 'mallOperation'" class="tab-content">
|
||||||
<view id="member-mall" class="section-anchor"></view>
|
<view id="member-mall" class="section-anchor"></view>
|
||||||
@ -181,6 +199,11 @@ import SupplierListBox from './components/SupplierListBox.vue'
|
|||||||
import MallOrderStatistics from './components/MallOrderStatistics.vue'
|
import MallOrderStatistics from './components/MallOrderStatistics.vue'
|
||||||
import ThisMonthBenefits from './components/ThisMonthBenefits.vue'
|
import ThisMonthBenefits from './components/ThisMonthBenefits.vue'
|
||||||
import AnalysisOfMember from './components/AnalysisOfMember.vue'
|
import AnalysisOfMember from './components/AnalysisOfMember.vue'
|
||||||
|
import SupplierOverview from './components/SupplierOverview.vue'
|
||||||
|
import SupplierPerformance from './components/SupplierPerformance.vue'
|
||||||
|
import SupplierCategory from './components/SupplierCategory.vue'
|
||||||
|
import SupplierRanking from './components/SupplierRanking.vue'
|
||||||
|
import SupplierCooperation from './components/SupplierCooperation.vue'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
|
|
||||||
@ -210,7 +233,12 @@ export default {
|
|||||||
SupplierListBox,
|
SupplierListBox,
|
||||||
MallOrderStatistics,
|
MallOrderStatistics,
|
||||||
ThisMonthBenefits,
|
ThisMonthBenefits,
|
||||||
AnalysisOfMember
|
AnalysisOfMember,
|
||||||
|
SupplierOverview,
|
||||||
|
SupplierPerformance,
|
||||||
|
SupplierCategory,
|
||||||
|
SupplierRanking,
|
||||||
|
SupplierCooperation
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -221,6 +249,7 @@ export default {
|
|||||||
{ name: '运营中心', key: 'business' },
|
{ name: '运营中心', key: 'business' },
|
||||||
{ name: '客群画像', key: 'customerProfile' },
|
{ name: '客群画像', key: 'customerProfile' },
|
||||||
{ name: '经营分析', key: 'businessRevenue' },
|
{ name: '经营分析', key: 'businessRevenue' },
|
||||||
|
{ name: '供应链生态', key: 'supplierAnalysis' },
|
||||||
{ name: '电商生态', key: 'mallOperation' },
|
{ name: '电商生态', key: 'mallOperation' },
|
||||||
],
|
],
|
||||||
// 各个Tab对应的导航栏数据
|
// 各个Tab对应的导航栏数据
|
||||||
@ -249,6 +278,13 @@ export default {
|
|||||||
{ id: 'business-structure', name: '业态' },// 业态结构
|
{ id: 'business-structure', name: '业态' },// 业态结构
|
||||||
{ id: 'festival-revenue-sum-info', name: '节假日' },// 节假日营收
|
{ id: 'festival-revenue-sum-info', name: '节假日' },// 节假日营收
|
||||||
],
|
],
|
||||||
|
supplierAnalysis: [
|
||||||
|
{ id: 'supplier-overview', name: '概览' },// 供应商概览
|
||||||
|
{ id: 'supplier-performance', name: '绩效' },// 供应商绩效
|
||||||
|
{ id: 'supplier-category', name: '分类' },// 供应商分类
|
||||||
|
{ id: 'supplier-ranking', name: '排名' },// 供应商排名
|
||||||
|
{ id: 'supplier-cooperation', name: '合作' },// 合作分析
|
||||||
|
],
|
||||||
mallOperation: [
|
mallOperation: [
|
||||||
{ id: 'member-mall', name: '商城' },// 会员商城
|
{ id: 'member-mall', name: '商城' },// 会员商城
|
||||||
{ id: 'hot-product-list', name: '榜单' },// 商品榜单
|
{ id: 'hot-product-list', name: '榜单' },// 商品榜单
|
||||||
@ -263,6 +299,7 @@ export default {
|
|||||||
business: '#6F86FF',
|
business: '#6F86FF',
|
||||||
customerProfile: '#FF8F6F',
|
customerProfile: '#FF8F6F',
|
||||||
businessRevenue: '#38C9A4',
|
businessRevenue: '#38C9A4',
|
||||||
|
supplierAnalysis: '#9B7EDE',
|
||||||
mallOperation: '#F1C84C'
|
mallOperation: '#F1C84C'
|
||||||
},
|
},
|
||||||
// 当前活动的导航项
|
// 当前活动的导航项
|
||||||
@ -276,6 +313,7 @@ export default {
|
|||||||
business: '',
|
business: '',
|
||||||
customerProfile: '',
|
customerProfile: '',
|
||||||
businessRevenue: '',
|
businessRevenue: '',
|
||||||
|
supplierAnalysis: '',
|
||||||
mallOperation: ''
|
mallOperation: ''
|
||||||
},
|
},
|
||||||
tabScrollPosition: 0,
|
tabScrollPosition: 0,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user