Files
screen/src/modules/dashboardBig/views/order.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>