添加接口

This commit is contained in:
2025-12-11 17:30:38 +08:00
parent 0927b5bcd8
commit 5b44cdb3eb
26 changed files with 613 additions and 212 deletions

View File

@@ -1,119 +1,530 @@
// 订单列表逻辑
(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' }
];
// 存储 Token
let authToken = '';
function renderOrderList() {
// 登录并获取订单数据
function loginAndFetchOrders() {
// 如果已有 Token直接获取订单
if (authToken) {
fetchOrders();
return;
}
// 登录接口
$.ajax({
url: '/api/login',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({
mobile: '18888888888', // 请替换为真实账号
password: '123456', // 请替换为真实密码
loginType: 0
}),
success: function(res) {
console.log('登录接口完整响应:', res);
// 兼容多种 Token 返回结构
// 1. res.data.tokenValue (Sa-Token 常见)
// 2. res.data.token (常见 JWT)
// 3. res.token (根层级)
// 4. res.data (直接返回字符串)
let token = '';
if (res && res.code === 200) {
if (res.data && res.data.tokenValue) {
token = res.data.tokenValue;
} else if (res.data && res.data.token) {
token = res.data.token;
} else if (res.token) {
token = res.token;
} else if (typeof res.data === 'string') {
token = res.data;
}
}
if (token) {
authToken = token;
console.log('登录成功获取到Token:', authToken);
fetchOrders();
fetchCattleOverview();
fetchSlaughterOverview();
} else {
console.error('登录成功但未能提取Token请检查响应结构:', res);
}
},
error: function(err) {
console.error('登录请求错误:', err);
}
});
}
// 获取订单列表
function fetchOrders() {
if (!authToken) return;
$.ajax({
url: '/api/delivery/pageQueryList',
method: 'POST', // 假设是 POST 分页查询
contentType: 'application/json',
headers: {
'Authorization': authToken,
// 或者根据后端要求可能是其他 header key如 satoken
'satoken': authToken
},
data: JSON.stringify({
pageNo: 1,
pageSize: 300,
interfaceType: 2
}),
success: function(res) {
console.log('订单列表响应:', res);
let list = [];
if (res && res.data && Array.isArray(res.data.rows)) {
// 适配 { code: 200, data: { rows: [...] } } 结构
list = res.data.rows;
} else if (res && res.data && Array.isArray(res.data.records)) {
// 适配 { code: 200, data: { records: [...] } } 结构
list = res.data.records;
} else if (res && Array.isArray(res.data)) {
// 适配 { code: 200, data: [...] } 结构
list = res.data;
}
renderOrderList(list);
renderOrderStatusStats(list);
updateMapWithFlyLines(list);
},
error: function(err) {
console.error('获取订单列表失败:', err);
if (err.status === 401) {
// Token 过期,重新登录
authToken = '';
loginAndFetchOrders();
}
}
});
}
function renderOrderStatusStats(orders) {
if (!orders || !Array.isArray(orders)) return;
let pendingCount = 0; // status: 1
let shippingCount = 0; // status: 2
let doneCount = 0; // status: 3
orders.forEach(order => {
const status = parseInt(order.status);
if (status === 1) {
pendingCount++;
} else if (status === 2) {
shippingCount++;
} else if (status === 3) {
doneCount++;
}
});
// 更新 DOM
$('.stat-value[data-field="status_pending"]').text(pendingCount);
$('.stat-value[data-field="status_shipping"]').text(shippingCount);
$('.stat-value[data-field="status_done"]').text(doneCount);
}
function updateMapWithFlyLines(data) {
if (!data || !Array.isArray(data)) return;
const flyLineData = [];
const pointMap = new Map(); // 用于去重地点
data.forEach(item => {
// startLon, startLat, endLon, endLat
if (item.startLon && item.startLat && item.endLon && item.endLat) {
// 1. 飞线数据
flyLineData.push({
fromName: item.startLocation || item.startAddress || '',
toName: item.endLocation || item.endAddress || '',
coords: [
[parseFloat(item.startLon), parseFloat(item.startLat)], // 起点
[parseFloat(item.endLon), parseFloat(item.endLat)] // 终点
]
});
// 2. 起点数据 (用于显示名称)
const startName = item.startLocation || item.startAddress || '';
if (startName) {
const startKey = `${startName}_${item.startLon}_${item.startLat}`;
if (!pointMap.has(startKey)) {
pointMap.set(startKey, {
name: startName,
value: [parseFloat(item.startLon), parseFloat(item.startLat)]
});
}
}
// 3. 终点数据 (用于显示名称)
const endName = item.endLocation || item.endAddress || '';
if (endName) {
const endKey = `${endName}_${item.endLon}_${item.endLat}`;
if (!pointMap.has(endKey)) {
pointMap.set(endKey, {
name: endName,
value: [parseFloat(item.endLon), parseFloat(item.endLat)]
});
}
}
}
});
// 更新 option8 (全局变量)
if (typeof option8 !== 'undefined') {
// series[1] 是线路
if (option8.series && option8.series[1]) {
option8.series[1].data = flyLineData;
}
// series[3] 是运单地点 (我们在 chartMap.js 中新加的)
if (option8.series && option8.series[3]) {
option8.series[3].data = Array.from(pointMap.values());
}
// 尝试获取 echarts 实例并更新
if (typeof myChart8 !== 'undefined') {
myChart8.setOption(option8);
} else if (window.myChart8) {
window.myChart8.setOption(option8);
}
}
}
// 存储滚动定时器,防止重复创建
let orderScrollTimer = null;
function renderOrderList(orders) {
const container = $('.order_list_content');
if (container.length === 0) return;
// 清除旧的定时器和事件监听
if (orderScrollTimer) {
clearInterval(orderScrollTimer);
orderScrollTimer = null;
}
container.off('mouseenter mouseleave');
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);
}
if (orders.length === 0) {
html = '<div style="text-align:center;color:#ccc;padding:10px;">暂无运单</div>';
container.html(html);
} else {
orders.forEach((order, index) => {
// 状态映射: 1-准备中2-运送中3-已结束
let statusText = '--';
let statusClass = '';
// 确保 status 是数字
const status = parseInt(order.status);
switch(status) {
case 1:
statusText = '准备中';
statusClass = 'status-pending'; // 红色
break;
case 2:
statusText = '运送中';
statusClass = 'status-shipping'; // 黄色
break;
case 3:
statusText = '已结束';
statusClass = 'status-done'; // 绿色
break;
default:
statusText = '未知';
}
// 模拟新订单
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);
html += `
<div class="order_item">
<span>${index + 1}</span>
<span>${order.deliveryNumber || '--'}</span>
<span>${order.startLocation || order.startAddress || '--'}</span>
<span>${order.endLocation || order.endAddress || '--'}</span>
<span class="${statusClass}">${statusText}</span>
<span>${order.estimatedDeliveryTime || '--'}</span>
</div>
`;
});
container.html(html);
// 自动滚动逻辑
// 确保 DOM 渲染完成
setTimeout(() => {
const scrollHeight = container[0].scrollHeight;
const clientHeight = container.height();
// 只有当内容高度超过容器高度时才滚动
if (scrollHeight > clientHeight) {
// 复制一份内容实现无缝滚动
container.append(html);
let currentScroll = 0;
function startScroll() {
if (orderScrollTimer) clearInterval(orderScrollTimer);
orderScrollTimer = setInterval(() => {
currentScroll += 0.5; // 滚动速度,数值越小越慢
// 当滚动到第一份内容的末尾时,瞬间切换回顶部
if (currentScroll >= scrollHeight) {
currentScroll = 0;
}
container.scrollTop(currentScroll);
}, 20); // 刷新频率
}
startScroll();
// 鼠标悬停暂停
container.on('mouseenter', function() {
if (orderScrollTimer) clearInterval(orderScrollTimer);
});
// 鼠标移开继续
container.on('mouseleave', function() {
startScroll();
});
}
}, 100);
}
}
// 初始化
$(function() {
renderOrderList();
loginAndFetchOrders();
// 定时刷新 (每30秒)
setInterval(() => {
if (authToken) {
fetchOrders();
fetchCattleOverview();
fetchSlaughterOverview();
} else {
loginAndFetchOrders();
}
}, 30000);
});
})();
// 牛只概况列表逻辑
(function() {
const cattleData = [
{ name: '中山仓', value: 10 },
{ name: '横沥仓', value: 23 },
{ name: '三水仓', value: 12 },
{ name: '陆丰仓', value: 30 },
{ name: '博罗仓', value: 21 },
{ name: '梅州仓', value: 34 },
];
// 获取牛只概况(仓库列表)
function fetchCattleOverview() {
if (!authToken) return;
function renderCattleOverview() {
$.ajax({
url: '/api/warehouse/list',
method: 'POST', // 改为 POST
contentType: 'application/json',
headers: {
'Authorization': 'Bearer ' + authToken,
'satoken': authToken
},
data: JSON.stringify({
pageNo: 1,
pageSize: 100 // 假设需要分页参数,如果不传可能会报错
}),
success: function(res) {
console.log('牛只概况响应:', res);
let list = [];
// 适配双层嵌套结构: res.data.data.rows
if (res && res.code === 200 && res.data) {
if (res.data.data && Array.isArray(res.data.data.rows)) {
// 结构: { code: 200, data: { data: { rows: [...] } } }
list = res.data.data.rows;
} else if (res.data.rows && Array.isArray(res.data.rows)) {
// 结构: { code: 200, data: { rows: [...] } }
list = res.data.rows;
} else if (Array.isArray(res.data)) {
list = res.data;
}
}
renderCattleOverview(list);
updateMapWithWarehouseData(list);
},
error: function(err) {
console.error('获取牛只概况失败:', err);
}
});
}
function updateMapWithWarehouseData(data) {
if (!data || !Array.isArray(data)) return;
const mapData = data.map(item => {
if (item.longitude && item.latitude) {
return {
name: item.warehouseName || '未知仓库',
value: [parseFloat(item.longitude), parseFloat(item.latitude)]
};
}
return null;
}).filter(item => item !== null);
// 更新 option8 (全局变量)
if (typeof option8 !== 'undefined') {
// 假设 series[0] 是 scatter/effectScatter 用于显示地点
if (option8.series && option8.series[0]) {
option8.series[0].data = mapData;
}
// 尝试获取 echarts 实例并更新
// myChart8 在 index.html 中定义为 var myChart8 (全局)
if (typeof myChart8 !== 'undefined') {
myChart8.setOption(option8);
} else if (window.myChart8) {
window.myChart8.setOption(option8);
}
}
}
function renderCattleOverview(data) {
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>
if (!data || data.length === 0) {
html = '<div style="text-align:center;color:#ccc;padding:10px;width:100%;">暂无数据</div>';
} else {
data.forEach(item => {
// 接口字段: warehouseName, account
if (item.account === undefined) {
console.warn('牛只概况接口返回数据缺少 account 字段,请检查接口文档或后端返回:', item);
}
const name = item.warehouseName || '--';
const value = item.account || 0;
html += `
<div class="cattle_item">
<div class="cattle_icon">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
</div>
<div class="cattle_info">
<span class="cattle_name" title="${name}">${name}</span>
<div>
<span class="cattle_value">${value}</span>
<span class="cattle_unit">头</span>
</div>
</div>
</div>
</div>
`;
});
`;
});
}
container.html(html);
}
// 模拟数据波动
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 fetchSlaughterOverview() {
if (!authToken) return;
$(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);
$.ajax({
url: '/api/slaughter/house/list',
method: 'POST',
contentType: 'application/json',
headers: {
'Authorization': 'Bearer ' + authToken,
'satoken': authToken
},
data: JSON.stringify({
pageNo: 1,
pageSize: 100
}),
success: function(res) {
console.log('屠宰场概况响应:', res);
let list = [];
// 适配双层嵌套结构: res.data.data.rows
if (res && res.code === 200 && res.data) {
if (res.data.data && Array.isArray(res.data.data.rows)) {
list = res.data.data.rows;
} else if (res.data.rows && Array.isArray(res.data.rows)) {
list = res.data.rows;
} else if (Array.isArray(res.data)) {
list = res.data;
}
}
renderSlaughterOverview(list);
updateMapWithSlaughterData(list);
},
error: function(err) {
console.error('获取屠宰场概况失败:', err);
}
});
});
}
function updateMapWithSlaughterData(data) {
if (!data || !Array.isArray(data)) return;
const mapData = data.map(item => {
if (item.longitude && item.latitude) {
return {
name: item.houseName || '未知屠宰场',
value: [parseFloat(item.longitude), parseFloat(item.latitude)]
};
}
return null;
}).filter(item => item !== null);
// 更新 option8 (全局变量)
if (typeof option8 !== 'undefined') {
// series[2] 是屠宰场
if (option8.series && option8.series[2]) {
option8.series[2].data = mapData;
}
// 尝试获取 echarts 实例并更新
if (typeof myChart8 !== 'undefined') {
myChart8.setOption(option8);
} else if (window.myChart8) {
window.myChart8.setOption(option8);
}
}
}
function renderSlaughterOverview(data) {
const container = $('#slaughterhouse_overview_container');
if (container.length === 0) return;
let html = '';
if (!data || data.length === 0) {
html = '<div style="text-align:center;color:#ccc;padding:10px;width:100%;">暂无数据</div>';
} else {
data.forEach(item => {
// 接口字段: houseName, account
const name = item.houseName || '--';
const value = item.account || 0;
html += `
<div class="cattle_item">
<div class="cattle_icon">
<span class="glyphicon glyphicon-oil" aria-hidden="true"></span>
</div>
<div class="cattle_info">
<span class="cattle_name" title="${name}">${name}</span>
<div>
<span class="cattle_value">${value}</span>
<span class="cattle_unit">头</span>
</div>
</div>
</div>
`;
});
}
container.html(html);
}
})();
// 移除旧的模拟数据逻辑
/*
(function() {
// ... 旧代码 ...
})();
*/
// 牛只行情列表逻辑
(function() {
let scrollInterval;
@@ -319,82 +730,4 @@
});
})();
// 屠宰场概况图表逻辑
(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,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '20',
fontWeight: 'bold',
color: '#fff'
}
},
labelLine: {
show: false
},
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' } }
]
}
]
};
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);
});
})();