2025-12-08 15:24:43 +08:00
|
|
|
|
|
2025-12-10 17:19:01 +08:00
|
|
|
|
// 订单列表逻辑
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
const orders = [
|
|
|
|
|
|
{ id: 'ORD001', amount: '¥12,000', status: '已完成', class: 'status-done' },
|
|
|
|
|
|
{ id: 'ORD002', amount: '¥8,500', status: '运输中', class: 'status-shipping' },
|
|
|
|
|
|
{ id: 'ORD003', amount: '¥15,000', status: '待发货', class: 'status-pending' },
|
|
|
|
|
|
{ id: 'ORD004', amount: '¥9,200', status: '已完成', class: 'status-done' },
|
|
|
|
|
|
{ id: 'ORD005', amount: '¥21,000', status: '运输中', class: 'status-shipping' },
|
|
|
|
|
|
{ id: 'ORD006', amount: '¥6,800', status: '已完成', class: 'status-done' }
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
function renderOrderList() {
|
|
|
|
|
|
const container = $('.order_list_content');
|
|
|
|
|
|
if (container.length === 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
let html = '';
|
|
|
|
|
|
orders.forEach(order => {
|
|
|
|
|
|
html += `
|
|
|
|
|
|
<div class="order_item">
|
|
|
|
|
|
<span>${order.id}</span>
|
|
|
|
|
|
<span>${order.amount}</span>
|
|
|
|
|
|
<span class="${order.class}">${order.status}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
`;
|
|
|
|
|
|
});
|
|
|
|
|
|
container.html(html);
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-10 17:19:01 +08:00
|
|
|
|
// 模拟新订单
|
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
|
const newId = 'ORD' + String(Date.now()).slice(-3);
|
|
|
|
|
|
const amount = '¥' + (Math.floor(Math.random() * 20000) + 5000).toLocaleString();
|
|
|
|
|
|
const statuses = [
|
|
|
|
|
|
{ text: '已完成', class: 'status-done' },
|
|
|
|
|
|
{ text: '运输中', class: 'status-shipping' },
|
|
|
|
|
|
{ text: '待发货', class: 'status-pending' }
|
|
|
|
|
|
];
|
|
|
|
|
|
const status = statuses[Math.floor(Math.random() * statuses.length)];
|
|
|
|
|
|
|
|
|
|
|
|
orders.unshift({
|
|
|
|
|
|
id: newId,
|
|
|
|
|
|
amount: amount,
|
|
|
|
|
|
status: status.text,
|
|
|
|
|
|
class: status.class
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (orders.length > 10) orders.pop(); // 保持列表长度
|
|
|
|
|
|
|
|
|
|
|
|
renderOrderList();
|
|
|
|
|
|
}, 5000);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化
|
|
|
|
|
|
$(function() {
|
|
|
|
|
|
renderOrderList();
|
|
|
|
|
|
});
|
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
|
|
// 牛只概况列表逻辑
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
const cattleData = [
|
|
|
|
|
|
{ name: '中山仓', value: 10 },
|
|
|
|
|
|
{ name: '横沥仓', value: 23 },
|
|
|
|
|
|
{ name: '三水仓', value: 12 },
|
|
|
|
|
|
{ name: '陆丰仓', value: 30 },
|
|
|
|
|
|
{ name: '博罗仓', value: 21 },
|
|
|
|
|
|
{ name: '梅州仓', value: 34 },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
function renderCattleOverview() {
|
|
|
|
|
|
const container = $('#cattle_overview_container');
|
|
|
|
|
|
if (container.length === 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
let html = '';
|
|
|
|
|
|
cattleData.forEach(item => {
|
|
|
|
|
|
html += `
|
|
|
|
|
|
<div class="cattle_item" data-name="${item.name}">
|
|
|
|
|
|
<div class="cattle_icon">
|
|
|
|
|
|
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="cattle_info">
|
|
|
|
|
|
<span class="cattle_name">${item.name}</span>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<span class="cattle_value">${item.value}</span>
|
|
|
|
|
|
<span class="cattle_unit">头</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
`;
|
|
|
|
|
|
});
|
|
|
|
|
|
container.html(html);
|
|
|
|
|
|
}
|
2025-12-08 15:24:43 +08:00
|
|
|
|
|
2025-12-10 17:19:01 +08:00
|
|
|
|
// 模拟数据波动
|
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
|
const index = Math.floor(Math.random() * cattleData.length);
|
|
|
|
|
|
const change = Math.floor(Math.random() * 3) - 1; // -1, 0, 1
|
|
|
|
|
|
let newVal = cattleData[index].value + change;
|
|
|
|
|
|
if (newVal < 0) newVal = 0;
|
|
|
|
|
|
cattleData[index].value = newVal;
|
|
|
|
|
|
renderCattleOverview();
|
|
|
|
|
|
}, 3000);
|
|
|
|
|
|
|
|
|
|
|
|
$(function() {
|
|
|
|
|
|
renderCattleOverview();
|
|
|
|
|
|
|
|
|
|
|
|
// 点击跳转到监控页面
|
|
|
|
|
|
$('#cattle_overview_container').on('click', '.cattle_item', function() {
|
|
|
|
|
|
const name = $(this).data('name');
|
|
|
|
|
|
if (name) {
|
|
|
|
|
|
window.location.href = 'monitor.html?warehouse=' + encodeURIComponent(name);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
|
|
// 牛只行情列表逻辑
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
let scrollInterval;
|
|
|
|
|
|
|
|
|
|
|
|
function fetchAndRenderMarketList() {
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
|
// 使用本地代理接口解决跨域问题
|
|
|
|
|
|
// 原接口: https://ad.yunmainiu.com/api/cattle-data
|
|
|
|
|
|
// 代理配置在 server.js 中: /api/cattle-market-data -> https://ad.yunmainiu.com/api/cattle-data
|
|
|
|
|
|
url: '/api/cattle-market-data',
|
|
|
|
|
|
method: 'GET',
|
|
|
|
|
|
success: function(response) {
|
|
|
|
|
|
// 尝试解析字符串响应
|
|
|
|
|
|
if (typeof response === 'string') {
|
|
|
|
|
|
try {
|
|
|
|
|
|
response = JSON.parse(response);
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('JSON解析失败:', e);
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-10 17:19:01 +08:00
|
|
|
|
let data = [];
|
|
|
|
|
|
// 兼容可能的返回格式:直接数组 或 { data: [] }
|
|
|
|
|
|
if (Array.isArray(response)) {
|
|
|
|
|
|
data = response;
|
|
|
|
|
|
} else if (response && Array.isArray(response.data)) {
|
|
|
|
|
|
data = response.data;
|
|
|
|
|
|
} else if (response && Array.isArray(response.list)) {
|
|
|
|
|
|
data = response.list;
|
|
|
|
|
|
}
|
2025-12-08 15:24:43 +08:00
|
|
|
|
|
2025-12-10 17:19:01 +08:00
|
|
|
|
console.log('获取到的牛只行情数据:', data);
|
|
|
|
|
|
renderMarketList(data);
|
2025-12-08 15:24:43 +08:00
|
|
|
|
},
|
2025-12-10 17:19:01 +08:00
|
|
|
|
error: function(err) {
|
|
|
|
|
|
console.error('获取牛只行情数据失败:', err);
|
|
|
|
|
|
// 失败时显示空或错误提示,或者保留旧数据
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
2025-12-10 17:19:01 +08:00
|
|
|
|
});
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-10 17:19:01 +08:00
|
|
|
|
function renderMarketList(data) {
|
|
|
|
|
|
const container = $('.market_list_content');
|
|
|
|
|
|
if (container.length === 0) return;
|
|
|
|
|
|
|
|
|
|
|
|
let html = '';
|
|
|
|
|
|
if (data.length === 0) {
|
|
|
|
|
|
html = '<div style="text-align:center;color:#ccc;padding:20px;">暂无数据</div>';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
data.forEach((item, index) => {
|
|
|
|
|
|
// 接口字段: province(省份), location(地区), type(品种), price(单价)
|
|
|
|
|
|
html += `
|
|
|
|
|
|
<div class="market_item">
|
|
|
|
|
|
<span>${index + 1}</span>
|
|
|
|
|
|
<span>${item.province || '--'}</span>
|
|
|
|
|
|
<span>${item.location || '--'}</span>
|
|
|
|
|
|
<span>${item.type || '--'}</span>
|
|
|
|
|
|
<span class="market_price">${item.price || '--'}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
`;
|
|
|
|
|
|
});
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
2025-12-10 17:19:01 +08:00
|
|
|
|
container.html(html);
|
|
|
|
|
|
|
|
|
|
|
|
// 清除旧的滚动定时器
|
|
|
|
|
|
if (scrollInterval) {
|
|
|
|
|
|
clearInterval(scrollInterval);
|
|
|
|
|
|
scrollInterval = null;
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-10 17:19:01 +08:00
|
|
|
|
// 简单的自动滚动效果
|
|
|
|
|
|
// 需要等待DOM渲染完成后计算高度,这里简单使用setTimeout
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
let scrollPos = 0;
|
|
|
|
|
|
// 重新获取DOM元素属性,确保准确
|
|
|
|
|
|
const scrollHeight = container[0].scrollHeight;
|
|
|
|
|
|
const clientHeight = container[0].clientHeight;
|
|
|
|
|
|
|
|
|
|
|
|
// 只有当内容高度超过容器高度时才滚动
|
|
|
|
|
|
if (scrollHeight > clientHeight) {
|
|
|
|
|
|
scrollInterval = setInterval(() => {
|
|
|
|
|
|
scrollPos += 1;
|
|
|
|
|
|
// 当滚动到底部时,回到顶部
|
|
|
|
|
|
if (scrollPos >= scrollHeight - clientHeight) {
|
|
|
|
|
|
scrollPos = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
container.scrollTop(scrollPos);
|
|
|
|
|
|
}, 50);
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
2025-12-10 17:19:01 +08:00
|
|
|
|
}, 100);
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-10 17:19:01 +08:00
|
|
|
|
$(function() {
|
|
|
|
|
|
fetchAndRenderMarketList();
|
|
|
|
|
|
|
|
|
|
|
|
// 每60秒刷新一次数据
|
|
|
|
|
|
setInterval(fetchAndRenderMarketList, 60000);
|
2025-12-08 15:24:43 +08:00
|
|
|
|
});
|
2025-12-10 17:19:01 +08:00
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
|
|
// 出肉率图表逻辑
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
// 确保 DOM 加载完成
|
|
|
|
|
|
$(function() {
|
|
|
|
|
|
const chartDom = document.getElementById('meat_yield_chart');
|
|
|
|
|
|
if (!chartDom) return;
|
|
|
|
|
|
|
|
|
|
|
|
const myChart = echarts.init(chartDom);
|
|
|
|
|
|
|
|
|
|
|
|
const option = {
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
|
axisPointer: { type: 'shadow' }
|
|
|
|
|
|
},
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
left: '3%',
|
|
|
|
|
|
right: '10%',
|
|
|
|
|
|
bottom: '3%',
|
|
|
|
|
|
top: '10%',
|
|
|
|
|
|
containLabel: true
|
|
|
|
|
|
},
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
fontSize: 12
|
2025-12-08 15:24:43 +08:00
|
|
|
|
},
|
2025-12-10 17:19:01 +08:00
|
|
|
|
splitLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: 'rgba(255,255,255,0.1)'
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-12-10 17:19:01 +08:00
|
|
|
|
axisLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: '#fff'
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-10 17:19:01 +08:00
|
|
|
|
},
|
|
|
|
|
|
yAxis: {
|
|
|
|
|
|
type: 'category',
|
|
|
|
|
|
data: ['鲁西黄牛', '西门塔尔', '夏洛莱', '利木赞', '安格斯'],
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
fontSize: 12
|
2025-12-08 15:24:43 +08:00
|
|
|
|
},
|
2025-12-10 17:19:01 +08:00
|
|
|
|
axisLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: '#fff'
|
|
|
|
|
|
}
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
2025-12-10 17:19:01 +08:00
|
|
|
|
},
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '出肉率',
|
|
|
|
|
|
type: 'bar',
|
|
|
|
|
|
data: [45, 52, 58, 55, 60],
|
|
|
|
|
|
itemStyle: {
|
|
|
|
|
|
normal: {
|
|
|
|
|
|
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
|
|
|
|
|
{ offset: 0, color: '#2b86ff' },
|
|
|
|
|
|
{ offset: 1, color: '#1effc0' }
|
|
|
|
|
|
]),
|
|
|
|
|
|
barBorderRadius: [0, 5, 5, 0]
|
|
|
|
|
|
}
|
2025-12-08 15:24:43 +08:00
|
|
|
|
},
|
|
|
|
|
|
label: {
|
2025-12-10 17:19:01 +08:00
|
|
|
|
show: true,
|
|
|
|
|
|
position: 'right',
|
|
|
|
|
|
formatter: '{c}%',
|
|
|
|
|
|
color: '#fff'
|
2025-12-08 15:24:43 +08:00
|
|
|
|
},
|
2025-12-10 17:19:01 +08:00
|
|
|
|
barWidth: '40%'
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
2025-12-10 17:19:01 +08:00
|
|
|
|
]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
myChart.setOption(option);
|
|
|
|
|
|
|
|
|
|
|
|
// 窗口大小改变时重置图表大小
|
|
|
|
|
|
window.addEventListener("resize", function () {
|
|
|
|
|
|
myChart.resize();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 模拟数据动态变化
|
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
|
const newData = option.series[0].data.map(val => {
|
|
|
|
|
|
let change = Math.floor(Math.random() * 3) - 1;
|
|
|
|
|
|
let newVal = val + change;
|
|
|
|
|
|
if (newVal > 70) newVal = 70;
|
|
|
|
|
|
if (newVal < 35) newVal = 35;
|
|
|
|
|
|
return newVal;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
myChart.setOption({
|
|
|
|
|
|
series: [{
|
|
|
|
|
|
data: newData
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
|
|
|
|
|
}, 5000);
|
|
|
|
|
|
});
|
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
|
|
// 屠宰场概况图表逻辑
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
// 确保 DOM 加载完成
|
|
|
|
|
|
$(function() {
|
|
|
|
|
|
const chartDom = document.getElementById('slaughterhouse_chart');
|
|
|
|
|
|
if (!chartDom) return;
|
|
|
|
|
|
|
|
|
|
|
|
const myChart = echarts.init(chartDom);
|
|
|
|
|
|
|
|
|
|
|
|
const option = {
|
|
|
|
|
|
tooltip: {
|
|
|
|
|
|
trigger: 'item',
|
|
|
|
|
|
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
|
|
|
|
|
},
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
orient: 'vertical',
|
|
|
|
|
|
right: 10,
|
|
|
|
|
|
top: 'center',
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
color: '#fff'
|
|
|
|
|
|
},
|
|
|
|
|
|
data: ['正常运行', '检修中', '待运行', '已关闭']
|
|
|
|
|
|
},
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '屠宰场状态',
|
|
|
|
|
|
type: 'pie',
|
|
|
|
|
|
radius: ['50%', '70%'],
|
|
|
|
|
|
center: ['35%', '50%'],
|
|
|
|
|
|
avoidLabelOverlap: false,
|
2025-12-08 15:24:43 +08:00
|
|
|
|
label: {
|
2025-12-10 17:19:01 +08:00
|
|
|
|
show: false,
|
|
|
|
|
|
position: 'center'
|
|
|
|
|
|
},
|
|
|
|
|
|
emphasis: {
|
|
|
|
|
|
label: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
fontSize: '20',
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
color: '#fff'
|
|
|
|
|
|
}
|
2025-12-08 15:24:43 +08:00
|
|
|
|
},
|
|
|
|
|
|
labelLine: {
|
|
|
|
|
|
show: false
|
|
|
|
|
|
},
|
2025-12-10 17:19:01 +08:00
|
|
|
|
data: [
|
|
|
|
|
|
{ value: 12, name: '正常运行', itemStyle: { color: '#37a2da' } },
|
|
|
|
|
|
{ value: 3, name: '检修中', itemStyle: { color: '#ffdb5c' } },
|
|
|
|
|
|
{ value: 5, name: '待运行', itemStyle: { color: '#ff9f7f' } },
|
|
|
|
|
|
{ value: 1, name: '已关闭', itemStyle: { color: '#fb7293' } }
|
|
|
|
|
|
]
|
2025-12-08 15:24:43 +08:00
|
|
|
|
}
|
2025-12-10 17:19:01 +08:00
|
|
|
|
]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
myChart.setOption(option);
|
|
|
|
|
|
|
|
|
|
|
|
// 窗口大小改变时重置图表大小
|
|
|
|
|
|
window.addEventListener("resize", function () {
|
|
|
|
|
|
myChart.resize();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 模拟数据动态变化
|
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
|
const newData = option.series[0].data.map(item => {
|
|
|
|
|
|
let change = Math.floor(Math.random() * 3) - 1;
|
|
|
|
|
|
let newVal = item.value + change;
|
|
|
|
|
|
if (newVal < 0) newVal = 0;
|
|
|
|
|
|
return { ...item, value: newVal };
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
myChart.setOption({
|
|
|
|
|
|
series: [{
|
|
|
|
|
|
data: newData
|
|
|
|
|
|
}]
|
|
|
|
|
|
});
|
|
|
|
|
|
}, 6000);
|
|
|
|
|
|
});
|
|
|
|
|
|
})();
|