From 0ad2c4106d6f570e0ca63c8fe5093e6f97492534 Mon Sep 17 00:00:00 2001
From: maven <2163098428@qq.com>
Date: 星期六, 11 十月 2025 17:44:10 +0800
Subject: [PATCH] yys 1.修改销售出库-煤种选中问题 2.采购管理增加车牌字段
---
src/views/productionControl/reportAnalysis/index.vue | 688 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 688 insertions(+), 0 deletions(-)
diff --git a/src/views/productionControl/reportAnalysis/index.vue b/src/views/productionControl/reportAnalysis/index.vue
new file mode 100644
index 0000000..e6533c6
--- /dev/null
+++ b/src/views/productionControl/reportAnalysis/index.vue
@@ -0,0 +1,688 @@
+<template>
+ <div class="coal-blending-efficiency">
+ <div class="page-header">
+ <div class="search-form">
+ <el-form :inline="true" :model="searchParams" class="demo-form-inline">
+ <el-form-item label="鏃堕棿鑼冨洿">
+ <el-date-picker
+ v-model="searchParams.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ :shortcuts="dateShortcuts"
+ />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleSearch" :loading="loading">鏌ヨ</el-button>
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ </div>
+
+ <!-- 缁熻鍗$墖鍖哄煙 -->
+ <div class="stats-cards">
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-s-operation"></i>
+ </div>
+ <div class="card-content">
+ <div class="card-title">鍗曚綅鐑�艰�楃叅閲�</div>
+ <div class="card-value">{{ unitHeatCoalConsumption.toFixed(2) }} kg/GJ</div>
+ <div class="card-desc">瓒婁綆瓒婂ソ</div>
+ </div>
+ </div>
+
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-check-circle"></i>
+ </div>
+ <div class="card-content">
+ <div class="card-title">鏁翠綋杈炬爣鐜�</div>
+ <div class="card-value">{{ overallComplianceRate.toFixed(2) }}%</div>
+ <div class="card-desc">鍙戠儹閲忊墺5000澶у崱</div>
+ </div>
+ </div>
+
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-data-line"></i>
+ </div>
+ <div class="card-content">
+ <div class="card-title">骞冲潎鍙戠儹閲�</div>
+ <div class="card-value">{{ averageCalorificValue.toFixed(0) }} 澶у崱</div>
+ <div class="card-desc">瓒婇珮瓒婂ソ</div>
+ </div>
+ </div>
+
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-files"></i>
+ </div>
+ <div class="card-content">
+ <div class="card-title">閰嶆柟浣跨敤棰戞</div>
+ <div class="card-value">{{ totalBatches }} 娆�</div>
+ <div class="card-desc">鏃堕棿鑼冨洿鍐�</div>
+ </div>
+ </div>
+
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-s-data"></i>
+ </div>
+ <div class="card-content">
+ <div class="card-title">鎬绘壒娆�</div>
+ <div class="card-value">{{ totalBatches }}</div>
+ <div class="card-desc">鏃堕棿鑼冨洿鍐�</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 鍥捐〃鍖哄煙 -->
+ <div class="charts-container">
+ <!-- 杈炬爣鐜囪秼鍔垮浘 -->
+ <el-card class="chart-card">
+ <template #header>
+ <div class="card-header">
+ <span>杈炬爣鐜囪秼鍔�</span>
+ </div>
+ </template>
+ <div class="chart-wrapper">
+ <Echarts
+ ref="complianceChartRef"
+ :options="complianceTrendOptions"
+ :chartStyle="{ height: '300px', width: '100%' }"
+ />
+ </div>
+ </el-card>
+
+ <!-- 鐓ょ鍙戠儹閲忓姣� -->
+ <el-card class="chart-card">
+ <template #header>
+ <div class="card-header">
+ <span>鐓ょ鍙戠儹閲忓姣�</span>
+ </div>
+ </template>
+ <div class="chart-wrapper">
+ <Echarts
+ ref="calorificChartRef"
+ :options="calorificValueOptions"
+ :chartStyle="{ height: '300px', width: '100%' }"
+ />
+ </div>
+ </el-card>
+
+ <!-- 閰嶆柟浣跨敤棰戞 -->
+ <el-card class="chart-card">
+ <template #header>
+ <div class="card-header">
+ <span>閰嶆柟浣跨敤棰戞</span>
+ </div>
+ </template>
+ <div class="chart-wrapper">
+ <Echarts
+ ref="recipeChartRef"
+ :options="recipeFrequencyOptions"
+ :chartStyle="{ height: '300px', width: '100%' }"
+ />
+ </div>
+ </el-card>
+
+ <!-- 鍔犲伐寰楃巼鍒嗘瀽 -->
+ <el-card class="chart-card">
+ <template #header>
+ <div class="card-header">
+ <span>鍔犲伐寰楃巼鍒嗘瀽</span>
+ </div>
+ </template>
+ <div class="chart-wrapper">
+ <Echarts
+ ref="yieldChartRef"
+ :options="processingYieldOptions"
+ :chartStyle="{ height: '300px', width: '100%' }"
+ />
+ </div>
+ </el-card>
+
+ <!-- 鎴愭湰缁撴瀯鍥捐氨 -->
+ <el-card class="chart-card cost-structure">
+ <template #header>
+ <div class="card-header">
+ <span>鎴愭湰缁撴瀯鍥捐氨</span>
+ </div>
+ </template>
+ <div class="chart-wrapper">
+ <Echarts
+ ref="costChartRef"
+ :options="costStructureOptions"
+ :chartStyle="{ height: '300px', width: '100%' }"
+ />
+ </div>
+ </el-card>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted, computed } from 'vue'
+import * as echarts from 'echarts'
+import Echarts from '@/components/Echarts/echarts.vue'
+import { ElMessage } from 'element-plus'
+
+
+// 鎼滅储鍙傛暟
+const searchParams = ref({
+ dateRange: []
+})
+
+// 鏃ユ湡蹇嵎閫夐」
+const dateShortcuts = [
+ {
+ text: '杩�7澶�',
+ value: () => {
+ const end = new Date()
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+ return [start, end]
+ }
+ },
+ {
+ text: '杩�30澶�',
+ value: () => {
+ const end = new Date()
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+ return [start, end]
+ }
+ },
+ {
+ text: '鏈湀',
+ value: () => {
+ const end = new Date()
+ const start = new Date(end.getFullYear(), end.getMonth(), 1)
+ return [start, end]
+ }
+ }
+]
+
+// 缁熻鏁版嵁
+const unitHeatCoalConsumption = ref(32.5)
+const overallComplianceRate = ref(85.7)
+const averageCalorificValue = ref(5260)
+const totalBatches = ref(48)
+
+// 妯℃嫙鏁版嵁
+const mockComplianceData = [
+ { date: '2023-06-01', rate: 82 },
+ { date: '2023-06-02', rate: 85 },
+ { date: '2023-06-03', rate: 88 },
+ { date: '2023-06-04', rate: 84 },
+ { date: '2023-06-05', rate: 87 },
+ { date: '2023-06-06', rate: 90 },
+ { date: '2023-06-07', rate: 86 },
+ { date: '2023-06-08', rate: 89 },
+ { date: '2023-06-09', rate: 92 },
+ { date: '2023-06-10', rate: 88 }
+]
+
+const mockCalorificData = [
+ { name: '鐑熺叅', value: 5800 },
+ { name: '鏃犵儫鐓�', value: 6200 },
+ { name: '瑜愮叅', value: 4500 },
+ { name: '璐叅', value: 5300 },
+ { name: '鐦︾叅', value: 5500 }
+]
+
+const mockRecipeData = [
+ { name: '閰嶆柟A (鐑熺叅60%+鏃犵儫鐓�40%)', value: 18 },
+ { name: '閰嶆柟B (鐑熺叅70%+瑜愮叅30%)', value: 12 },
+ { name: '閰嶆柟C (鏃犵儫鐓�50%+璐叅50%)', value: 8 },
+ { name: '閰嶆柟D (鐑熺叅50%+鐦︾叅50%)', value: 6 },
+ { name: '鍏朵粬閰嶆柟', value: 4 }
+]
+
+const mockYieldData = [
+ { name: '鐑熺叅', yield: 85, efficiency: 92 },
+ { name: '鏃犵儫鐓�', yield: 88, efficiency: 89 },
+ { name: '瑜愮叅', yield: 75, efficiency: 78 },
+ { name: '璐叅', yield: 82, efficiency: 85 },
+ { name: '鐦︾叅', yield: 80, efficiency: 87 }
+]
+
+const mockCostData = [
+ { name: '鑰楁潗', value: 45 },
+ { name: '鑳借��', value: 30 },
+ { name: '浜哄姏', value: 25 }
+]
+
+// 杈炬爣鐜囪秼鍔垮浘閰嶇疆
+const complianceTrendOptions = computed(() => ({
+ tooltip: {
+ trigger: 'axis',
+ formatter: '{b}<br/>杈炬爣鐜�: {c}%'
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: mockComplianceData.map(item => item.date),
+ axisLabel: {
+ rotate: 45
+ }
+ },
+ yAxis: {
+ type: 'value',
+ name: '杈炬爣鐜� (%)',
+ min: 70,
+ max: 100
+ },
+ series: [
+ {
+ name: '杈炬爣鐜�',
+ type: 'line',
+ smooth: true,
+ data: mockComplianceData.map(item => item.rate),
+ itemStyle: {
+ color: '#409EFF'
+ },
+ lineStyle: {
+ width: 3
+ },
+ areaStyle: {
+ color: {
+ type: 'linear',
+ x: 0,
+ y: 0,
+ x2: 0,
+ y2: 1,
+ colorStops: [{
+ offset: 0,
+ color: 'rgba(64, 158, 255, 0.3)'
+ }, {
+ offset: 1,
+ color: 'rgba(64, 158, 255, 0.05)'
+ }]
+ }
+ }
+ }
+ ]
+}))
+
+// 鐓ょ鍙戠儹閲忓姣斿浘閰嶇疆
+const calorificValueOptions = computed(() => ({
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow'
+ },
+ formatter: '{b}<br/>鍙戠儹閲�: {c} 澶у崱'
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: mockCalorificData.map(item => item.name)
+ },
+ yAxis: {
+ type: 'value',
+ name: '鍙戠儹閲� (澶у崱)'
+ },
+ series: [
+ {
+ name: '鍙戠儹閲�',
+ type: 'bar',
+ data: mockCalorificData.map(item => item.value),
+ itemStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ { offset: 0, color: '#FF6B81' },
+ { offset: 1, color: '#FF8E53' }
+ ])
+ },
+ label: {
+ show: true,
+ position: 'top',
+ formatter: '{c}澶у崱'
+ }
+ }
+ ]
+}))
+
+// 閰嶆柟浣跨敤棰戞鍥鹃厤缃�
+const recipeFrequencyOptions = computed(() => ({
+ tooltip: {
+ trigger: 'item',
+ formatter: '{b}: {c}娆� ({d}%)'
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'left',
+ textStyle: {
+ fontSize: 12
+ }
+ },
+ series: [
+ {
+ name: '閰嶆柟浣跨敤棰戞',
+ type: 'pie',
+ radius: '60%',
+ center: ['60%', '50%'],
+ data: mockRecipeData,
+ emphasis: {
+ itemStyle: {
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
+ }
+ },
+ itemStyle: {
+ borderRadius: 8,
+ borderColor: '#fff',
+ borderWidth: 2
+ },
+ label: {
+ show: true,
+ formatter: '{b}\n{c}娆�'
+ }
+ }
+ ]
+}))
+
+// 鍔犲伐寰楃巼鍒嗘瀽鍥鹃厤缃�
+const processingYieldOptions = computed(() => ({
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow'
+ }
+ },
+ legend: {
+ data: ['鍑烘礂鐜�', '鍔犲伐鑳芥晥']
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: mockYieldData.map(item => item.name)
+ },
+ yAxis: {
+ type: 'value',
+ name: '鐧惧垎姣� (%)',
+ min: 60,
+ max: 100
+ },
+ series: [
+ {
+ name: '鍑烘礂鐜�',
+ type: 'bar',
+ data: mockYieldData.map(item => item.yield),
+ itemStyle: {
+ color: '#52C41A'
+ }
+ },
+ {
+ name: '鍔犲伐鑳芥晥',
+ type: 'bar',
+ data: mockYieldData.map(item => item.efficiency),
+ itemStyle: {
+ color: '#1890FF'
+ }
+ }
+ ]
+}))
+
+// 鎴愭湰缁撴瀯鍥捐氨閰嶇疆
+const costStructureOptions = computed(() => ({
+ tooltip: {
+ trigger: 'item',
+ formatter: '{b}: {c}%'
+ },
+ legend: {
+ orient: 'vertical',
+ left: 'left'
+ },
+ series: [
+ {
+ name: '鎴愭湰缁撴瀯',
+ type: 'pie',
+ radius: '60%',
+ center: ['60%', '50%'],
+ data: mockCostData,
+ emphasis: {
+ itemStyle: {
+ shadowBlur: 10,
+ shadowOffsetX: 0,
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
+ }
+ },
+ roseType: 'radius',
+ itemStyle: {
+ borderRadius: 8,
+ borderColor: '#fff',
+ borderWidth: 2
+ }
+ }
+ ]
+}))
+
+// 鏌ヨ鏁版嵁
+const loading = ref(false)
+
+const handleSearch = async () => {
+ try {
+ loading.value = true
+ // 鍦ㄥ疄闄呭簲鐢ㄤ腑锛岃繖閲屼細璋冪敤API鑾峰彇鐪熷疄鏁版嵁
+ console.log('鎼滅储鍙傛暟:', searchParams.value)
+
+ // 鑾峰彇閰嶇叅鏁版嵁
+ // const blendingRes = await getCoalBlendingList({
+ // startTime: searchParams.value.dateRange[0] ? parseTime(searchParams.value.dateRange[0]) : '',
+ // endTime: searchParams.value.dateRange[1] ? parseTime(searchParams.value.dateRange[1]) : ''
+ // })
+
+ // 妯℃嫙API璇锋眰寤惰繜
+ await new Promise(resolve => setTimeout(resolve, 800))
+
+ // 妯℃嫙鏁版嵁鏇存柊锛堝疄闄呭簲鐢ㄤ腑搴旀牴鎹瓵PI杩斿洖缁撴灉鏇存柊锛�
+ unitHeatCoalConsumption.value = 31.8 + Math.random() * 5
+ overallComplianceRate.value = 80 + Math.random() * 15
+ averageCalorificValue.value = 5000 + Math.random() * 500
+ totalBatches.value = 40 + Math.floor(Math.random() * 20)
+
+ // 闅忔満鏇存柊閮ㄥ垎鍥捐〃鏁版嵁
+ mockComplianceData.forEach(item => {
+ item.rate = 80 + Math.random() * 15
+ })
+
+ ElMessage.success('鏌ヨ鎴愬姛')
+ } catch (error) {
+ console.error('鏌ヨ澶辫触:', error)
+ ElMessage.error('鏌ヨ澶辫触锛岃绋嶅悗閲嶈瘯')
+ } finally {
+ loading.value = false
+ }
+}
+
+// 鍒锋柊鏁版嵁
+const handleRefresh = () => {
+ ElMessage.info('姝e湪鍒锋柊鏁版嵁...')
+ handleSearch()
+}
+
+// 瀵煎嚭鏁版嵁
+const handleExport = async () => {
+ try {
+ loading.value = true
+ // 妯℃嫙瀵煎嚭鎿嶄綔
+ await new Promise(resolve => setTimeout(resolve, 1000))
+
+ ElMessage.success('鏁版嵁瀵煎嚭鎴愬姛')
+ } catch (error) {
+ console.error('瀵煎嚭澶辫触:', error)
+ ElMessage.error('瀵煎嚭澶辫触锛岃绋嶅悗閲嶈瘯')
+ } finally {
+ loading.value = false
+ }
+}
+
+// 閲嶇疆鎼滅储鍙傛暟
+const handleReset = () => {
+ searchParams.value = {
+ dateRange: []
+ }
+}
+
+// 鍒濆鍖栭〉闈�
+onMounted(() => {
+ // 榛樿鏌ヨ杩�7澶╂暟鎹�
+ const end = new Date()
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+ searchParams.value.dateRange = [start, end]
+
+ // 鍒濆鍔犺浇鏁版嵁
+ handleSearch()
+})
+</script>
+
+<style scoped>
+.coal-blending-efficiency {
+ padding: 20px;
+}
+
+.page-header {
+ margin-bottom: 20px;
+}
+
+.page-header h2 {
+ margin-bottom: 15px;
+ font-size: 18px;
+ font-weight: 600;
+ color: #303133;
+}
+
+.stats-cards {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 16px;
+ margin-bottom: 24px;
+}
+
+.stat-card {
+ display: flex;
+ padding: 20px;
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ transition: transform 0.3s, box-shadow 0.3s;
+}
+
+.stat-card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+}
+
+.card-icon {
+ width: 48px;
+ height: 48px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ font-size: 24px;
+ margin-right: 16px;
+}
+
+.stat-card:nth-child(1) .card-icon {
+ background: #ECF5FF;
+ color: #409EFF;
+}
+
+.stat-card:nth-child(2) .card-icon {
+ background: #F0F9FF;
+ color: #69B1FF;
+}
+
+.stat-card:nth-child(3) .card-icon {
+ background: #F6FFED;
+ color: #52C41A;
+}
+
+.stat-card:nth-child(4) .card-icon {
+ background: #FFF7E6;
+ color: #FAAD14;
+}
+
+.card-content {
+ flex: 1;
+}
+
+.card-title {
+ font-size: 14px;
+ color: #606266;
+ margin-bottom: 8px;
+}
+
+.card-value {
+ font-size: 24px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+}
+
+.card-desc {
+ font-size: 12px;
+ color: #909399;
+}
+
+.charts-container {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
+ gap: 24px;
+}
+
+.chart-card {
+ background: #fff;
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 16px;
+ border-bottom: 1px solid #EBEEF5;
+}
+
+.card-header span {
+ font-weight: 600;
+ color: #303133;
+}
+
+.chart-wrapper {
+ padding: 20px;
+}
+
+.cost-structure {
+ grid-column: 1 / -1;
+}
+
+@media (max-width: 1200px) {
+ .charts-container {
+ grid-template-columns: 1fr;
+ }
+}
+</style>
\ No newline at end of file
--
Gitblit v1.9.3