commit ffc0f7421c06ee6b83a7c662940572c31aa896e1 Author: 凛冬将至 Date: Fri Sep 11 09:47:30 2026 +0800 初始化网络货运智慧运营双屏大屏项目。 Co-authored-by: Cursor diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..503e811 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules +dist +.vite +*.log +.DS_Store +*.tsbuildinfo diff --git a/README.md b/README.md new file mode 100644 index 0000000..978cfef --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# 网络货运智慧运营中心 + +基于 Vue 3、TypeScript、Vite 与 ECharts 构建的 1920×1080 网络货运数据大屏。项目不依赖后台接口,使用关联模拟数据实时推进车辆、运单与风险状态。 + +## 启动 + +```bash +npm install +npm run dev +``` + +## 检查与构建 + +```bash +npm run typecheck +npm run build +``` + +## 设计说明 + +完整产品定位、指标口径、素材规范与验收标准见 [`docs/网络货运数据大屏规划.md`](docs/网络货运数据大屏规划.md)。 + +地图通过 `MapRenderer` 接收统一的 `MapScene` 数据,当前由 ECharts 中国地图渲染全国煤运飞线网络。 diff --git a/docs/素材来源.md b/docs/素材来源.md new file mode 100644 index 0000000..fd71902 --- /dev/null +++ b/docs/素材来源.md @@ -0,0 +1,23 @@ +# 数据大屏素材来源 + +以下图片均已下载到项目本地,仅用于网络货运场景展示。 + +- `src/assets/stock/coal-road-truck.jpg` + - 来源:[Wikimedia Commons - Coal Truck Tavan Tolgoi](https://commons.wikimedia.org/wiki/File:Coal_Truck_Tavan_Tolgoi.JPG) + - 作者:Brücke-Osteuropa(Dr. Bernd Gross) + - 场景:从塔旺陶勒盖煤矿驶往中国的满载公路煤车 + - 许可:Public Domain +- `src/assets/stock/coal-truck-loading.png` + - 来源:[Wikimedia Commons - Liebherr T282C Coal Haul Truck](https://commons.wikimedia.org/wiki/File:Liebherr_T282C_Coal_Haul_Truck.png) + - 作者:Peabody Energy, Inc. + - 场景:采煤装载设备向矿用运输车辆装煤 + - 许可:[CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) + +使用方式:本地静态资源、深色蒙版、裁切为场景背景;不使用第三方远程热链。 + +## 小图标 + +- 来源:[Font Awesome Free](https://fontawesome.com/) +- 安装包:`@fortawesome/vue-fontawesome`、`@fortawesome/free-solid-svg-icons` +- 许可:[Font Awesome Free License](https://fontawesome.com/license/free) +- 使用方式:由组件库直接渲染,替代项目内手绘 SVG 图标。 diff --git a/docs/网络货运数据大屏规划.md b/docs/网络货运数据大屏规划.md new file mode 100644 index 0000000..f21a694 --- /dev/null +++ b/docs/网络货运数据大屏规划.md @@ -0,0 +1,138 @@ +# 网络货运智慧运营中心规划 + +## 1. 产品定位 + +本项目是一套无需后台接口、可离线演示的网络货运数据大屏。画面围绕“货源、运力、运输、履约、风控、效益”展开,用一个 1920×1080 驾驶舱讲清从货源发布到车辆履约的完整业务链路。 + +目标观众为平台管理者、企业客户及展示来宾。首版采用阿里 DataV 类工业科技视觉,但不复制具体模板;核心记忆点是中央全国货运态势图、贯穿全屏的线路流光,以及风险发生时地图与告警面板同步响应。 + +## 2. 信息架构 + +### 顶部全局区 + +- 平台累计运单:累计业务规模 +- 今日运输吨位:当日承运货重 +- 今日运费金额:当日运单含税运费 +- 当前在途车辆:处于运输中的去重车辆 +- 活跃司机:当日有接单、装卸或运输行为的司机 +- 累计运输里程:已完成及在途运单里程 + +### 左侧供给区 + +1. 运单量趋势:最近 12 小时发布与完成运单 +2. 货物类型:钢材、煤炭、建材、农产品、快消、机械、化工 +3. 运力状态:空闲、待装、装货、运输、待卸、异常 +4. 车辆构成:高栏、厢式、平板、冷藏、罐式 +5. 货源城市排行:货源量前五城市 + +### 中央态势区 + +1. 伪 3D 中国地图与视觉地台 +2. 重点物流枢纽脉冲 +3. 城际货运飞线与流动光点 +4. 车辆沿线路移动 +5. 省份业务热度与货运光柱 +6. 当前焦点线路图文浮层 + +### 右侧运营区 + +1. 实时风险预警 +2. 准时装货、准时送达、回单上传履约仪表 +3. 区域经营排行 +4. 司机行为雷达 +5. 吨公里运价、空驶率、车辆利用率、等待时长 + +### 底部调度区 + +1. 实时运单流水 +2. 热门线路排行 +3. 智能调度匹配过程 +4. 节省空驶里程、碳减排、新能源车辆占比 + +## 3. 视觉规范 + +- 基准画布:1920×1080,整体等比缩放并居中 +- 背景:`#020913` 至 `#061b2d`,叠加道路网格、噪点和径向辉光 +- 主色:青蓝 `#19d9ff`,用于常规数据与线路 +- 辅色:深蓝 `#1668ff`、紫青 `#6af2e7` +- 强调:金色 `#ffc857`,用于金额、重点线路和排名 +- 风险:橙色 `#ff8a34`、红色 `#ff415d` +- 字体:标题使用窄体科技字族回退,正文使用中文黑体回退;数字使用等宽字族 +- 面板:透明深蓝底、切角、细描边、四角短线与顶部扫描光,不使用通用圆角白卡 +- 动画:首屏分层进入 800–1400ms;飞线 3–6s;扫描 6–10s;告警呼吸 1.8s +- 降级:系统开启减少动态效果时,停止粒子、扫描与循环位移动画 + +## 4. 数据模型与口径 + +### 运单 + +字段包括运单号、货物、重量、起点、终点、距离、单价、运费、车辆、司机、状态、计划及实际时间。 + +- 运费 = 重量 × 距离 × 吨公里单价 +- 状态为待调度、待装、运输中、待卸、已完成、异常 +- 总运单 = 各状态运单之和 + +### 车辆与司机 + +车辆字段包括车牌、车型、载重、状态、当前位置、线路进度和新能源标记。司机字段包括姓名、评分、接单数、准时率、安全分和活跃状态。 + +- 在途车辆数不大于活跃车辆数 +- 一个运输中运单绑定一辆车和一名司机 +- 车辆位置由线路起终点及进度插值得到 + +### 线路与区域 + +线路包含起终点、坐标、距离、运单量、运输吨位、平均运价、准时率和风险数。区域数据由线路和运单聚合,不单独随机生成。 + +### 风险 + +风险包括轨迹偏离、长时停留、疲劳驾驶、超速、人车不一致、围栏异常。每条风险绑定车辆、线路、等级、发生时间和处理状态。 + +### 效益 + +- 空驶率 = 空驶里程 ÷ 总行驶里程 +- 车辆利用率 = 执行任务车辆 ÷ 可用车辆 +- 回单上传率 = 已上传回单完成单 ÷ 已完成运单 +- 碳减排为减少空驶里程乘以统一排放因子,仅作为演示估算值 + +## 5. 模拟策略 + +采用固定随机种子生成基础数据,确保刷新后业务规模稳定;运行时每 2 秒推进车辆位置,每 4 秒新增或完成一笔运单,每 6–12 秒触发一次可控风险。所有图表共享同一数据源,禁止各组件自行产生互相冲突的随机数。 + +演示规模为 30 个物流节点、10 条重点线路、约 180 辆车辆、240 名司机和 600–1000 笔运单。晚间线路活跃度、货物占比、地区规模与价格保持符合行业展示语境的差异。 + +## 6. 素材规范 + +- 生成式素材:夜间智慧物流园区、重卡侧前方透明主体、调度中心氛围背景 +- 自制 SVG:车型剪影、货类图标、风险图标、科技边框、雷达和道路纹理 +- 地图:使用项目内中国 GeoJSON,边界仅用于数据展示 +- 图片统一转换为 WebP,压暗高光、叠加青蓝色调,不携带品牌、水印或文字 +- 外部素材必须记录来源及商用许可;无法确认授权时不用 + +## 7. 组件与数据流 + +页面容器只负责布局。模拟器提供只读状态和明确操作;各面板通过 props 接收数据,通过事件上报选中的区域、线路或车辆。地图渲染层接受统一的 `MapScene`,首版连接 ECharts,二期可替换为 Three.js 而不改变业务组件。 + +## 8. 性能目标 + +- 生产构建无 TypeScript 错误 +- 主流 Chromium 浏览器正常运行 +- 1920×1080 展示机上常态动画目标 50–60 FPS +- 首屏本地资源加载目标低于 3 秒 +- 1366×768 与 2560×1440 下完整等比显示,无裁切、无横向滚动 +- 定时器和图表实例在组件卸载时全部销毁 + +## 9. 验收清单 + +1. 页面包含不少于 16 个独立信息模块,且图表、图像和数据文字比例均衡 +2. 中央地图具备立体地台、枢纽、飞线、车辆点和焦点线路 +3. 告警列表、地图异常线路与顶部风险提示能够联动 +4. 模拟数据满足金额、运单状态、车辆及区域聚合关系 +5. 运单列表、车辆位置和时间持续更新且长时间运行稳定 +6. 背景、卡车主体及行业 SVG 素材风格统一,无版权风险 +7. 支持全屏比例适配和减少动态效果 +8. 完成类型检查、生产构建、浏览器截图及多分辨率验收 + +## 10. 二期真 3D + +首版不引入重型模型。二期在现有 `MapRenderer` 边界内增加 Three.js 渲染器,加载压缩后的 GLTF 卡车、地形挤出、光带道路和镜头巡航。业务数据、指标面板及交互协议保持不变。 diff --git a/index.html b/index.html new file mode 100644 index 0000000..7b6d2cd --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + 网络货运智慧运营中心 + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..51c6b0b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1640 @@ +{ + "name": "network-freight-datav", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "network-freight-datav", + "version": "1.0.0", + "dependencies": { + "@fortawesome/free-solid-svg-icons": "^7.3.1", + "@fortawesome/vue-fontawesome": "^3.3.3", + "@vueuse/core": "^13.9.0", + "china-map-data": "^1.0.4", + "echarts": "^6.0.0", + "vue": "^3.5.21" + }, + "devDependencies": { + "@types/node": "^22.20.2", + "@vitejs/plugin-vue": "^6.0.1", + "typescript": "~5.9.2", + "vite": "^7.1.5", + "vue-tsc": "^3.0.7" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "7.3.1", + "resolved": "https://registry.npmmirror.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.3.1.tgz", + "integrity": "sha512-k0C0sdHmZtAo6dRDtd1Z/qcpyHbL0CKsjV8seMY/21xGhY5Wsv0XRmiI/xEEH4y2c9b1+jvgNs/3EqhV27yUEA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "7.3.1", + "resolved": "https://registry.npmmirror.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.3.1.tgz", + "integrity": "sha512-BoxVN3PKnMbgStHhjoaky/oWdxHomDqmBVA24IA3KEmssFGeI7u9YT/BJceOjIum/t6TpPa/vcMKaVYQeIQ/3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "7.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "7.3.1", + "resolved": "https://registry.npmmirror.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-7.3.1.tgz", + "integrity": "sha512-v0BLa0eqg7ubvVWeNSHVBs8fWH/GJicERZoJaxJ3FE/lj67VSqzoMg9pzfZVOfLMX10y0pGwQAuxoRVVH2patg==", + "license": "(CC-BY-4.0 AND MIT)", + "dependencies": { + "@fortawesome/fontawesome-common-types": "7.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/vue-fontawesome": { + "version": "3.3.3", + "resolved": "https://registry.npmmirror.com/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.3.3.tgz", + "integrity": "sha512-Jbjze98gGcVBSdkscLbnDlHECumMAFVWDarMtycctn9qL3p92ApnV36VW4PwVrcm9IWrHnnE6ZL9x7MXStSCfA==", + "license": "MIT", + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6 || ~7", + "vue": ">= 3.0.0 < 4" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "license": "MIT" + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.1.tgz", + "integrity": "sha512-UZ8sUxPTiHWYX9QNdJedb1kDZSpS1t/VPWBWGSgqHNi9w3Cu6IXvu2mzbhiTiPvtrqgTQJ+zqiAq2iPIPilpaQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.63.1.tgz", + "integrity": "sha512-cQ4nFQABN5cDvDpbvJ7bMStCpnaVxynZrRMfUJYgxcIk9Sh54FIO1vtfkg0B69REjER77ioZ/ov+eAApx/KmLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.63.1.tgz", + "integrity": "sha512-FQNqd1lRy/0QhDk3xeRIkSBiCpXCiDnZO3YLVdcDKN1UBiKToNftCzcXYNLshmPDUMlu2TdeS8tGcsU6f3YF1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.63.1.tgz", + "integrity": "sha512-pvD16V939D3CloK0+qikpGaxiPrDUXTe7Y5cWOMkMSy7m1cawa8EGy/kXYi/G/cKAC4HDAbSnzCIk1WmsoOKXg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.63.1.tgz", + "integrity": "sha512-pcFGeL2345VwdTnJhA6zLbew+YgWB0qBG2+dMtXjCicf6+rm6kO6cOoh5VnTe0ZMrMRgRyuHmCJxZWrIdzYuOw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.63.1.tgz", + "integrity": "sha512-mRJlqSRulVzcKq/LKA6ICSIc3K/l4fzlVn/gePn2nXIHy8seRi5z/eeRE0d/XMBxcMldiXtQTSpRj0tkkC3g8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.63.1.tgz", + "integrity": "sha512-YDUNvVM85TI3g/1OpnqKP1h4NeW/j64DfWMf+G3M809xNk1bJSnpFp4sh83NpmVE5DXnkh8ULor4LTVZKoYLHw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.63.1.tgz", + "integrity": "sha512-7Mcn71p9ZuQFAj+h+dhQXy/yeLePRS2yKRnmW1DijA9thKO5qap0GNOIQK4yQ6iP3SU0Mrb/yWo8h8vgRba8lw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.63.1.tgz", + "integrity": "sha512-4YiLQTX6U4CSl0L9cluep9A9W6UmTfqBDc2/CH6wlu54pl4E7Jn3cOD8oxzvBDEGk/JMKgJ47C8g+radF7mwvg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.63.1.tgz", + "integrity": "sha512-2ra8F7w8OquwZN9z2/fKFnli69wa8PLwaVzRMIPGb13ByMJwC28Fbp8YcVGoUhlYMTt7j5j9bNgpysrN2UM+vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.63.1.tgz", + "integrity": "sha512-Sy20ncyhjmBP0Ml+UvQbimjlk6VFgjW5uNP+qqwHB00mTE8Bl2C1TuHTlRwK2YoXeZbee5lP2XevBWVkAQAtSQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.63.1.tgz", + "integrity": "sha512-noITLp8oNjYliPnGWmLyelIHwULGqbHloQHGw1rtxbWhTuWooRpnZarZQJ1y9EUC4szuCusCc+HEpUtxpIwYvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.63.1.tgz", + "integrity": "sha512-hlxxXd+F1mWiAcaFR7Sv9ZQT6m6UfI8+Vy/kFJzztq2pDMU/0wZ9sish0iszNZvsQDo8Gc0i5yuFEOz5dDf6fA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.63.1.tgz", + "integrity": "sha512-EF7OpqQTQ/BvGqLzUi4rEHuagCV9MugAUXSHemwPW5vxZ75RR+jxO/2j95Ph2dalMpFHSVECjRoioHZgA9zOYA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.63.1.tgz", + "integrity": "sha512-wQO3JesW9PRkwlabQ27y7sPfVOOTLRG73I4F2UYHG5PXun3J9U3y+b7ezVKSYbsvSKGQ1k1cq8Qlun4C9kLt3w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.63.1.tgz", + "integrity": "sha512-ouAGwhO6wHRXdnOVCOsB0tRFkA7nhNB2Nwax6oECXN0YiN8EYUTBAOudADOB1PI+yDL61TeNx/u7MVCzksNbkQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.63.1.tgz", + "integrity": "sha512-q2R38Sn+1J8RxhfJ+T54wSWmyKXWec+9jgDfqO2AtArEqHO5R2aeayp5H5OYLr5UYDVGsVaZPEFUooMhYCdz5A==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.63.1.tgz", + "integrity": "sha512-gfI5T24WLLuFfSKw7Go/zDXjAAV0fny0swTaDv+WjK7vqcw4cRhFfdsyKL1n+ukI+ooBxn3bVQnyrn06WpI50w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.63.1.tgz", + "integrity": "sha512-4h6XqthmB4Hspji84wvgk+ElodTsGj+dbZqHJHHtKxj4mYq0ANSEEPX9ys3moJueqsRjwpaJYH7874Itwnj2ow==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.63.1.tgz", + "integrity": "sha512-dlfCOa87o1VAYegLQ9EKilx2JCeRofiyPGhTCmqnuXZ6bMPiycO1rq1+sKoulAp7pGLIsTIw+1x5R+zgh5LhhA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.63.1.tgz", + "integrity": "sha512-cjkLbOlfcm3QGhMM1J5zaZjsw1GggbN6rw9UTSSRrPrR1KkcXnN7Uq9rPw34xImQ9VOY9GN+6u2Zj80B9ptkcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.63.1.tgz", + "integrity": "sha512-Li1KdUnWGE4N3e1F/B4RTB1ms+nG4WBgjByO46pkeBVX/2UBsY53xf5vK9WygVmnH3RwncIST7lkSdLSY6P9lg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.63.1.tgz", + "integrity": "sha512-t4ZYOSoLTgwhuFMrmTMLx/+i1DQVK7HYqMc6kY46EApwi8X0nIVphzdNoThU3xt6n+N5urG1/gxBdCaKDLavfg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.63.1.tgz", + "integrity": "sha512-RgroPfMmKlD1RzSDxvwgcPiy2HNQKoYV7OmwIXDsk73uKW5t6B/V8KIy27SMv/FNXFo/oSBtWc9J0X7t91ezZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.63.1.tgz", + "integrity": "sha512-at8QVep6S3h5Y6gSbdGU06bRY5WJkf6WUduM9YtvYMbYhB1MOFfUgc6kehitQXzOtMSaT70q7f9ydPhpqu821w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.20.2", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.20.2.tgz", + "integrity": "sha512-xlvWf4Vs9n1PEVYwP1n4vvG07M6y8WgvJ2t0vbrWTmijsIHp1cS+uJ2kMIRdY3nHZK0nCYKrPeD171+SzF4/zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.8", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-6.0.8.tgz", + "integrity": "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.42.tgz", + "integrity": "sha512-2Ye1ilMtKXxl8qZUrQ5j0CdgenFp/HFQmta6rfRyfEsTG69L6Wk+tWuNoHYHMx9E8tF2Slvdg1FuwDvAXdy1LQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.42", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.42.tgz", + "integrity": "sha512-qbhQZEFmycr+ni/qyuccS4sucNN7VAbDfbkvNxWOX2VfgFm90MNs3/UhRNKoPMEIVn0F8gdlYjLPvqxHwHeQOA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.42.tgz", + "integrity": "sha512-fkCAFB4okcAANGMThboWnScp/gzWjU0ZSkVnjTIiplmMDq2uq0tIB3j+xVu4rhv5rvOgBySCysudmbMd6xRRqw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.42", + "@vue/compiler-dom": "3.5.42", + "@vue/compiler-ssr": "3.5.42", + "@vue/shared": "3.5.42", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.19", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.42.tgz", + "integrity": "sha512-xmLk3wLkbizPAiLyomjgFFosf2ys9b5Ghb+oh/k2tnvipNz8OFrQOiTcWCzyK7MpBp9KkyGtfvgfLUivbmuGYA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/language-core": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-3.3.11.tgz", + "integrity": "sha512-QJmpliwAVpC/OxubIByPAhNzsQPRc8/gxlN2qnVzVfIMjMDz/9RnXRFoetjz5yEgXVXyp4LqhXq3V53PjmNzFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.2.1", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.4" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.42.tgz", + "integrity": "sha512-TzNNfKpb7hDxbQltwAut8VDQA5YP+BuRlxntHUuRjyKwlMvmAPbs3unhCvieijifY6vFfVBwsS7wG/C7uq+bEQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.42.tgz", + "integrity": "sha512-9uACtuHs7vJGkm5Bp3xu4xRDLFTIYy5DgxpToVjqGIAhAEKwQfsaLvKINhM6nFVp6bZPRFGdDqd1g52MqKsotA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.42.tgz", + "integrity": "sha512-rsCmhiWLaRxGltLwhlCWyYkFn7WAbKRh0q17eZ1A6Dq6eqc2ACQ61IIryxz0LrsvCzHSilLA9JHovVwM8CNE2g==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.42", + "@vue/runtime-core": "3.5.42", + "@vue/shared": "3.5.42", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.42.tgz", + "integrity": "sha512-2++5dUyYS4gvo7xQXSECUDhB7TS0aOl5SeVfC5qSq1Jgfhjvegw1zqhwTIR3imZ+QYPJQw9gfcFvXGAjGZ7ajQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.42", + "@vue/runtime-dom": "3.5.42", + "@vue/shared": "3.5.42" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.42.tgz", + "integrity": "sha512-2rPxex1jQf4jvl9MOHl6YaXCPcrNqz/FstMOEh3QWY+/OME9nQTvl9WYeCwhW7AFjaR0SnngZGlp/wkR6rkI6g==", + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "13.9.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-13.9.0.tgz", + "integrity": "sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "13.9.0", + "@vueuse/shared": "13.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "13.9.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-13.9.0.tgz", + "integrity": "sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "13.9.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-13.9.0.tgz", + "integrity": "sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/alien-signals": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-3.2.1.tgz", + "integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/china-map-data": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/china-map-data/-/china-map-data-1.0.4.tgz", + "integrity": "sha512-wy6BabF4zzZf/o4DAxaPW84FuvZnbZH+F7s8kiRchvUWd8Mi67BOITwoS8jFv7IfbF3PyzXrh0QvazNkgvfigg==", + "license": "ISC" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/echarts": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-6.1.0.tgz", + "integrity": "sha512-q0yaFPggC9FUdsWH4blavRWFmxdrIodbkoKNAjJudAI6CA9gNPxHtV2RcZNEepZVlk4yvBYkOkbk6HIVpIyHZA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "6.1.0" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.28", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.18", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.63.1", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.63.1.tgz", + "integrity": "sha512-3Df9jsstwhccuEfmAMi9l8XUh/GOkVObmFTU7CCVBysEbcOZLl84jCtaAZMcPiMz2EGKsATzQcU+Xr3n/wU6cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.63.1", + "@rollup/rollup-android-arm64": "4.63.1", + "@rollup/rollup-darwin-arm64": "4.63.1", + "@rollup/rollup-darwin-x64": "4.63.1", + "@rollup/rollup-freebsd-arm64": "4.63.1", + "@rollup/rollup-freebsd-x64": "4.63.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.63.1", + "@rollup/rollup-linux-arm-musleabihf": "4.63.1", + "@rollup/rollup-linux-arm64-gnu": "4.63.1", + "@rollup/rollup-linux-arm64-musl": "4.63.1", + "@rollup/rollup-linux-loong64-gnu": "4.63.1", + "@rollup/rollup-linux-loong64-musl": "4.63.1", + "@rollup/rollup-linux-ppc64-gnu": "4.63.1", + "@rollup/rollup-linux-ppc64-musl": "4.63.1", + "@rollup/rollup-linux-riscv64-gnu": "4.63.1", + "@rollup/rollup-linux-riscv64-musl": "4.63.1", + "@rollup/rollup-linux-s390x-gnu": "4.63.1", + "@rollup/rollup-linux-x64-gnu": "4.63.1", + "@rollup/rollup-linux-x64-musl": "4.63.1", + "@rollup/rollup-openbsd-x64": "4.63.1", + "@rollup/rollup-openharmony-arm64": "4.63.1", + "@rollup/rollup-win32-arm64-msvc": "4.63.1", + "@rollup/rollup-win32-ia32-msvc": "4.63.1", + "@rollup/rollup-win32-x64-gnu": "4.63.1", + "@rollup/rollup-win32-x64-msvc": "4.63.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.6", + "resolved": "https://registry.npmmirror.com/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.2.0.tgz", + "integrity": "sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.42", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.42.tgz", + "integrity": "sha512-4RyHQTbQvOPs3MfvUO1Sg0YRrKNnA0mAVtvpd12Tg1fKDN7OHBUl1IqSn8zGJjK9nI3NkNp8cgTpVrSZC5TTcA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.42", + "@vue/compiler-sfc": "3.5.42", + "@vue/runtime-dom": "3.5.42", + "@vue/server-renderer": "3.5.42", + "@vue/shared": "3.5.42" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-tsc": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-3.3.11.tgz", + "integrity": "sha512-gOb0B9rtU2+f1dszwPqSH5kAieIF9ReeLhD3kSRNHv5WZZUQz/JdVXW0RTdqhNTMlQkqKzrTTviqKr/4FYZraQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.3.11" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/zrender": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-6.1.0.tgz", + "integrity": "sha512-oEGMDB6pOP2S6OwRR4PdVv610zrjnA3Bh+JnSG12fYJlBKjtNAoEb5fSUoCOOINlH96I2fU38/A2UpRKs67xYQ==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..513f5ed --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "network-freight-datav", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite --host 0.0.0.0", + "build": "vue-tsc -b && vite build", + "typecheck": "vue-tsc -b --pretty false", + "preview": "vite preview --host 0.0.0.0" + }, + "dependencies": { + "@fortawesome/free-solid-svg-icons": "^7.3.1", + "@fortawesome/vue-fontawesome": "^3.3.3", + "@vueuse/core": "^13.9.0", + "china-map-data": "^1.0.4", + "echarts": "^6.0.0", + "vue": "^3.5.21" + }, + "devDependencies": { + "@types/node": "^22.20.2", + "@vitejs/plugin-vue": "^6.0.1", + "typescript": "~5.9.2", + "vite": "^7.1.5", + "vue-tsc": "^3.0.7" + } +} diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..dc11705 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/assets/stock/coal-road-truck.jpg b/src/assets/stock/coal-road-truck.jpg new file mode 100644 index 0000000..f57159c Binary files /dev/null and b/src/assets/stock/coal-road-truck.jpg differ diff --git a/src/assets/stock/coal-truck-loading.png b/src/assets/stock/coal-truck-loading.png new file mode 100644 index 0000000..8558e05 Binary files /dev/null and b/src/assets/stock/coal-truck-loading.png differ diff --git a/src/assets/visuals/logistics-night.svg b/src/assets/visuals/logistics-night.svg new file mode 100644 index 0000000..4ceb5b9 --- /dev/null +++ b/src/assets/visuals/logistics-night.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/base/FreightIcon.vue b/src/components/base/FreightIcon.vue new file mode 100644 index 0000000..b809533 --- /dev/null +++ b/src/components/base/FreightIcon.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/src/components/base/KpiCard.vue b/src/components/base/KpiCard.vue new file mode 100644 index 0000000..b689e5b --- /dev/null +++ b/src/components/base/KpiCard.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/src/components/base/TechPanel.vue b/src/components/base/TechPanel.vue new file mode 100644 index 0000000..56a330a --- /dev/null +++ b/src/components/base/TechPanel.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/components/map/ChinaFreightMap.vue b/src/components/map/ChinaFreightMap.vue new file mode 100644 index 0000000..9eb6053 --- /dev/null +++ b/src/components/map/ChinaFreightMap.vue @@ -0,0 +1,282 @@ + + + + + diff --git a/src/components/map/MapOperationsHud.vue b/src/components/map/MapOperationsHud.vue new file mode 100644 index 0000000..f9da993 --- /dev/null +++ b/src/components/map/MapOperationsHud.vue @@ -0,0 +1,137 @@ + + + + + diff --git a/src/components/map/MapRenderer.vue b/src/components/map/MapRenderer.vue new file mode 100644 index 0000000..680eafd --- /dev/null +++ b/src/components/map/MapRenderer.vue @@ -0,0 +1,11 @@ + + + diff --git a/src/components/map/RouteExecutionMap.vue b/src/components/map/RouteExecutionMap.vue new file mode 100644 index 0000000..d75d0d9 --- /dev/null +++ b/src/components/map/RouteExecutionMap.vue @@ -0,0 +1,238 @@ + + + + + diff --git a/src/composables/useFreightSimulation.ts b/src/composables/useFreightSimulation.ts new file mode 100644 index 0000000..f2985f2 --- /dev/null +++ b/src/composables/useFreightSimulation.ts @@ -0,0 +1,146 @@ +import { computed, onMounted, onUnmounted, readonly, reactive, shallowRef } from 'vue' +import { drivers, initialAlerts, initialOrders, routes, vehicles } from '@/mock/freightData' +import type { FreightOrder, KpiMetric, PlatformSnapshot, RiskAlert } from '@/types/freight' + +const cargoSequence = ['动力煤', '焦煤', '洗精煤', '无烟煤', '焦炭', '矿粉'] +const alertTypes = ['轨迹偏离', '长时间停留', '疲劳驾驶', '电子围栏异常', '疑似超速'] + +function formatClock(date: Date) { + return date.toLocaleTimeString('zh-CN', { hour12: false }) +} + +export function useFreightSimulation() { + const orderList = reactive(initialOrders.map((order) => ({ ...order }))) + const vehicleList = reactive(vehicles.map((vehicle) => ({ ...vehicle }))) + const alertList = reactive(initialAlerts.map((alert) => ({ ...alert }))) + const selectedRouteId = shallowRef(routes[0].id) + const clock = shallowRef(new Date()) + const tick = shallowRef(0) + const timers: number[] = [] + + const routeTotals = computed(() => routes.reduce((result, route) => { + result.orders += route.orders + result.tonnage += route.tonnage + result.tonKilometres += route.tonnage * route.distance + result.freight += route.tonnage * route.distance * route.rate + return result + }, { orders: 0, tonnage: 0, tonKilometres: 0, freight: 0 })) + + const snapshot = computed(() => ({ + todayOrders: routeTotals.value.orders + Math.floor(tick.value / 2), + completedOrders: 6_917 + Math.floor(Math.floor(tick.value / 2) * 0.68), + inTransitOrders: routeTotals.value.orders + Math.floor(tick.value / 2) + - (6_917 + Math.floor(Math.floor(tick.value / 2) * 0.68)) + - (426 + Math.floor(tick.value / 6) % 3), + pendingPickupOrders: 426 + Math.floor(tick.value / 6) % 3, + activeVehicles: 6_380, + inTransitVehicles: 1_089 + tick.value % 7, + todayTonnage: Math.round(routeTotals.value.tonnage + Math.floor(tick.value / 2) * 32.8), + freightAmount: Math.round(routeTotals.value.freight + Math.floor(tick.value / 2) * 32.8 * 612 * 0.31), + averageWeight: Number(((routeTotals.value.tonnage + Math.floor(tick.value / 2) * 32.8) / (routeTotals.value.orders + Math.floor(tick.value / 2))).toFixed(2)), + averageDistance: Math.round(routeTotals.value.tonKilometres / routeTotals.value.tonnage), + averageRate: Number((routeTotals.value.freight / routeTotals.value.tonKilometres).toFixed(3)), + responseSeconds: 164 + tick.value % 5, + onTimeRate: 94.7, + trackIntegrityRate: 98.3, + receiptRate: 92.6, + settlementRate: 88.4, + invoiceRate: 84.9, + abnormalRate: 0.74, + })) + + const kpis = computed(() => [ + { label: '今日有效运单', value: snapshot.value.todayOrders, unit: '单', change: 6.8 }, + { label: '今日运输吨位', value: snapshot.value.todayTonnage / 10_000, unit: '万吨', change: 4.2, digits: 2 }, + { label: '今日运费金额', value: snapshot.value.freightAmount / 10_000, unit: '万元', change: 5.6, accent: 'gold', digits: 0 }, + { label: '当前在途车辆', value: snapshot.value.inTransitVehicles, unit: '辆', change: 3.1 }, + { + label: '平均报价响应', + value: snapshot.value.responseSeconds, + displayValue: `${Math.floor(snapshot.value.responseSeconds / 60)}分${snapshot.value.responseSeconds % 60}秒`, + unit: '', + change: -8.4, + }, + ]) + + const recentOrders = computed(() => orderList.slice(0, 8)) + const clockText = computed(() => formatClock(clock.value)) + const dateText = computed(() => clock.value.toLocaleDateString('zh-CN', { + year: 'numeric', month: '2-digit', day: '2-digit', weekday: 'short', + })) + + function advanceVehicles() { + vehicleList.forEach((vehicle) => { + if (vehicle.status !== '运输中') return + vehicle.progress = (vehicle.progress + 0.008 + (Number(vehicle.id.slice(1)) % 5) * 0.001) % 1 + }) + tick.value += 1 + } + + function addOrder() { + const index = orderList.length + tick.value + const route = routes[index % routes.length] + const vehicle = vehicleList[index % vehicleList.length] + const weight = 20 + index % 14 + const unitRate = route.rate + (index % 4) * 0.01 + orderList.unshift({ + id: `YD${clock.value.getFullYear()}${String(900000 + index)}`, + cargo: cargoSequence[index % cargoSequence.length], + weight, + routeId: route.id, + distance: route.distance, + unitRate, + fee: Math.round(weight * route.distance * unitRate), + vehicleId: vehicle.id, + driverId: drivers[index % drivers.length].id, + status: index % 5 === 0 ? '待装货' : '运输中', + createdAt: new Date().toISOString(), + eta: new Date(Date.now() + (8 + index % 18) * 3_600_000).toISOString(), + }) + if (orderList.length > 820) orderList.pop() + } + + function rotateAlert() { + const index = tick.value % vehicleList.length + const route = routes[index % routes.length] + alertList.unshift({ + id: `A${Date.now()}`, + type: alertTypes[index % alertTypes.length], + level: index % 5 === 0 ? '高' : index % 2 === 0 ? '中' : '低', + vehicleId: vehicleList[index].id, + routeId: route.id, + city: `${route.from.name}段`, + time: new Date().toISOString(), + resolved: false, + }) + if (alertList.length > 9) alertList.pop() + selectedRouteId.value = route.id + } + + function selectRoute(routeId: string) { + selectedRouteId.value = routeId + } + + onMounted(() => { + timers.push(window.setInterval(() => { clock.value = new Date() }, 1_000)) + timers.push(window.setInterval(advanceVehicles, 2_000)) + timers.push(window.setInterval(addOrder, 4_000)) + timers.push(window.setInterval(rotateAlert, 9_000)) + }) + + onUnmounted(() => timers.forEach(window.clearInterval)) + + return { + orders: readonly(orderList), + vehicles: readonly(vehicleList), + alerts: readonly(alertList), + routes, + kpis, + snapshot, + recentOrders, + selectedRouteId: readonly(selectedRouteId), + clockText, + dateText, + selectRoute, + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..97128ba --- /dev/null +++ b/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import App from './App.vue' +import './styles/main.css' + +createApp(App).mount('#app') diff --git a/src/mock/freightData.ts b/src/mock/freightData.ts new file mode 100644 index 0000000..8f45d4f --- /dev/null +++ b/src/mock/freightData.ts @@ -0,0 +1,132 @@ +import type { CityNode, Driver, FreightOrder, FreightRoute, RiskAlert, Vehicle } from '@/types/freight' + +export const cities: CityNode[] = [ + { id: 'urumqi', name: '乌鲁木齐', province: '新疆', x: 13, y: 29, volume: 68 }, + { id: 'lanzhou', name: '兰州', province: '甘肃', x: 35, y: 44, volume: 82 }, + { id: 'chengdu', name: '成都', province: '四川', x: 39, y: 61, volume: 108 }, + { id: 'xian', name: '西安', province: '陕西', x: 48, y: 49, volume: 126 }, + { id: 'chongqing', name: '重庆', province: '重庆', x: 47, y: 63, volume: 118 }, + { id: 'kunming', name: '昆明', province: '云南', x: 39, y: 78, volume: 72 }, + { id: 'beijing', name: '北京', province: '北京', x: 67, y: 27, volume: 156 }, + { id: 'tianjin', name: '天津', province: '天津', x: 71, y: 32, volume: 133 }, + { id: 'jinan', name: '济南', province: '山东', x: 69, y: 42, volume: 171 }, + { id: 'qingdao', name: '青岛', province: '山东', x: 78, y: 43, volume: 144 }, + { id: 'zhengzhou', name: '郑州', province: '河南', x: 59, y: 49, volume: 203 }, + { id: 'linyi', name: '临沂', province: '山东', x: 73, y: 48, volume: 231 }, + { id: 'wuhan', name: '武汉', province: '湖北', x: 59, y: 61, volume: 167 }, + { id: 'nanjing', name: '南京', province: '江苏', x: 74, y: 57, volume: 182 }, + { id: 'shanghai', name: '上海', province: '上海', x: 83, y: 58, volume: 228 }, + { id: 'hangzhou', name: '杭州', province: '浙江', x: 79, y: 64, volume: 194 }, + { id: 'changsha', name: '长沙', province: '湖南', x: 57, y: 70, volume: 121 }, + { id: 'nanchang', name: '南昌', province: '江西', x: 66, y: 69, volume: 97 }, + { id: 'xiamen', name: '厦门', province: '福建', x: 72, y: 80, volume: 91 }, + { id: 'guangzhou', name: '广州', province: '广东', x: 58, y: 86, volume: 212 }, + { id: 'shenzhen', name: '深圳', province: '广东', x: 62, y: 89, volume: 186 }, + { id: 'nanning', name: '南宁', province: '广西', x: 47, y: 87, volume: 76 }, + { id: 'haerbin', name: '哈尔滨', province: '黑龙江', x: 84, y: 11, volume: 89 }, + { id: 'shenyang', name: '沈阳', province: '辽宁', x: 78, y: 23, volume: 111 }, + { id: 'ordos', name: '鄂尔多斯', province: '内蒙古', x: 48, y: 35, volume: 238 }, + { id: 'yulin', name: '榆林', province: '陕西', x: 49, y: 40, volume: 226 }, + { id: 'datong', name: '大同', province: '山西', x: 59, y: 32, volume: 194 }, + { id: 'shenmu', name: '神木', province: '陕西', x: 51, y: 38, volume: 208 }, + { id: 'wuhai', name: '乌海', province: '内蒙古', x: 40, y: 34, volume: 116 }, + { id: 'baotou', name: '包头', province: '内蒙古', x: 50, y: 31, volume: 139 }, + { id: 'jincheng', name: '晋城', province: '山西', x: 60, y: 48, volume: 128 }, + { id: 'yangquan', name: '阳泉', province: '山西', x: 63, y: 40, volume: 104 }, + { id: 'shijiazhuang', name: '石家庄', province: '河北', x: 66, y: 39, volume: 146 }, + { id: 'tangshan', name: '唐山', province: '河北', x: 73, y: 31, volume: 213 }, + { id: 'handan', name: '邯郸', province: '河北', x: 65, y: 46, volume: 167 }, + { id: 'guiyang', name: '贵阳', province: '贵州', x: 47, y: 72, volume: 142 }, + { id: 'liupanshui', name: '六盘水', province: '贵州', x: 42, y: 72, volume: 196 }, + { id: 'bijie', name: '毕节', province: '贵州', x: 44, y: 68, volume: 181 }, + { id: 'qujing', name: '曲靖', province: '云南', x: 40, y: 76, volume: 173 }, + { id: 'zhaotong', name: '昭通', province: '云南', x: 40, y: 67, volume: 158 }, + { id: 'dazhou', name: '达州', province: '四川', x: 47, y: 58, volume: 164 }, +] + +const routePairs = [ + ['ordos', 'tangshan'], ['yulin', 'handan'], ['datong', 'tianjin'], + ['shenmu', 'jinan'], ['jincheng', 'wuhan'], ['liupanshui', 'guiyang'], + ['bijie', 'chongqing'], ['qujing', 'kunming'], ['zhaotong', 'chengdu'], ['dazhou', 'chongqing'], +] + +export const routes: FreightRoute[] = routePairs.map(([fromId, toId], index) => { + const from = cities.find((city) => city.id === fromId)! + const to = cities.find((city) => city.id === toId)! + const distance = [830, 620, 470, 710, 760, 240, 470, 150, 520, 230][index] + const orders = [1286, 1139, 986, 874, 821, 776, 703, 668, 624, 589][index] + const rates = [0.28, 0.30, 0.31, 0.29, 0.30, 0.42, 0.34, 0.46, 0.33, 0.40] + return { + id: `R${String(index + 1).padStart(2, '0')}`, + from, to, distance, orders, + tonnage: Math.round(orders * (32.2 + index * 0.18)), + rate: rates[index], + punctuality: Number((96.8 - index * 0.31).toFixed(1)), + riskCount: index % 4, + } +}) + +const plates = ['蒙K', '陕K', '晋B', '冀B', '晋E', '贵B', '贵F', '云D', '云C', '川S'] +const vehicleTypes: Vehicle['type'][] = ['自卸车', '自卸车', '半挂牵引车', '自卸车', '罐式车'] +const statuses: Vehicle['status'][] = ['运输中', '运输中', '运输中', '待装', '空闲', '待卸', '装货', '异常'] + +export const vehicles: Vehicle[] = Array.from({ length: 180 }, (_, index) => ({ + id: `V${String(index + 1).padStart(3, '0')}`, + plate: `${plates[index % plates.length]}${String(63010 + index).slice(-5)}`, + type: vehicleTypes[index % vehicleTypes.length], + load: [32, 35, 33, 32, 34][index % 5], + status: statuses[index % statuses.length], + routeId: routes[index % routes.length].id, + progress: ((index * 13) % 100) / 100, + newEnergy: index % 7 === 0, +})) + +export const drivers: Driver[] = Array.from({ length: 240 }, (_, index) => ({ + id: `D${String(index + 1).padStart(3, '0')}`, + name: `${['张', '王', '李', '赵', '刘', '陈', '杨', '周'][index % 8]}${['师傅', '建国', '海峰', '志强', '文斌'][index % 5]}`, + score: Number((4.72 + (index % 26) / 100).toFixed(2)), + punctuality: 92 + (index % 8), + safety: 90 + (index % 10), + active: index < 204, +})) + +const cargos = ['动力煤', '焦煤', '动力煤', '洗精煤', '无烟煤', '焦炭', '矿粉', '热轧钢卷'] +const orderStatuses: FreightOrder['status'][] = ['运输中', '待装货', '已完成', '已完成', '待卸货', '待调度'] +const now = new Date() + +export const initialOrders: FreightOrder[] = Array.from({ length: 720 }, (_, index) => { + const route = routes[index % routes.length] + const weight = 30 + (index % 7) + const unitRate = Number((route.rate + (index % 5) * 0.01).toFixed(2)) + return { + id: `YD${now.getFullYear()}${String(860000 + index)}`, + cargo: cargos[index % cargos.length], + weight, + routeId: route.id, + distance: route.distance, + unitRate, + fee: Math.round(weight * route.distance * unitRate), + vehicleId: vehicles[index % vehicles.length].id, + driverId: drivers[index % drivers.length].id, + status: orderStatuses[index % orderStatuses.length], + createdAt: new Date(now.getTime() - index * 167_000).toISOString(), + eta: new Date(now.getTime() + (index % 20 + 2) * 3_600_000).toISOString(), + } +}) + +export const initialAlerts: RiskAlert[] = [ + ['A01', '轨迹偏离', '高', 7, 0, '京唐港段'], + ['A02', '疲劳驾驶', '高', 23, 3, '济阳段'], + ['A03', '长时间停留', '中', 41, 6, '遵义服务区'], + ['A04', '电子围栏异常', '中', 62, 7, '曲靖煤场'], + ['A05', '疑似超速', '低', 89, 8, '昭通段'], +].map(([id, type, level, vehicleIndex, routeIndex, city], index) => ({ + id: String(id), + type: String(type), + level: level as RiskAlert['level'], + vehicleId: vehicles[Number(vehicleIndex)].id, + routeId: routes[Number(routeIndex)].id, + city: String(city), + time: new Date(now.getTime() - index * 190_000).toISOString(), + resolved: false, +})) diff --git a/src/styles/main.css b/src/styles/main.css new file mode 100644 index 0000000..eefde8f --- /dev/null +++ b/src/styles/main.css @@ -0,0 +1,35 @@ +@import url('https://fonts.googleapis.com/css2?family=Rajdhani:wght@500;600;700&family=Noto+Sans+SC:wght@400;500;600&display=swap'); + +:root { + font-family: 'Noto Sans SC', 'Microsoft YaHei', sans-serif; + color: #d9f7ff; + background: #020913; + font-synthesis: none; + --cyan: #19d9ff; + --cyan-soft: #6af2e7; + --blue: #1668ff; + --gold: #ffc857; + --red: #ff415d; + --orange: #ff8a34; + --panel: rgba(4, 25, 43, 0.78); + --line: rgba(49, 199, 255, 0.32); + --muted: #78a5b5; +} + +* { box-sizing: border-box; } +html, body, #app { width: 100%; height: 100%; margin: 0; overflow: hidden; } +body { + background: + radial-gradient(circle at 50% 45%, rgba(0, 104, 164, .2), transparent 42%), + linear-gradient(150deg, #01060d 0%, #041421 55%, #020913 100%); +} +button, input { font: inherit; } + +@keyframes scan { from { transform: translateX(-120%); } to { transform: translateX(240%); } } +@keyframes breathe { 50% { opacity: .42; filter: brightness(1.7); } } +@keyframes float { 50% { transform: translateY(-6px); } } +@keyframes dash { to { stroke-dashoffset: -32; } } + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; } +} diff --git a/src/types/china-map-data.d.ts b/src/types/china-map-data.d.ts new file mode 100644 index 0000000..ba82578 --- /dev/null +++ b/src/types/china-map-data.d.ts @@ -0,0 +1,4 @@ +declare module 'china-map-data/china' { + const chinaGeoJson: unknown + export default chinaGeoJson +} diff --git a/src/types/freight.ts b/src/types/freight.ts new file mode 100644 index 0000000..4c3f8e6 --- /dev/null +++ b/src/types/freight.ts @@ -0,0 +1,117 @@ +export type OrderStatus = '待调度' | '待装货' | '运输中' | '待卸货' | '已完成' | '异常' +export type RiskLevel = '高' | '中' | '低' + +export interface CityNode { + id: string + name: string + province: string + x: number + y: number + volume: number +} + +export interface FreightRoute { + id: string + from: CityNode + to: CityNode + distance: number + orders: number + tonnage: number + rate: number + punctuality: number + riskCount: number +} + +export interface Vehicle { + id: string + plate: string + type: '高栏车' | '厢式车' | '平板车' | '冷藏车' | '罐式车' | '自卸车' | '半挂牵引车' + load: number + status: '空闲' | '待装' | '装货' | '运输中' | '待卸' | '异常' + routeId?: string + progress: number + newEnergy: boolean +} + +export interface Driver { + id: string + name: string + score: number + punctuality: number + safety: number + active: boolean +} + +export interface FreightOrder { + id: string + cargo: string + weight: number + routeId: string + distance: number + unitRate: number + fee: number + vehicleId: string + driverId: string + status: OrderStatus + createdAt: string + eta: string +} + +export interface RiskAlert { + id: string + type: string + level: RiskLevel + vehicleId: string + routeId: string + city: string + time: string + resolved: boolean +} + +export interface MapScene { + nodes: CityNode[] + routes: FreightRoute[] + vehicles: Vehicle[] + alerts: RiskAlert[] + snapshot: PlatformSnapshot + selectedRouteId: string +} + +export interface MapRendererProps { + scene: MapScene +} + +export interface MapRendererEvents { + selectRoute: [routeId: string] +} + +export interface KpiMetric { + label: string + value: number + displayValue?: string + unit: string + change: number + accent?: 'cyan' | 'gold' + digits?: number +} + +export interface PlatformSnapshot { + todayOrders: number + completedOrders: number + inTransitOrders: number + pendingPickupOrders: number + activeVehicles: number + inTransitVehicles: number + todayTonnage: number + freightAmount: number + averageWeight: number + averageDistance: number + averageRate: number + responseSeconds: number + onTimeRate: number + trackIntegrityRate: number + receiptRate: number + settlementRate: number + invoiceRate: number + abnormalRate: number +} diff --git a/src/views/ExecutionScreenV2.vue b/src/views/ExecutionScreenV2.vue new file mode 100644 index 0000000..5376ea3 --- /dev/null +++ b/src/views/ExecutionScreenV2.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/src/views/FreightDashboardV2.vue b/src/views/FreightDashboardV2.vue new file mode 100644 index 0000000..b5ac32e --- /dev/null +++ b/src/views/FreightDashboardV2.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/src/views/OverviewScreenV2.vue b/src/views/OverviewScreenV2.vue new file mode 100644 index 0000000..bd2193c --- /dev/null +++ b/src/views/OverviewScreenV2.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..7e31cd2 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "jsx": "preserve", + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "noEmit": true, + "baseUrl": ".", + "paths": { "@/*": ["src/*"] }, + "types": ["vite/client"] + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..42083b3 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "moduleResolution": "Bundler", + "skipLibCheck": true, + "noEmit": true, + "strict": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..8be8b42 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,10 @@ +import { fileURLToPath, URL } from 'node:url' +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) }, + }, +})