| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- 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 },
- };
- }
|