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