From ea6ad9ddc3d5b33897e93276282245f7023836ff Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 28 八月 2025 17:45:28 +0800
Subject: [PATCH] 大数据市场分析
---
src/views/marketAnalysis/index.vue | 1082 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,082 insertions(+), 0 deletions(-)
diff --git a/src/views/marketAnalysis/index.vue b/src/views/marketAnalysis/index.vue
new file mode 100644
index 0000000..cd8feda
--- /dev/null
+++ b/src/views/marketAnalysis/index.vue
@@ -0,0 +1,1082 @@
+<template>
+ <div class="market-analysis-container">
+
+ <!-- 鏁版嵁姒傝鍗$墖 -->
+ <el-row :gutter="20" class="data-overview">
+ <el-col :span="6">
+ <el-card class="overview-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-icon price-icon">
+ <el-icon><TrendCharts /></el-icon>
+ </div>
+ <div class="card-info">
+ <div class="card-title">骞冲潎鐓や环</div>
+ <div class="card-value">楼{{ marketData.avgPrice.toFixed(2) }}</div>
+ <div class="card-change" :class="marketData.priceChange >= 0 ? 'positive' : 'negative'">
+ {{ marketData.priceChange >= 0 ? '+' : '' }}{{ marketData.priceChange.toFixed(2) }}%
+ </div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="6">
+ <el-card class="overview-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-icon volume-icon">
+ <el-icon><DataLine /></el-icon>
+ </div>
+ <div class="card-info">
+ <div class="card-title">浜ゆ槗閲�</div>
+ <div class="card-value">{{ marketData.totalVolume }}涓囧惃</div>
+ <div class="card-change" :class="marketData.volumeChange >= 0 ? 'positive' : 'negative'">
+ {{ marketData.volumeChange >= 0 ? '+' : '' }}{{ marketData.volumeChange.toFixed(2) }}%
+ </div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="6">
+ <el-card class="overview-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-icon customer-icon">
+ <el-icon><User /></el-icon>
+ </div>
+ <div class="card-info">
+ <div class="card-title">娲昏穬瀹㈡埛</div>
+ <div class="card-value">{{ marketData.activeCustomers }}瀹�</div>
+ <div class="card-change" :class="marketData.customerChange >= 0 ? 'positive' : 'negative'">
+ {{ marketData.customerChange >= 0 ? '+' : '' }}{{ marketData.customerChange.toFixed(2) }}%
+ </div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+
+ <el-col :span="6">
+ <el-card class="overview-card" shadow="hover">
+ <div class="card-content">
+ <div class="card-icon trend-icon">
+ <el-icon><TrendCharts /></el-icon>
+ </div>
+ <div class="card-info">
+ <div class="card-title">甯傚満瓒嬪娍</div>
+ <div class="card-value">{{ marketData.marketTrend }}</div>
+ <div class="card-change" :class="marketData.trendScore >= 0 ? 'positive' : 'negative'">
+ 淇″績鎸囨暟: {{ marketData.trendScore }}
+ </div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 涓昏鍒嗘瀽鍖哄煙 -->
+ <el-row :gutter="20" class="main-analysis">
+ <!-- 浠锋牸瓒嬪娍鍒嗘瀽 -->
+ <el-col :span="16">
+ <el-card class="analysis-card" shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>鐓ょ浠锋牸瓒嬪娍鍒嗘瀽</span>
+ <div class="header-controls">
+ <el-select v-model="selectedCoalType" placeholder="閫夋嫨鐓ょ" size="small" style="width: 120px">
+ <el-option label="娣风叅" value="mixed" />
+ <el-option label="绮剧叅" value="refined" />
+ <el-option label="鍔ㄥ姏鐓�" value="power" />
+ <el-option label="鐒︾叅" value="coking" />
+ </el-select>
+ <el-select v-model="selectedRegion" placeholder="閫夋嫨浜у湴" size="small" style="width: 120px">
+ <el-option label="灞辫タ" value="shanxi" />
+ <el-option label="鍐呰挋鍙�" value="neimenggu" />
+ <el-option label="闄曡タ" value="shaanxi" />
+ <el-option label="鏂扮枂" value="xinjiang" />
+ </el-select>
+ <el-select v-model="selectedPeriod" placeholder="鏃堕棿鍛ㄦ湡" size="small" style="width: 100px">
+ <el-option label="鏃�" value="day" />
+ <el-option label="鍛�" value="week" />
+ <el-option label="鏈�" value="month" />
+ <el-option label="瀛�" value="quarter" />
+ </el-select>
+ </div>
+ </div>
+ </template>
+
+ <div class="chart-container">
+ <div ref="priceChartRef" class="chart" style="height: 400px;"></div>
+ </div>
+ </el-card>
+ </el-col>
+
+ <!-- 瀹㈡埛琛屼负鍒嗘瀽 -->
+ <el-col :span="8">
+ <el-card class="analysis-card" shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>瀹㈡埛琛屼负鐢诲儚</span>
+ </div>
+ </template>
+
+ <div class="customer-analysis">
+ <div class="customer-type-distribution">
+ <h4>瀹㈡埛绫诲瀷鍒嗗竷</h4>
+ <div ref="customerChartRef" class="chart" style="height: 200px;"></div>
+ </div>
+
+ <div class="purchase-preference">
+ <h4>閲囪喘鍋忓ソ鍒嗘瀽</h4>
+ <div class="preference-item" v-for="item in customerPreferences" :key="item.type">
+ <div class="preference-label">{{ item.type }}</div>
+ <div class="preference-bar">
+ <div class="bar-fill" :style="{ width: item.percentage + '%' }"></div>
+ </div>
+ <div class="preference-value">{{ item.percentage }}%</div>
+ </div>
+ </div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 璇︾粏鍒嗘瀽鍖哄煙 -->
+ <el-row :gutter="20" class="detail-analysis">
+ <!-- 鍖哄煙浠锋牸瀵规瘮 -->
+ <el-col :span="12">
+ <el-card class="analysis-card" shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>鍖哄煙浠锋牸瀵规瘮</span>
+ </div>
+ </template>
+
+ <div class="region-comparison">
+ <div ref="regionChartRef" class="chart" style="height: 300px;"></div>
+ </div>
+ </el-card>
+ </el-col>
+
+ <!-- 瀹㈡埛閲囪喘鍛ㄦ湡鍒嗘瀽 -->
+ <el-col :span="12">
+ <el-card class="analysis-card" shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>瀹㈡埛閲囪喘鍛ㄦ湡鍒嗘瀽</span>
+ </div>
+ </template>
+
+ <div class="purchase-cycle">
+ <div ref="cycleChartRef" class="chart" style="height: 300px;"></div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 鏅鸿兘鎺ㄨ崘鍖哄煙 -->
+ <el-row :gutter="20" class="smart-recommendations">
+ <el-col :span="24">
+ <el-card class="analysis-card" shadow="hover">
+ <template #header>
+ <div class="card-header">
+ <span>鏅鸿兘钀ラ攢鎺ㄨ崘</span>
+ <el-tag type="warning" size="small">AI绠楁硶椹卞姩</el-tag>
+ </div>
+ </template>
+
+ <div class="recommendations-content">
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <div class="recommendation-section">
+ <h4>涓�у寲瀹氫环寤鸿</h4>
+ <div class="pricing-suggestions">
+ <div class="suggestion-item" v-for="suggestion in pricingSuggestions" :key="suggestion.id">
+ <div class="suggestion-header">
+ <span class="customer-name">{{ suggestion.customerName }}</span>
+ <el-tag :type="suggestion.priority" size="small">{{ suggestion.priorityText }}</el-tag>
+ </div>
+ <div class="suggestion-content">
+ <p>寤鸿浠锋牸锛毬{ suggestion.suggestedPrice }}/鍚�</p>
+ <p>璁环绌洪棿锛歿{ suggestion.negotiationSpace }}%</p>
+ <p>鎺ㄥ崟鏃舵満锛歿{ suggestion.timing }}</p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </el-col>
+
+ <el-col :span="8">
+ <div class="recommendation-section">
+ <h4>鐑攢鐓ゅ瀷鎺ㄨ崘</h4>
+ <div class="hot-coal-types">
+ <div class="coal-type-item" v-for="coal in hotCoalTypes" :key="coal.id">
+ <div class="coal-info">
+ <div class="coal-name">{{ coal.name }}</div>
+ <div class="coal-spec">{{ coal.specification }}</div>
+ </div>
+ <div class="coal-metrics">
+ <div class="metric">
+ <span class="label">鐑害鎸囨暟锛�</span>
+ <span class="value">{{ coal.heatIndex }}</span>
+ </div>
+ <div class="metric">
+ <span class="label">搴撳瓨鐘舵�侊細</span>
+ <el-tag :type="coal.stockStatus === '鍏呰冻' ? 'success' : 'warning'" size="small">
+ {{ coal.stockStatus }}
+ </el-tag>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </el-col>
+
+ <el-col :span="8">
+ <div class="recommendation-section">
+ <h4>瀹㈡埛绮樻�ф彁鍗�</h4>
+ <div class="loyalty-improvements">
+ <div class="improvement-item" v-for="improvement in loyaltyImprovements" :key="improvement.id">
+ <div class="improvement-header">
+ <span class="strategy-name">{{ improvement.strategyName }}</span>
+ <span class="success-rate">鎴愬姛鐜�: {{ improvement.successRate }}%</span>
+ </div>
+ <div class="improvement-content">
+ <p>{{ improvement.description }}</p>
+ <div class="action-buttons">
+ <el-button type="primary" size="small">鎵ц绛栫暐</el-button>
+ <el-button size="small">鏌ョ湅璇︽儏</el-button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </el-col>
+ </el-row>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue'
+import { ElMessage } from 'element-plus'
+import { Refresh, TrendCharts, DataLine, User } from '@element-plus/icons-vue'
+import * as echarts from 'echarts'
+
+// 鍝嶅簲寮忔暟鎹�
+const refreshing = ref(false)
+const lastUpdateTime = ref('')
+const selectedCoalType = ref('mixed')
+const selectedRegion = ref('shanxi')
+const selectedPeriod = ref('month')
+
+// 鍥捐〃寮曠敤
+const priceChartRef = ref(null)
+const customerChartRef = ref(null)
+const regionChartRef = ref(null)
+const cycleChartRef = ref(null)
+
+// 鍥捐〃瀹炰緥
+let priceChart = null
+let customerChart = null
+let regionChart = null
+let cycleChart = null
+
+// 甯傚満鏁版嵁
+const marketData = reactive({
+ avgPrice: 1250.50,
+ priceChange: 2.35,
+ totalVolume: 1250.8,
+ volumeChange: -1.25,
+ activeCustomers: 156,
+ customerChange: 3.45,
+ marketTrend: '绋充腑鏈夊崌',
+ trendScore: 8.5
+})
+
+// 瀹㈡埛鍋忓ソ鏁版嵁
+const customerPreferences = ref([
+ { type: '鐒﹀寲鍘�', percentage: 35 },
+ { type: '鐢靛巶', percentage: 28 },
+ { type: '閽㈠巶', percentage: 22 },
+ { type: '鍖栧伐鍘�', percentage: 15 }
+])
+
+// 瀹氫环寤鸿
+const pricingSuggestions = ref([
+ {
+ id: 1,
+ customerName: '灞辫タ鐒﹀寲闆嗗洟',
+ priority: 'high',
+ priorityText: '楂樹紭鍏堢骇',
+ suggestedPrice: 1280,
+ negotiationSpace: 5.2,
+ timing: '鏈懆鍐�'
+ },
+ {
+ id: 2,
+ customerName: '鍗庤兘鐢靛姏',
+ priority: 'medium',
+ priorityText: '涓紭鍏堢骇',
+ suggestedPrice: 1250,
+ negotiationSpace: 3.8,
+ timing: '涓嬪懆鍒�'
+ },
+ {
+ id: 3,
+ customerName: '瀹濋挗闆嗗洟',
+ priority: 'low',
+ priorityText: '浣庝紭鍏堢骇',
+ suggestedPrice: 1220,
+ negotiationSpace: 2.5,
+ timing: '鏈湀鍐�'
+ }
+])
+
+// 鐑攢鐓ゅ瀷
+const hotCoalTypes = ref([
+ {
+ id: 1,
+ name: '浼樿川娣风叅',
+ specification: '鍙戠儹閲�5500澶у崱',
+ heatIndex: 9.2,
+ stockStatus: '鍏呰冻'
+ },
+ {
+ id: 2,
+ name: '绮炬礂鐒︾叅',
+ specification: '鐏板垎鈮�8%',
+ heatIndex: 8.8,
+ stockStatus: '鍏呰冻'
+ },
+ {
+ id: 3,
+ name: '鍔ㄥ姏鐓�',
+ specification: '鍙戠儹閲�6000澶у崱',
+ heatIndex: 8.5,
+ stockStatus: '绱у紶'
+ }
+])
+
+// 瀹㈡埛绮樻�ф彁鍗囩瓥鐣�
+const loyaltyImprovements = ref([
+ {
+ id: 1,
+ strategyName: '宸紓鍖栧畾浠风瓥鐣�',
+ successRate: 85,
+ description: '鏍规嵁瀹㈡埛閲囪喘棰戞鍜岃浠疯兘鍔涳紝鍒跺畾涓�у寲浠锋牸鏂规'
+ },
+ {
+ id: 2,
+ strategyName: '绮惧噯鎺ㄥ崟鑺傚',
+ successRate: 78,
+ description: '鍩轰簬瀹㈡埛閲囪喘鍛ㄦ湡鍒嗘瀽锛屽湪鏈�浣虫椂鏈烘帹閫佺浉鍏充骇鍝�'
+ },
+ {
+ id: 3,
+ strategyName: '澧炲�兼湇鍔″寘',
+ successRate: 92,
+ description: '鎻愪緵鐗╂祦閰嶉�併�佽川閲忔娴嬬瓑澧炲�兼湇鍔★紝鎻愬崌瀹㈡埛婊℃剰搴�'
+ }
+])
+
+// 妯℃嫙鏁版嵁鐢熸垚
+const generateMockData = () => {
+ // 鐢熸垚浠锋牸瓒嬪娍鏁版嵁
+ const dates = []
+ const prices = []
+ const volumes = []
+
+ for (let i = 30; i >= 0; i--) {
+ const date = new Date()
+ date.setDate(date.getDate() - i)
+ dates.push(date.toLocaleDateString())
+
+ const basePrice = 1200 + Math.random() * 200
+ prices.push(basePrice)
+
+ const baseVolume = 30 + Math.random() * 20
+ volumes.push(baseVolume)
+ }
+
+ return { dates, prices, volumes }
+}
+
+// 鍒濆鍖栦环鏍艰秼鍔垮浘琛�
+const initPriceChart = () => {
+ if (!priceChartRef.value) return
+
+ priceChart = echarts.init(priceChartRef.value)
+ const { dates, prices, volumes } = generateMockData()
+
+ const option = {
+ title: {
+ text: '娣风叅鏈堝害浠锋牸鍙樺寲瓒嬪娍',
+ left: 'center',
+ textStyle: {
+ fontSize: 16,
+ fontWeight: 'bold'
+ }
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross'
+ }
+ },
+ legend: {
+ data: ['浠锋牸(鍏�/鍚�)', '浜ゆ槗閲�(涓囧惃)'],
+ top: 30
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: dates,
+ axisLabel: {
+ rotate: 45
+ }
+ },
+ yAxis: [
+ {
+ type: 'value',
+ name: '浠锋牸(鍏�/鍚�)',
+ position: 'left'
+ },
+ {
+ type: 'value',
+ name: '浜ゆ槗閲�(涓囧惃)',
+ position: 'right'
+ }
+ ],
+ series: [
+ {
+ name: '浠锋牸(鍏�/鍚�)',
+ type: 'line',
+ data: prices,
+ smooth: true,
+ lineStyle: {
+ color: '#409EFF',
+ width: 3
+ },
+ itemStyle: {
+ color: '#409EFF'
+ }
+ },
+ {
+ name: '浜ゆ槗閲�(涓囧惃)',
+ type: 'bar',
+ yAxisIndex: 1,
+ data: volumes,
+ itemStyle: {
+ color: '#67C23A'
+ }
+ }
+ ]
+ }
+
+ priceChart.setOption(option)
+}
+
+// 鍒濆鍖栧鎴峰垎甯冨浘琛�
+const initCustomerChart = () => {
+ if (!customerChartRef.value) return
+
+ customerChart = echarts.init(customerChartRef.value)
+
+ const option = {
+ tooltip: {
+ trigger: 'item',
+ formatter: '{a} <br/>{b}: {c} ({d}%)'
+ },
+ series: [
+ {
+ name: '瀹㈡埛绫诲瀷',
+ type: 'pie',
+ radius: ['40%', '70%'],
+ avoidLabelOverlap: false,
+ label: {
+ show: false,
+ position: 'center'
+ },
+ emphasis: {
+ label: {
+ show: true,
+ fontSize: '18',
+ fontWeight: 'bold'
+ }
+ },
+ labelLine: {
+ show: false
+ },
+ data: [
+ { value: 35, name: '鐒﹀寲鍘�' },
+ { value: 28, name: '鐢靛巶' },
+ { value: 22, name: '閽㈠巶' },
+ { value: 15, name: '鍖栧伐鍘�' }
+ ]
+ }
+ ]
+ }
+
+ customerChart.setOption(option)
+}
+
+// 鍒濆鍖栧尯鍩熷姣斿浘琛�
+const initRegionChart = () => {
+ if (!regionChartRef.value) return
+
+ regionChart = echarts.init(regionChartRef.value)
+
+ const option = {
+ title: {
+ text: '鍚勪骇鍦扮叅浠峰姣�',
+ left: 'center'
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow'
+ }
+ },
+ legend: {
+ data: ['娣风叅', '绮剧叅', '鍔ㄥ姏鐓�', '鐒︾叅'],
+ top: 30
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: {
+ type: 'category',
+ data: ['灞辫タ', '鍐呰挋鍙�', '闄曡タ', '鏂扮枂']
+ },
+ yAxis: {
+ type: 'value',
+ name: '浠锋牸(鍏�/鍚�)'
+ },
+ series: [
+ {
+ name: '娣风叅',
+ type: 'bar',
+ data: [1250, 1180, 1220, 1150]
+ },
+ {
+ name: '绮剧叅',
+ type: 'bar',
+ data: [1350, 1280, 1320, 1250]
+ },
+ {
+ name: '鍔ㄥ姏鐓�',
+ type: 'bar',
+ data: [1150, 1080, 1120, 1050]
+ },
+ {
+ name: '鐒︾叅',
+ type: 'bar',
+ data: [1450, 1380, 1420, 1350]
+ }
+ ]
+ }
+
+ regionChart.setOption(option)
+}
+
+// 鍒濆鍖栭噰璐懆鏈熷浘琛�
+const initCycleChart = () => {
+ if (!cycleChartRef.value) return
+
+ cycleChart = echarts.init(cycleChartRef.value)
+
+ const option = {
+ title: {
+ text: '瀹㈡埛閲囪喘鍛ㄦ湡鍒嗗竷',
+ left: 'center'
+ },
+ tooltip: {
+ trigger: 'item'
+ },
+ series: [
+ {
+ name: '閲囪喘鍛ㄦ湡',
+ type: 'funnel',
+ left: '10%',
+ top: 60,
+ bottom: 60,
+ width: '80%',
+ height: '80%',
+ min: 0,
+ max: 100,
+ minSize: '0%',
+ maxSize: '100%',
+ sort: 'descending',
+ gap: 2,
+ label: {
+ show: true,
+ position: 'inside'
+ },
+ labelLine: {
+ length: 10,
+ lineStyle: {
+ width: 1,
+ type: 'solid'
+ }
+ },
+ itemStyle: {
+ borderColor: '#fff',
+ borderWidth: 1
+ },
+ emphasis: {
+ label: {
+ fontSize: 20
+ }
+ },
+ data: [
+ { value: 100, name: '楂橀瀹㈡埛(鍛ㄩ噰璐�)' },
+ { value: 80, name: '涓瀹㈡埛(鏈堥噰璐�)' },
+ { value: 60, name: '浣庨瀹㈡埛(瀛i噰璐�)' },
+ { value: 40, name: '鍋跺彂瀹㈡埛(骞撮噰璐�)' }
+ ]
+ }
+ ]
+ }
+
+ cycleChart.setOption(option)
+}
+
+// 鍒锋柊鏁版嵁
+const refreshData = async () => {
+ refreshing.value = true
+
+ try {
+ // 妯℃嫙鏁版嵁鍒锋柊
+ await new Promise(resolve => setTimeout(resolve, 2000))
+
+ // 鏇存柊甯傚満鏁版嵁
+ marketData.avgPrice = 1200 + Math.random() * 200
+ marketData.priceChange = (Math.random() - 0.5) * 10
+ marketData.totalVolume = 1000 + Math.random() * 500
+ marketData.volumeChange = (Math.random() - 0.5) * 8
+ marketData.activeCustomers = 140 + Math.floor(Math.random() * 40)
+ marketData.customerChange = (Math.random() - 0.5) * 6
+ marketData.trendScore = 7 + Math.random() * 3
+
+ // 鏇存柊鏃堕棿
+ lastUpdateTime.value = new Date().toLocaleString()
+
+ // 閲嶆柊鍒濆鍖栧浘琛�
+ await nextTick()
+ initPriceChart()
+ initCustomerChart()
+ initRegionChart()
+ initCycleChart()
+
+ ElMessage.success('鏁版嵁鍒锋柊鎴愬姛')
+ } catch (error) {
+ ElMessage.error('鏁版嵁鍒锋柊澶辫触')
+ } finally {
+ refreshing.value = false
+ }
+}
+
+// 鑷姩鍒锋柊瀹氭椂鍣�
+let refreshTimer = null
+
+// 鍚姩鑷姩鍒锋柊
+const startAutoRefresh = () => {
+ refreshTimer = setInterval(() => {
+ refreshData()
+ }, 10 * 60 * 1000) // 10鍒嗛挓
+}
+
+// 鍋滄鑷姩鍒锋柊
+const stopAutoRefresh = () => {
+ if (refreshTimer) {
+ clearInterval(refreshTimer)
+ refreshTimer = null
+ }
+}
+
+// 鐩戝惉绐楀彛澶у皬鍙樺寲
+const handleResize = () => {
+ if (priceChart) priceChart.resize()
+ if (customerChart) customerChart.resize()
+ if (regionChart) regionChart.resize()
+ if (cycleChart) cycleChart.resize()
+}
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(async () => {
+ // 鍒濆鍖栨椂闂�
+ lastUpdateTime.value = new Date().toLocaleString()
+
+ // 绛夊緟DOM娓叉煋瀹屾垚
+ await nextTick()
+
+ // 鍒濆鍖栧浘琛�
+ initPriceChart()
+ initCustomerChart()
+ initRegionChart()
+ initCycleChart()
+
+ // 鍚姩鑷姩鍒锋柊
+ startAutoRefresh()
+
+ // 鐩戝惉绐楀彛澶у皬鍙樺寲
+ window.addEventListener('resize', handleResize)
+})
+
+onUnmounted(() => {
+ // 鍋滄鑷姩鍒锋柊
+ stopAutoRefresh()
+
+ // 閿�姣佸浘琛�
+ if (priceChart) priceChart.dispose()
+ if (customerChart) customerChart.dispose()
+ if (regionChart) regionChart.dispose()
+ if (cycleChart) cycleChart.dispose()
+
+ // 绉婚櫎浜嬩欢鐩戝惉
+ window.removeEventListener('resize', handleResize)
+})
+</script>
+
+<style scoped>
+.market-analysis-container {
+ padding: 20px;
+ background-color: #f5f7fa;
+ min-height: 100vh;
+}
+
+.page-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ padding: 20px;
+ background: white;
+ border-radius: 8px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.page-header h1 {
+ margin: 0;
+ color: #303133;
+ font-size: 24px;
+ font-weight: 600;
+}
+
+.header-info {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+}
+
+.update-time {
+ color: #909399;
+ font-size: 14px;
+}
+
+.data-overview {
+ margin-bottom: 20px;
+}
+
+.overview-card {
+ height: 120px;
+}
+
+.card-content {
+ display: flex;
+ align-items: center;
+ height: 100%;
+}
+
+.card-icon {
+ width: 60px;
+ height: 60px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 15px;
+ font-size: 24px;
+ color: white;
+}
+
+.price-icon {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+}
+
+.volume-icon {
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
+}
+
+.customer-icon {
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+}
+
+.trend-icon {
+ background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
+}
+
+.card-info {
+ flex: 1;
+}
+
+.card-title {
+ font-size: 14px;
+ color: #909399;
+ margin-bottom: 8px;
+}
+
+.card-value {
+ font-size: 24px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 8px;
+}
+
+.card-change {
+ font-size: 12px;
+ font-weight: 500;
+}
+
+.card-change.positive {
+ color: #67c23a;
+}
+
+.card-change.negative {
+ color: #f56c6c;
+}
+
+.main-analysis {
+ margin-bottom: 20px;
+}
+
+.analysis-card {
+ margin-bottom: 20px;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-weight: 600;
+ font-size: 16px;
+}
+
+.header-controls {
+ display: flex;
+ gap: 10px;
+}
+
+.chart-container {
+ padding: 10px 0;
+}
+
+.chart {
+ width: 100%;
+}
+
+.customer-analysis h4 {
+ margin: 0 0 15px 0;
+ color: #303133;
+ font-size: 14px;
+}
+
+.customer-type-distribution {
+ margin-bottom: 20px;
+}
+
+.preference-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 12px;
+}
+
+.preference-label {
+ width: 80px;
+ font-size: 12px;
+ color: #606266;
+}
+
+.preference-bar {
+ flex: 1;
+ height: 8px;
+ background-color: #f0f0f0;
+ border-radius: 4px;
+ margin: 0 10px;
+ overflow: hidden;
+}
+
+.bar-fill {
+ height: 100%;
+ background: linear-gradient(90deg, #409eff 0%, #67c23a 100%);
+ border-radius: 4px;
+ transition: width 0.3s ease;
+}
+
+.preference-value {
+ width: 40px;
+ font-size: 12px;
+ color: #409eff;
+ font-weight: 500;
+}
+
+.detail-analysis {
+ margin-bottom: 20px;
+}
+
+.smart-recommendations {
+ margin-bottom: 20px;
+}
+
+.recommendations-content {
+ padding: 10px 0;
+}
+
+.recommendation-section h4 {
+ margin: 0 0 15px 0;
+ color: #303133;
+ font-size: 14px;
+ border-bottom: 2px solid #409eff;
+ padding-bottom: 5px;
+}
+
+.suggestion-item {
+ background: #f8f9fa;
+ border-radius: 6px;
+ padding: 12px;
+ margin-bottom: 12px;
+ border-left: 4px solid #409eff;
+}
+
+.suggestion-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+}
+
+.customer-name {
+ font-weight: 500;
+ color: #303133;
+}
+
+.suggestion-content p {
+ margin: 5px 0;
+ font-size: 12px;
+ color: #606266;
+}
+
+.coal-type-item {
+ background: #f8f9fa;
+ border-radius: 6px;
+ padding: 12px;
+ margin-bottom: 12px;
+ border-left: 4px solid #67c23a;
+}
+
+.coal-info {
+ margin-bottom: 8px;
+}
+
+.coal-name {
+ font-weight: 500;
+ color: #303133;
+ font-size: 14px;
+}
+
+.coal-spec {
+ font-size: 12px;
+ color: #909399;
+}
+
+.coal-metrics {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.metric {
+ font-size: 12px;
+}
+
+.metric .label {
+ color: #909399;
+}
+
+.metric .value {
+ color: #409eff;
+ font-weight: 500;
+}
+
+.improvement-item {
+ background: #f8f9fa;
+ border-radius: 6px;
+ padding: 12px;
+ margin-bottom: 12px;
+ border-left: 4px solid #e6a23c;
+}
+
+.improvement-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+}
+
+.strategy-name {
+ font-weight: 500;
+ color: #303133;
+}
+
+.success-rate {
+ font-size: 12px;
+ color: #67c23a;
+ font-weight: 500;
+}
+
+.improvement-content p {
+ margin: 5px 0 10px 0;
+ font-size: 12px;
+ color: #606266;
+}
+
+.action-buttons {
+ display: flex;
+ gap: 8px;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1200px) {
+ .header-controls {
+ flex-direction: column;
+ gap: 5px;
+ }
+
+ .header-controls .el-select {
+ width: 100px !important;
+ }
+}
+
+@media (max-width: 768px) {
+ .page-header {
+ flex-direction: column;
+ gap: 15px;
+ text-align: center;
+ }
+
+ .header-info {
+ flex-direction: column;
+ gap: 10px;
+ }
+}
+</style>
--
Gitblit v1.9.3