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

266 lines
6.6 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-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>