You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
livestock-trading/src/components/Outdoor/YakTradingOverview.vue

275 lines
7.2 KiB

<template>
<div class="trading-overview-card">
<div class="card-header">
<div class="title-container">
<h2 class="card-title">牦牛实时交易概况</h2>
<div class="title-tibetan">འབགཡགའདགནསངས</div>
</div>
</div>
<div class="overview-content">
<div class="stats-grid">
<div class="stat-item">
<div class="stat-label">
<span class="chinese">今日入场牦牛数</span>
<span class="tibetan">གསཔའགཡགངས</span>
</div>
<div class="stat-value primary">{{ todayEntryYaks }}</div>
<div class="stat-unit"></div>
</div>
<div class="stat-item">
<div class="stat-label">
<span class="chinese">已交易牦牛数</span>
<span class="tibetan">པའགཡགངས</span>
</div>
<div class="stat-value success">{{ tradedYaks }}</div>
<div class="stat-unit"></div>
</div>
<div class="stat-item">
<div class="stat-label">
<span class="chinese">待交易牦牛数</span>
<span class="tibetan">བསཔའགཡགངས</span>
</div>
<div class="stat-value warning">{{ waitingYaks }}</div>
<div class="stat-unit"></div>
</div>
<div class="stat-item">
<div class="stat-label">
<span class="chinese">卖家人数</span>
<span class="tibetan">པའངས</span>
</div>
<div class="stat-value info">{{ sellerCount }}</div>
<div class="stat-unit"></div>
</div>
<div class="stat-item">
<div class="stat-label">
<span class="chinese">剩余车位</span>
<span class="tibetan">པའགནསསའངས</span>
</div>
<div class="stat-value danger">{{ remainingParkingSpots }}</div>
<div class="stat-unit"></div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
// 实时交易概况数据
const todayEntryYaks = ref(0) // 今日入场牦牛数
const tradedYaks = ref(0) // 已交易牦牛数
const waitingYaks = ref(0) // 待交易牦牛数
const sellerCount = ref(0) // 卖家人数
const remainingParkingSpots = ref(0) // 剩余车位
let updateTimer = null
// 加载牦牛实时交易概况数据
const loadTradingOverviewData = async () => {
try {
console.log('正在从JSON文件加载牦牛实时交易概况数据...')
const response = await fetch('/牦牛实时交易概况.json')
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const data = await response.json()
if (data.牦牛实时交易概况) {
const overview = data.牦牛实时交易概况
todayEntryYaks.value = overview.todayEntryYaks || 0
tradedYaks.value = overview.tradedYaks || 0
waitingYaks.value = overview.waitingYaks || 0
sellerCount.value = overview.sellerCount || 0
remainingParkingSpots.value = overview.remainingParkingSpots || 0
console.log('成功加载牦牛实时交易概况数据')
} else {
throw new Error('牦牛实时交易概况数据格式不正确')
}
} catch (error) {
console.error('加载牦牛实时交易概况数据失败,使用默认数据:', error)
loadDefaultTradingData()
}
}
// 加载默认数据(作为备用方案)
const loadDefaultTradingData = () => {
todayEntryYaks.value = 1256
tradedYaks.value = 847
waitingYaks.value = 409
sellerCount.value = 168
remainingParkingSpots.value = 32
}
// 模拟数据更新
const startDataUpdate = () => {
updateTimer = setInterval(() => {
// 随机增加入场牦牛数
const newEntry = Math.floor(Math.random() * 5)
todayEntryYaks.value += newEntry
// 随机交易一些牦牛
const newTrades = Math.floor(Math.random() * 3)
if (waitingYaks.value >= newTrades) {
tradedYaks.value += newTrades
waitingYaks.value -= newTrades
}
// 更新待交易数量(新入场 - 新交易)
waitingYaks.value += (newEntry - newTrades)
if (waitingYaks.value < 0) waitingYaks.value = 0
// 偶尔更新卖家人数和车位
if (Math.random() > 0.7) {
sellerCount.value += Math.floor(Math.random() * 3) - 1 // -1到1的变化
remainingParkingSpots.value += Math.floor(Math.random() * 5) - 2 // -2到2的变化
// 确保数值合理
if (sellerCount.value < 100) sellerCount.value = 100
if (sellerCount.value > 300) sellerCount.value = 300
if (remainingParkingSpots.value < 0) remainingParkingSpots.value = 0
if (remainingParkingSpots.value > 50) remainingParkingSpots.value = 50
}
}, 30000) // 30秒更新一次
}
onMounted(async () => {
await loadTradingOverviewData()
startDataUpdate()
})
onUnmounted(() => {
if (updateTimer) {
clearInterval(updateTimer)
updateTimer = null
}
})
</script>
<style scoped>
.trading-overview-card {
height: 100%;
background: rgba(15, 25, 45, 0.4);
backdrop-filter: blur(20px) saturate(180%);
border-radius: 32px;
padding: 24px;
display: flex;
flex-direction: column;
box-shadow:
0 16px 64px rgba(0, 0, 0, 0.3),
0 8px 32px rgba(64, 158, 255, 0.1),
inset 0 2px 0 rgba(255, 255, 255, 0.1);
}
.card-header {
margin-bottom: 40px;
}
.title-container {
display: flex;
align-items: center;
gap: 32px;
}
.card-title {
font-size: 28px;
font-weight: 700;
background: linear-gradient(135deg, #409EFF 0%, #67C23A 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin: 0;
text-align: left;
}
.title-tibetan {
font-size: 28px;
color: #67C23A;
font-weight: 600;
opacity: 0.8;
}
.overview-content {
flex: 1;
display: flex;
flex-direction: column;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 20px;
flex: 1;
}
.stat-item {
background: rgba(255, 255, 255, 0.05);
border-radius: 20px;
padding: 24px;
text-align: center;
border: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
flex-direction: column;
justify-content: center;
min-height: 0;
}
.stat-label {
margin-bottom: 20px;
display: flex;
flex-direction: column;
gap: 8px;
}
.stat-label .chinese {
font-size: 28px;
color: #ffffff;
font-weight: 600;
line-height: 1.2;
}
.stat-label .tibetan {
font-size: 28px;
color: #67C23A;
opacity: 0.8;
line-height: 1.2;
}
.stat-value {
font-size: 64px;
font-weight: 700;
margin-bottom: 8px;
line-height: 1;
}
.stat-value.primary {
color: #409EFF;
}
.stat-value.success {
color: #67C23A;
}
.stat-value.warning {
color: #E6A23C;
}
.stat-value.danger {
color: #F56C6C;
}
.stat-value.info {
color: #17A2B8;
}
.stat-unit {
font-size: 32px;
color: #a0a8b8;
margin-top: 8px;
}
</style>