const SJZ_GOV = { lng: 116.21693, lat: 39.90446 }; // 石景山区演示落点(可后续替换更精确POI) function randn() { // 简单正态近似 let u = 0, v = 0; while (u === 0) u = Math.random(); while (v === 0) v = Math.random(); return Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v); } export function makePoints(n = 200) { // 做“带簇”的分布,更像真实路口 const clusters = [ { dx: 0.00, dy: 0.00, w: 0.45 }, { dx: 0.03, dy: 0.01, w: 0.25 }, { dx: -0.02, dy: 0.02, w: 0.18 }, { dx: 0.01, dy: -0.03, w: 0.12 }, ]; function pickCluster() { const r = Math.random(); let acc = 0; for (const c of clusters) { acc += c.w; if (r <= acc) return c; } return clusters[0]; } const pts = []; for (let i = 0; i < n; i++) { const c = pickCluster(); const lng = SJZ_GOV.lng + c.dx + randn() * 0.008; const lat = SJZ_GOV.lat + c.dy + randn() * 0.006; const statusRoll = Math.random(); const status = statusRoll < 0.78 ? "normal" : (statusRoll < 0.92 ? "busy" : "alarm"); pts.push({ id: `JUNC_${String(i + 1).padStart(3, "0")}`, name: `路口-${i + 1}`, lng: Number(lng.toFixed(6)), lat: Number(lat.toFixed(6)), status, updatedAt: Date.now() - Math.floor(Math.random() * 120000), }); } return pts; } // ====== 干路监控 mock 数据 ====== // 模拟 API 请求获取树形数据 export function menuData(tabId) { return new Promise(resolve => { // 模拟网络延迟 500ms setTimeout(() => { if (tabId === 'arterial') { resolve([ { id: 'm1', label: '主控中心', isOpen: true, children: [ { id: 'm1-1', label: '北京市交警总队', isOpen: true, children: [ { id: 'c1', label: '石景山区', isOpen: true, children: [ { id: 'l1', label: 'xxx 绿波带1' }, { id: 'l2', label: 'xxx 绿波带2' }, { id: 'l3', label: 'xxx 绿波带3' }, { id: 'l4', label: 'xxx 绿波带4' } ] }, { id: 'c2', label: '丰台区', isOpen: false, children: [{ id: 'l5', label: '丰台绿波带1' }] }, { id: 'c3', label: '门头沟区', isOpen: false, children: [{ id: 'l6', label: '门头沟绿波带1' }] }, { id: 'c4', label: '石景山区', isOpen: true, children: [ { id: 'l1', label: 'xxx 绿波带1' }, { id: 'l2', label: 'xxx 绿波带2' }, { id: 'l3', label: 'xxx 绿波带3' }, { id: 'l4', label: 'xxx 绿波带4' } ] }, { id: 'c5', label: '丰台区', isOpen: false, children: [{ id: 'l5', label: '丰台绿波带1' }] }, { id: 'c6', label: '门头沟区', isOpen: false, children: [{ id: 'l6', label: '门头沟绿波带1' }] }, { id: 'c7', label: '石景山区', isOpen: true, children: [ { id: 'l1', label: 'xxx 绿波带1' }, { id: 'l2', label: 'xxx 绿波带2' }, { id: 'l3', label: 'xxx 绿波带3' }, { id: 'l4', label: 'xxx 绿波带4' } ] }, { id: 'c8', label: '丰台区', isOpen: false, children: [{ id: 'l5', label: '丰台绿波带1' }] }, { id: 'c9', label: '门头沟区', isOpen: false, children: [{ id: 'l6', label: '门头沟绿波带1' }] } ] } ] } ]); } else { resolve([ { id: 'other1', label: `${tabId} 控制台`, isOpen: true, children: [ { id: 'o-c1', label: '测试节点 A' }, { id: 'o-c2', label: '测试节点 B' } ] } ]); } }, 500); }); } // ====== 交通时序图 mock 数据 ====== const trafficIntersections = [ '段祺瑞执政府', '剪子巷', '宽街', '北河沿', '锣鼓巷', '东板桥胡同', '地安门', '北海后门', '郭沫若故居' ]; const trafficDistances = [0, 300, 600, 900, 1200, 1500, 1800, 2100, 2400]; export function makeTrafficTimeSpaceData(opts = {}) { const { speed = 15, cycle = 120, band = 40, totalTime = 1800, maxDistance = 2400, dists = trafficDistances } = opts; const waveData = []; const greenData = []; for (let t = 0; t <= totalTime; t += cycle) { const downStart = t + cycle / 2; waveData.push({ yBottom: 0, yTop: maxDistance, xBL: t, xBR: t + band, xTL: t + maxDistance / speed, xTR: t + maxDistance / speed + band, label: Math.round(speed * 3.6) + 'km/h', direction: 'up' }); waveData.push({ yBottom: maxDistance, yTop: 0, xBL: downStart, xBR: downStart + band, xTL: downStart + maxDistance / speed, xTR: downStart + maxDistance / speed + band, label: Math.round(speed * 0.9 * 3.6) + 'km/h', direction: 'down' }); dists.forEach(y => { greenData.push({ y, start: t + y / speed, end: t + y / speed + band }); greenData.push({ y, start: downStart + (maxDistance - y) / speed, end: downStart + (maxDistance - y) / speed + band }); }); } return { intersections: trafficIntersections, distances: trafficDistances, waveData, greenData }; } /** * 模拟获取交通配时方案数据的 API 请求 */ export function fetchSignalTimingData(id) { console.log('id', id); return new Promise((resolve) => { // 模拟 500ms 的网络请求延迟 setTimeout(() => { resolve({ code: 200, message: 'success', data: { cycleLength: 140, currentTime: 67, // [轨道(1上,0下), 开始时间, 结束时间, 相位名称, 时长, 颜色类型, 图标类型] phaseData: [ // 单轨道 P1-P4 [0, 0, 27, 'P1', 27, 'green', 'UP'], [0, 27, 30, '', null, 'stripe', null], [0, 30, 32, '', null, 'yellow', null], [0, 32, 35, '', null, 'red', null], [0, 35, 62, 'P2', 27, 'green', 'TURN_LEFT'], [0, 62, 65, '', null, 'stripe', null], [0, 65, 67, '', null, 'yellow', null], [0, 67, 70, '', null, 'red', null], [0, 70, 97, 'P3', 27, 'green', 'DOWN'], [0, 97, 100, '', null, 'stripe', null], [0, 100, 102, '', null, 'yellow', null], [0, 102, 105, '', null, 'red', null], [0, 105, 132, 'P4', 27, 'green', 'TURN_RIGHT'], [0, 132, 135, '', null, 'stripe', null], [0, 135, 137, '', null, 'yellow', null], [0, 137, 140, '', null, 'red', null], ] } }); }, 500); }); } /** * 模拟获取路口信号相位与流量监控图数据的 API 请求 */ export function getIntersectionData(id) { console.log('id', id); return new Promise((resolve) => { // 模拟 500ms 的网络延迟 setTimeout(() => { resolve({ // 信号灯当前相位与倒计时状态 signals: { ns: { phaseName: '相位3', time: 38, isGreen: true }, // 南北向 ew: { phaseName: '相位7', time: 38, isGreen: false } // 东西向 }, // 交叉路口四个方向的静态配置 (N北, S南, E东, W西) armsConfig: { N: { cameraType: 1, // 1: 枪机, 2: 球机, 0: 无摄像头 // 车道指示标,从左到右(从中心黄线到路沿)排列。支持: 'U'调头, 'L'左转, 'S'直行, 'R'右转, null无 lanes: ['U', 'L', 'S', 'R'] }, S: { cameraType: 1, lanes: [null, 'L', 'S', 'R'] // 最内侧车道无指示标 }, E: { cameraType: 2, lanes: [null, 'L', 'S', null] }, W: { cameraType: 0, lanes: ['U', 'L', 'S', null] } } }); }, 500); }); } // ====== 首页 mock 数据 ====== export function makeHomeData() { // 这里做“看起来真”的波动 const onlineTotal = 1000; const online = 960 + Math.floor(Math.random() * 35); const offline = onlineTotal - online; const alarms = [ { id: "A001", title: "通讯中断", time: "16:28:28", loc: "中关村大街-科学南路路口", level: "high" }, { id: "A002", title: "降级黄闪", time: "16:28:28", loc: "中关村大街-科学南路路口", level: "mid" }, { id: "A003", title: "信号机离线", time: "16:18:02", loc: "阜石路-石景山路路口", level: "mid" }, { id: "A004", title: "检测器异常", time: "16:11:09", loc: "鲁谷路-政达路路口", level: "low" }, ]; const duty = Array.from({ length: 5 }).map((_, idx) => ({ id: `D${idx + 1}`, name: idx === 0 ? "测试" : ["张飞", "关将", "刘备", "孙权"][idx - 1], executor: idx === 0 ? "测试" : ["张飞", "关将", "刘备", "孙权"][idx - 1], level: idx === 2 ? "二级" : "一级", status: idx === 2 ? "进行中" : "未开始", })); return { header: { title: "交通信号控制平台", timeText: new Date().toLocaleTimeString(), dateText: new Date().toLocaleDateString(), weatherText: "晴 32/17℃", }, online: { online, offline, total: onlineTotal, rate: Math.round((online / onlineTotal) * 100) }, alarms, duty, device: { normal: 998, fault: 0 }, }; }