311 lines
9.6 KiB
Vue
311 lines
9.6 KiB
Vue
<template>
|
|
<div class="big-screen">
|
|
<header class="screen-header">
|
|
<h1 class="title">订单数据大屏</h1>
|
|
<span class="time">{{ currentTime }}</span>
|
|
</header>
|
|
|
|
<main class="screen-body">
|
|
<div class="card-grid">
|
|
<div class="data-card" v-for="card in cards" :key="card.title">
|
|
<div class="card-title">{{ card.title }}</div>
|
|
<div class="card-value" :style="{ color: card.color }">{{ card.value }}</div>
|
|
<div class="card-unit">{{ card.unit }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="chart-area">
|
|
<div class="chart-box">
|
|
<div class="box-title">订单趋势</div>
|
|
<div ref="trendChartRef" class="chart"></div>
|
|
</div>
|
|
<div class="chart-box">
|
|
<div class="box-title">订单状态分布</div>
|
|
<div ref="pieChartRef" class="chart"></div>
|
|
</div>
|
|
<div class="chart-box">
|
|
<div class="box-title">客户订单排行</div>
|
|
<div class="ranking-list">
|
|
<div class="ranking-item" v-for="(item, index) in rankingList" :key="item.name">
|
|
<span class="rank" :class="'rank-' + (index + 1)">{{ index + 1 }}</span>
|
|
<span class="name">{{ item.name }}</span>
|
|
<span class="value">{{ item.value }}</span>
|
|
<span class="unit">单</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="order-list-box">
|
|
<div class="box-title">订单列表</div>
|
|
<div class="order-table">
|
|
<div class="table-header">
|
|
<span>订单号</span>
|
|
<span>客户</span>
|
|
<span>金额</span>
|
|
<span>状态</span>
|
|
<span>时间</span>
|
|
</div>
|
|
<div class="table-body">
|
|
<div class="table-row" v-for="order in orderList" :key="order.orderNo">
|
|
<span class="order-no">{{ order.orderNo }}</span>
|
|
<span>{{ order.customer }}</span>
|
|
<span class="amount">{{ formatAmount(order.amount) }}</span>
|
|
<span :class="['status', order.status]">{{ order.status }}</span>
|
|
<span class="time">{{ order.time }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, onUnmounted } from 'vue'
|
|
import * as echarts from 'echarts'
|
|
|
|
const currentTime = ref('')
|
|
const trendChartRef = ref(null)
|
|
const pieChartRef = ref(null)
|
|
let trendChart = null
|
|
let pieChart = null
|
|
let timeInterval = null
|
|
|
|
const cards = ref([
|
|
{ title: '今日订单', value: '45', unit: '单', color: '#5cd9e8' },
|
|
{ title: '待处理订单', value: '12', unit: '单', color: '#ff9800' },
|
|
{ title: '已完成订单', value: '156', unit: '单', color: '#67c23a' },
|
|
{ title: '订单金额', value: '258', unit: '万元', color: '#1A5CD7' }
|
|
])
|
|
|
|
const rankingList = ref([
|
|
{ name: '周口钢铁', value: 125 },
|
|
{ name: '南阳重工', value: 98 },
|
|
{ name: '洛阳机械', value: 86 },
|
|
{ name: '开封汽配', value: 72 },
|
|
{ name: '商丘金属', value: 65 }
|
|
])
|
|
|
|
const orderList = ref([
|
|
{ orderNo: 'ORD20260515001', customer: '周口钢铁', amount: 125000, status: '生产中', time: '10:30' },
|
|
{ orderNo: 'ORD20260515002', customer: '南阳重工', amount: 89000, status: '已完成', time: '09:45' },
|
|
{ orderNo: 'ORD20260515003', customer: '洛阳机械', amount: 156000, status: '待生产', time: '11:20' },
|
|
{ orderNo: 'ORD20260515004', customer: '开封汽配', amount: 67000, status: '生产中', time: '08:15' },
|
|
{ orderNo: 'ORD20260515005', customer: '商丘金属', amount: 45000, status: '已完成', time: '07:30' }
|
|
])
|
|
|
|
const formatAmount = (amount) => {
|
|
return '¥' + (amount / 10000).toFixed(2) + '万'
|
|
}
|
|
|
|
const updateTime = () => {
|
|
currentTime.value = new Date().toLocaleString('zh-CN', {
|
|
year: 'numeric', month: '2-digit', day: '2-digit',
|
|
hour: '2-digit', minute: '2-digit', second: '2-digit'
|
|
})
|
|
}
|
|
|
|
const initCharts = () => {
|
|
if (trendChartRef.value) {
|
|
trendChart = echarts.init(trendChartRef.value)
|
|
trendChart.setOption({
|
|
grid: { top: 30, right: 30, bottom: 30, left: 60 },
|
|
tooltip: { trigger: 'axis' },
|
|
xAxis: {
|
|
type: 'category',
|
|
data: ['1月', '2月', '3月', '4月', '5月', '6月'],
|
|
axisLine: { lineStyle: { color: '#2a3f5c' } },
|
|
axisTick: { show: false },
|
|
axisLabel: { color: '#999' }
|
|
},
|
|
yAxis: {
|
|
type: 'value',
|
|
axisLine: { show: false },
|
|
axisTick: { show: false },
|
|
splitLine: { lineStyle: { color: 'rgba(255,255,255,0.1)' } },
|
|
axisLabel: { color: '#999' }
|
|
},
|
|
series: [{
|
|
type: 'bar',
|
|
data: [35, 42, 38, 45, 40, 48],
|
|
itemStyle: {
|
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
{ offset: 0, color: '#1A5CD7' },
|
|
{ offset: 1, color: '#5cd9e8' }
|
|
]),
|
|
borderRadius: [4, 4, 0, 0]
|
|
}
|
|
}]
|
|
})
|
|
}
|
|
|
|
if (pieChartRef.value) {
|
|
pieChart = echarts.init(pieChartRef.value)
|
|
pieChart.setOption({
|
|
tooltip: { trigger: 'item' },
|
|
legend: { bottom: 10, textStyle: { color: '#999' } },
|
|
series: [{
|
|
type: 'pie',
|
|
radius: ['40%', '70%'],
|
|
center: ['50%', '40%'],
|
|
data: [
|
|
{ value: 45, name: '生产中', itemStyle: { color: '#409eff' } },
|
|
{ value: 12, name: '待生产', itemStyle: { color: '#e6a23c' } },
|
|
{ value: 156, name: '已完成', itemStyle: { color: '#67c23a' } }
|
|
],
|
|
label: { show: false }
|
|
}]
|
|
})
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
updateTime()
|
|
timeInterval = setInterval(updateTime, 1000)
|
|
initCharts()
|
|
window.addEventListener('resize', () => {
|
|
trendChart?.resize()
|
|
pieChart?.resize()
|
|
})
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
if (timeInterval) clearInterval(timeInterval)
|
|
trendChart?.dispose()
|
|
pieChart?.dispose()
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.big-screen {
|
|
width: 1920px;
|
|
height: 1080px;
|
|
background: linear-gradient(135deg, #0a0e27 0%, #1a1f4e 100%);
|
|
color: #d3d6dd;
|
|
}
|
|
|
|
.screen-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 20px 40px;
|
|
|
|
.title { font-size: 32px; font-weight: bold; color: #fff; text-shadow: 0 0 20px rgba(26, 92, 215, 0.8); letter-spacing: 4px; }
|
|
.time { font-size: 18px; color: #5cd9e8; font-family: 'Courier New', monospace; }
|
|
}
|
|
|
|
.screen-body { padding: 0 20px; }
|
|
|
|
.card-grid {
|
|
display: flex;
|
|
justify-content: space-around;
|
|
padding: 20px 0;
|
|
|
|
.data-card {
|
|
width: 22%;
|
|
background: rgba(19, 25, 47, 0.8);
|
|
border: 1px solid rgba(26, 92, 215, 0.3);
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
text-align: center;
|
|
|
|
.card-title { font-size: 16px; color: #999; margin-bottom: 10px; }
|
|
.card-value { font-size: 36px; font-weight: bold; margin-bottom: 5px; }
|
|
.card-unit { font-size: 14px; color: #666; }
|
|
}
|
|
}
|
|
|
|
.chart-area {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr 1fr;
|
|
gap: 20px;
|
|
padding: 20px 0;
|
|
|
|
.chart-box {
|
|
background: rgba(19, 25, 47, 0.8);
|
|
border: 1px solid rgba(26, 92, 215, 0.3);
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
|
|
.box-title { font-size: 16px; color: #5cd9e8; margin-bottom: 15px; padding-left: 10px; border-left: 3px solid #1A5CD7; }
|
|
.chart { height: 280px; }
|
|
|
|
.ranking-list {
|
|
height: 280px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-around;
|
|
|
|
.ranking-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 10px 15px;
|
|
background: rgba(26, 92, 215, 0.1);
|
|
border-radius: 6px;
|
|
|
|
.rank {
|
|
width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
|
|
font-size: 12px; font-weight: bold; margin-right: 12px; background: rgba(255,255,255,0.1);
|
|
&.rank-1 { background: linear-gradient(135deg, #ffd700, #ffb700); color: #fff; }
|
|
&.rank-2 { background: linear-gradient(135deg, #c0c0c0, #a0a0a0); color: #fff; }
|
|
&.rank-3 { background: linear-gradient(135deg, #cd7f32, #b87333); color: #fff; }
|
|
}
|
|
|
|
.name { flex: 1; font-size: 14px; color: #d3d6dd; }
|
|
.value { font-size: 16px; font-weight: bold; color: #5cd9e8; margin-right: 5px; }
|
|
.unit { font-size: 12px; color: #666; }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.order-list-box {
|
|
background: rgba(19, 25, 47, 0.8);
|
|
border: 1px solid rgba(26, 92, 215, 0.3);
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
margin-top: 20px;
|
|
|
|
.box-title { font-size: 16px; color: #5cd9e8; margin-bottom: 15px; padding-left: 10px; border-left: 3px solid #1A5CD7; }
|
|
|
|
.order-table {
|
|
.table-header {
|
|
display: grid;
|
|
grid-template-columns: 2fr 2fr 1.5fr 1fr 1fr;
|
|
gap: 15px;
|
|
padding: 10px 15px;
|
|
background: rgba(26, 92, 215, 0.2);
|
|
border-radius: 4px;
|
|
font-size: 14px;
|
|
color: #999;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.table-body {
|
|
max-height: 250px;
|
|
overflow-y: auto;
|
|
|
|
.table-row {
|
|
display: grid;
|
|
grid-template-columns: 2fr 2fr 1.5fr 1fr 1fr;
|
|
gap: 15px;
|
|
padding: 12px 15px;
|
|
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
font-size: 14px;
|
|
|
|
.order-no { color: #5cd9e8; font-family: 'Courier New', monospace; }
|
|
.amount { color: #ff9800; font-weight: 600; }
|
|
.status {
|
|
padding: 2px 8px; border-radius: 4px; font-size: 12px; text-align: center;
|
|
&.已完成 { background: rgba(103,194,58,0.2); color: #67c23a; }
|
|
&.生产中 { background: rgba(64,158,255,0.2); color: #409eff; }
|
|
&.待生产 { background: rgba(230,162,60,0.2); color: #e6a23c; }
|
|
}
|
|
.time { color: #999; }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|