每年毕业设计季节总能看到大量学生在同一类选题上挣扎——有的选了太复杂的课题后期做不完有的选了太简单的又过不了答辩。公交线路查询系统管理平台属于那种看起来普通、但实际上非常讨巧的选题业务场景人人熟悉、功能边界清晰、技术栈覆盖全面最重要的是它能把 SpringBoot、Vue、MySQL 这三门核心课程的知识全部串起来。这篇文章把这套系统的从需求分析到部署上线的完整链路拆开来讲包括数据库建模、接口设计、前端地图联调、答辩常见问题适合正在做毕设、课设或者想拿一个完整项目练手的同学。1. 公交线路查询系统的选题逻辑一个稳准狠的毕设样本1.1 业务模型天然契合课程知识体系公交线路查询系统最大的优势在于它的实体关系非常典型。线路Line、站点Station、车辆Vehicle、用户User这四个实体之间天然存在多对多、一对多的关系。比如一条线路要经过多个站点一个站点会被多条线路经过这是教科书中标准的中间表场景。而一辆公交车属于某条线路每天跑固定班次这又是一对多关系。这类业务模型的好处在于它不会像进销存系统那样让评审老师一看就觉得老套又不会像人脸识别系统那样把复杂度堆在算法上而忽略了工程能力。公交系统的核心是数据的组织和查询效率这正好落在 Web 开发的知识范围内。SpringBoot 负责接口层Vue 负责展示层MySQL 负责数据层三者职责分明任何一环都能展开讲出东西来。1.2 从答辩评分角度看这个选题的得分点我接触过不少评审老师也看过很多学生的答辩现场。对于这类管理系统评审通常关注四个维度功能完整性、技术深度、代码规范性、演示流畅度。公交线路查询系统在这四个维度上都很容易做出亮点。功能完整性方面除了基本的线路查询和站点查询还能加入最短换乘方案、收藏线路、后台数据管理等模块。技术深度方面换乘方案查询用到的 BFS 图搜索算法是很好的答辩加分点它比单纯的 CRUD 高出一个档次。代码规范性则是通过统一返回体、全局异常处理、自定义注解这些细节体现。而演示流畅度因为系统是 B/S 架构浏览器打开就能操作不会有软件安装或环境配置问题。这个选题适合的人群很明确学过 Java 和数据库、但还没独立做过完整项目的人。它能让你在一两个月内掌握前后端交互的完整流程而且每一步的参考资料都非常丰富。2. 技术选型与版本匹配环境问题中的隐形坑2.1 SpringBoot Vue 组合的主流版本搭配很多学生一上来就装最新版结果踩了一堆版本兼容问题的坑。我的经验是做毕设项目稳定性和资料丰富度比版本新旧更重要。后端建议使用 SpringBoot 2.7.x前端使用 Vue 2 Element UI或者 Vue 3 Element Plus具体取决于你的熟练程度。这里有一个很现实的问题SpringBoot 3.x 要求 JDK 17 以上而很多学校的实验课和教材还在用 JDK 8。如果你电脑上装的是 JDK 8硬要用 SpringBoot 3.x 会发现启动直接报 UnsupportedClassVersionError。反过来如果你的电脑是 JDK 17用 SpringBoot 2.7 也没问题2.7 版本同时兼容 JDK 8 和 JDK 11/17。所以我的建议是如果拿不准就选 SpringBoot 2.7 JDK 8/11 的组合这是当前网络上资料最丰富、踩坑解法最全的搭配。前端这块Vue 2 虽然官方进入了维护末期但 Element UI 的组件文档、各类后台管理模板比如 vue-element-admin基本都是基于 Vue 2 的照抄起来效率极高。如果你本身对 Vue 3 的 Composition API 更熟那就用 Vue 3 Element Plus核心功能实现差异并不大。2.2 MySQL 版本与驱动连接的几个关键细节MySQL 推荐用 8.0 版本不要用 5.7。原因不只是性能而是 8.0 官方驱动名和连接配置跟 5.7 有差异现在网上的教程绝大多数默认是 8.0 的写法。如果用了 5.7你得手动注意驱动类名是com.mysql.jdbc.Driver而 8.0 是com.mysql.cj.jdbc.Driver。驱动类名写错是最常见的启动报错。数据库连接串里有两个参数建议必须加上spring: datasource: url: jdbc:mysql://localhost:3306/bus_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue username: root password: 你自己的密码 driver-class-name: com.mysql.cj.jdbc.DriverserverTimezoneAsia/Shanghai是解决时区报错的不加的话 MySQL 8.0 会提示 CST 时区无法识别或相差 8 小时。useSSLfalse是解决 SSL 连接告警的尤其在公司内网或者本地连接时没必要走 SSL 加密。allowPublicKeyRetrievaltrue是配合 MySQL 8.0 默认的 caching_sha2_password 认证插件的很多学生本地连不上数据库都是因为它——报错信息类似 Public Key Retrieval is not allowed没有这个参数就会卡在这一步。2.3 持久层框架选择MyBatis Plus 为什么更适合课设持久层用 MyBatis 还是 MyBatis Plus我强烈建议后者。MyBatis Plus 本质上是 MyBatis 的增强工具单表 CRUD 完全不用写 SQL靠BaseMapper接口自带的方法就能完成。这对课设项目来说省下了大量时间同时你想写复杂 SQL 的时候它也不拦着你比如多表关联查询照样用Select注解或 XML 文件自定义。用 MyBatis Plus 有个额外好处是内置逻辑删除功能。公交线路管理平台里的线路、站点删除操作不建议物理删除也就是真正的 DELETE因为历史运营数据有统计价值。MyBatis Plus 里配置TableLogic注解配合全局配置文件就能实现删除时自动转成 UPDATE 修改 deleted 标记字段这正好是答辩时能讲的一个技术亮点。3. 数据库建模的核心方案线路、站点与中间关系表3.1 表结构设计原则与字段明细公交线路查询系统的数据模型其实不复杂但表之间的关系要理清楚。我给出的参考表结构一共五张基础表加一张中间表。用户表sys_user主键 id、用户名、密码BCrypt 加密存储、真实姓名、角色admin/user/admin 区分管理端和普通查询端、手机号、创建时间。管理端和查询端共用一张用户表用 role 字段区分权限即可。线路表line主键 id、线路名称如1路、K209路、起点站名、终点站名、发车时间、收车时间、票价、线路类型普通/空调/快速、状态0停运/1运营。注意起点终点这里直接存冗余的站点名字段是为了列表展示方便不用每次都去关联站点表查一遍。真正的站点关联关系由中间表维护。站点表station主键 id、站点名称、经度、纬度、所属区域。经纬度的精度用 DECIMAL(10,6) 存储这个精度在地图上定位已经够用。如果做换乘方案的可视化经纬度是必须的。不做地图展示的话至少也要保留站点名称、所属区域和附近地标方便后面扩展。中间表line_station_rel主键 id、线路 id、站点 id、站点序号从 1 开始表示这是第几站、单向/双向标记。这个表是整个系统设计的关键。很多人不知道站点序号字段有什么用它决定了换乘算法中方向判断的准确性。比如从 A 站到 B 站如果 B 在 A 前面即 B 的站点序号小于 A 的序号这条线路就是反向乘坐方案提示里要明确给出开往某某方向的引导语。3.2 多对多关系的中间表设计细节拿1路公交车经过哪些站点来举例。1路有 id1站点表里有 id50 的人民广场站。那么中间表插入一行rel_id1, line_id1, station_id50, station_order5。当需要查询 1 路所有站点时SQL 就是SELECT s.name, s.longitude, s.latitude, r.station_order FROM line_station_rel r LEFT JOIN station s ON r.station_id s.id WHERE r.line_id 1 AND s.deleted 0 ORDER BY r.station_order ASC这里 LEFT JOIN 而不是 INNER JOIN 的目的是确保即使某条数据关联的站点被逻辑删除了线路信息本身还能正常返回避免整条线路因为一个站点的逻辑删除而不显示任何数据。实际测试中这个细节很关键因为站点迁移时往往会把旧站点逻辑删除如果用了 INNER JOIN线路站点列表会直接少一项看起来像 bug。反过来查人民广场站有哪些线路经过就更简单了SELECT l.name, r.station_order FROM line_station_rel r LEFT JOIN line l ON r.line_id l.id WHERE r.station_id 50 AND l.status 1 AND l.deleted 0 ORDER BY l.name3.3 字段默认值与索引设计中的实用经验建表时要养成设 DEFAULT 值的习惯。比如逻辑删除标记deleted设置默认值 0线路状态status设置默认值 1这样插入数据时不需要显式传这些字段。这个操作虽然简单但在 MyBatis Plus 的insert()方法里能避免奇怪的 null 值问题。热搜词里有人搜mysql 设置默认值为 0我猜就是遇到了插入后字段为 NULL 导致查询异常的情况。索引设计方面第一优先级是中间表的line_id和station_id各建一个普通索引因为换乘算法要高频按这两个维度查询。第二优先级是line表的name字段线路名称的模糊搜索是系统最高频操作不过对于LIKE %1路%这种前模糊匹配普通 B-tree 索引是用不上的数据量小的时候全表扫描也没压力但你需要知道这个知识点——将来如果数据量大可以考虑全文索引或者前缀匹配的优化方案。4. 后端接口的核心实现从 CRUD 到换乘算法的技术纵深4.1 RESTful API 设计与统一返回体后端接口的设计决定了前端联调的效率。一套干净的 RESTful 风格 统一返回结构能让前后端配合顺畅很多。我建议的接口划分如下模块方法路径说明认证POST/api/auth/login登录返回 JWT Token线路查询GET/api/line/search?keyword按名称模糊查询线路线路详情GET/api/line/{id}包含起点、终点、票价、班次等线路站点GET/api/line/{id}/stations按站点序号返回途经站列表站点查询GET/api/station/search?keyword按名称模糊查询站点线路途经站GET/api/station/{id}/lines查询经过某站点的所有线路换乘方案GET/api/transfer/plan?from站点Ato站点B返回 0~2 次换乘的乘车方案收藏管理POST/api/favorite/add用户收藏常用线路或站点统一返回体是最容易被忽视但实际很加分的部分。我见过很多学生项目直接返回裸数据前端拿到什么是什么一旦出现异常就只能看浏览器控制台。建议定义一个Result类包含 code、message、data 三个字段public class ResultT { private Integer code; // 200 成功500 业务异常401 未登录 private String message; // 成功提示或错误信息 private T data; // 真正要返回的数据 }配合RestControllerAdvice全局异常处理器业务代码里只需要抛出自定义异常前端的 axios 拦截器统一处理 code 值即可。JWT 方面用一个简单拦截器校验请求头里的 Token排除/api/auth/**路径不拦截管理端接口再额外校验角色权限。4.2 换乘方案的算法选择BFS 在最短路中的应用换乘方案是这套系统里最有技术含量的功能也是答辩时最值得展开讲的部分。用最直白的话说把每一条公交线路抽象成图上的一条链每个站点是一个节点能把两个节点连接起来的任何公共站点就是换乘点。我建议用 BFS 而不是 Dijkstra因为公交线网中站点间单位距离权重并不精确核心目标是换乘次数最少。BFS 按层级扩散的特性天然满足换乘次数最少这个条件。简单实现思路如下先把所有站点和线路的关系加载进内存构建一个Map站点id, List线路id表示每站可乘坐的所有线路再构建一个Map线路id, List站点id表示每线路经过的所有站点。从起点站出发把经过起点站的每一条线路加入队列作为第一层候选。然后遍历这些线路经过的所有站点再从新站点出发换乘到其他线路继续扩散。每扩散一层换乘次数就加一。如果扩散到第三层还没有覆盖终点站就可以停止并返回换乘次数过多因为一般市区的二次换乘已经能覆盖绝大多数通勤场景。这个算法看起来简单实际实现时有个关键点一定要记录乘坐路线也就是方案不能只返回换乘了两次要返回先坐 1 路从人民广场到火车站再换乘 2 路到机场。所以队列里的元素建议设计成结构体包含当前线路 id、经过站点列表、累计换乘次数、完整乘坐历史。用 BFS 的每一层代表一次换乘即可保证方案的完整性。4.3 管理端接口的权限控制策略管理平台和普通查询端分开是很必要的。管理员负责线路、站点、班次数据的 CRUD 操作普通用户只能做查询和收藏。最简单可靠的方案是基于 JWT 的角色判断。登录接口在验证用户密码后生成 token 的时候把用户角色写进 claims。拦截器里除了验证 token 有效性还要判断请求路径是否以/api/admin/开头。如果是检查 claims 里的角色是否等于admin不等于就直接抛 403 异常。这里要注意的是拦截器在 SpringBoot 中默认只拦截 controller 层静态资源不需要管。但前端页面打包部署后如果放在同一个服务里需要额外放行/static/**、/index.html等路径。4.4 事务管理与数据一致性线路数据的修改往往涉及多张表。比如修改一条线路的途经站点你得先删除中间表里的旧关联再批量插入新关联。如果删除成功但插入失败数据就处于中间状态。这个问题在答辩中经常被问到所以必须在设计阶段考虑。解决办法是在 Service 层加Transactional(rollbackFor Exception.class)注解。这个注解让方法内的所有数据库操作放在同一个数据库事务里任何一个操作抛出异常就整体回滚删除的数据也会恢复。要注意rollbackFor必须带上因为 Spring 的声明式事务默认只回滚 RuntimeException而业务中经常抛的是 Checked Exception比如文件解析失败、外部接口调用失败不指定的话事务不会回滚。5. 前端 Vue 实现的关键细节组件拆解与地图展示5.1 项目脚手架、路由布局与axios封装前端项目的创建方式我建议直接用 Vite相比 Vue CLI 启动速度快很多。注意使用 Vite 需要 Node.js 版本在 14.18 以上如果 Node 版本太低会直接报错。项目内的目录结构建议按模块划分而不是按文件类型堆在一起。我的习惯是views目录下按页面划分比如views/home、views/search、views/admin、views/user每个文件夹里自带该页面专用的组件公共组件放components目录。这种组织方式在项目变得复杂后能让代码库保持可维护性。axios 需要封装两层逻辑。第一层是拦截器请求拦截器里从 localStorage 取出 token 并加到请求头响应拦截器里统一判断 HTTP 状态码和业务 code。如果 code 是 401token 过期或未登录自动跳转登录页code 是 500用 Element UI 的 Message 组件弹出错误提示。这样一来所有页面的异常处理逻辑都集中在一个文件里开发效率会高很多。5.2 线路查询页与地图可视化方案公交线路查询页面是整个系统给用户的第一印象必须把搜索-结果展示-地图联动这条链路做通。页面分左中右三个区域左侧是搜索栏和线路列表中间是地图右侧是选中线路的站点列表和详细信息。地图展示有几种方案。最简单的是用 ECharts 绘制线路走向图将站点坐标转换成散点图用 line 连接形成线路轨迹。ECharts 的effectScatter可以模拟公交车的移动效果视觉效果很好而且不需要申请地图服务的 key。复杂一点的是用腾讯地图 JavaScript API把站点真实叠加到城市地图上。热搜词里也有用在 vue 里的腾讯地图这个确实适合公交场景因为用户对站点位置的感知更真实。腾讯地图 JS API 在 Vue 里的用法是直接通过 script 标签引入然后在mounted生命周期里初始化地图实例注意地图容器需要设置具体高度否则地图区域不会渲染出来。我现场测试时发现很多学生的地图初始化代码没问题但渲染不出来排查到最后基本是 CSS 高度塌陷导致的——地图组的父级容器和地图 div 都没设置height属性默认高度为 0。5.3 换乘方案展示的 UI 设计换乘方案页面要解决的核心问题是信息呈现的清晰度。当一个方案包含两三次换乘时用户要能一眼看出先坐什么车、在哪站换、还要坐多远。我用的是时间线组件每个步骤节点显示一次乘车动线。比如人民广场站上车乘坐 1 路开往火车站方向经过 5 站到达火车站站下车然后换乘图标自动跳到下一步。期间每个步骤右侧的地图会实时高亮对应路段底部显示总耗时估算、总票价、步行距离如果两端距离较远。抓取前端接口用到的换乘方案的字段包括线路名称、方向、上车站名、下车站名、经过站数。这些字段后端在 BFS 中都已经算出来了前端只是按顺序展示而已。关键的实现难点在方向的判断和文案拼接这属于看起来简单做起来繁琐的细节活。5.4 调试利器Vue Devtools 插件的作用我强烈建议开发前端时安装 Vue Devtools 浏览器插件。很多时候页面显示异常不一定是代码逻辑错误而是数据流传输问题。打开 DevTools 的 Vue 面板你可以直接实时查看组件的 data、props、computed 和事件流。特别是调试页面初始化时的接口调用顺序、组件传参是否对得上这种问题比对着 console.log 一点一点打印高效太多。Vue 3 项目注意下载 Beta 版本插件Vue 2 项目用正式版。装错版本会发现插件面板里看不到组件树打开只显示Vue 2 detected之类的提示但无法调试。6. 从零到部署的完整流程与高频报错处理方案6.1 开发环境的完整搭建清单这里我按步骤列一个环境准备清单跟着做基本不会走弯路。第一步安装 JDK 8 或 11配置JAVA_HOME环境变量命令行输入java -version能正常输出版本号。第二步安装 Maven 3.6配置仓库镜像为阿里云仓库这个可以大幅提升依赖下载速度。第三步安装 MySQL 8.0初始化 root 密码新建bus_system数据库用 Navicat 导入项目提供的bus_system.sql文件。第四步安装 Node.js 14设置 npm 淘宝镜像源。第五步安装 IDEA后端开发建议用 IDEA社区版足够安装 Vue.js 和 Lombok 插件。以上就是最精简的完整组合。每一步展开都能讲一小时但按照这个顺序能保证开发过程顺畅。6.2 后端运行和前端运行的完整命令后端运行在 IDEA 里打开项目等待 Maven 自动下载依赖然后启动主类BusSystemApplication.java。如果启动失败优先查看控制台第一行报错信息大部分情况是 application.yml 里的数据库密码错误或者端口被占用。端口被占用时修改server.port或者用命令杀掉占用进程。# 查看端口被哪个进程占用 netstat -ano | findstr 8080前端运行在项目目录下执行npm install npm run devnpm install如果卡住不动的确认一下 npm 源是否是指定的镜像源。开发模式启动后Vite 默认监听http://localhost:5173在.env.development文件里配置VITE_API_BASE_URL/api并在vite.config.js里配置代理server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这样前端调用/api/line/search时会被代理转发到后端的8080端口不需要后端配置任何 CORS 跨域处理。很多学生不知道这个方案默认在前端请求后端接口时跨域报错然后在后端写一堆 CORS 配置类其实用代理在开发环境就能干净地解决这个问题。6.3 打包部署与常见报错的经验手册开发完成后打包部署后端打包命令是mvn clean package -DskipTests生成的 jar 包在target目录下通过java -jar bus-system-0.0.1.jar运行即可。前端打包命令是npm run build生成的dist目录可以直接用 Nginx 托管也可以复制到后端项目的src/main/resources/static目录下这样后端一个 jar 包就把前后端都运行起来部署成本最低。部署过程中最常见的报错我列了一个速查表报错信息原因解决方案Public Key Retrieval is not allowedMySQL 8.0 认证插件问题JDBC 连接串加allowPublicKeyRetrievaltrueAccess denied for user rootlocalhost密码错误或权限不足检查密码确认 root 允许本地登录Server returns invalid timezone时区配置缺失连接串加serverTimezoneAsia/ShanghaiClassNotFoundException: com.mysql.jdbc.Driver驱动类名错误8.0 使用com.mysql.cj.jdbc.DriverThe server time zone value CST时区识别异常连接串加serverTimezoneAsia/Shanghai并重启端口被占用8080/5173 被其他程序占用更换端口或结束占用进程SyntaxError: Unexpected token 前端请求到了 HTML 而非接口检查代理配置确认后端是否正常启动npm ERR! code ELIFECYCLEnpm 依赖安装异常删除 node_modules 和 lock 文件重新 install6.4 源码丢失与二次开发的小技巧最后额外分享一个扩展话题有热搜词提到怎么将 SpringBoot jar 反编译成项目这是拿到别人的打包产物后想学习或复用时必须掌握的技能。SpringBoot 打包出的 jar 本质上还是 Java 字节码可以用 IDEA 自带的反编译器直接打开 jar 包浏览源码。具体做法是IDEA 里新建一个空项目把 jar 包拖进去IDEA 会自动识别为库文件双击类名即可看到反编译后的代码。但如果要还原成完整的可开发项目需要把BOOT-INF/classes下的文件全部取出重组成标准 Maven 结构lib目录里的依赖直接放入本地 Maven 仓库。这个方法适用于学习消化的场景如果是自己的源码不小心丢了建议从数据库结构和线上 jar 反推配合 Git 提交记录恢复整体结构。7. 答辩前要准备的技术问答与演示要点7.1 评审老师最爱问的五个技术问题做了这么多届课设指导我发现评审老师的问题高度集中但很多学生准备不足。这里把五个高频问题列出来并给出参考回答思路。第一个问题为什么用 JWT 而不是 Session核心回答思路是JWT 无状态、跨域友好、天然适合前后端分离架构。Session 需要服务端存储状态如果将来部署多个后端实例做负载均衡Session 同步就成了麻烦。JWT 的信息签名保存在客户端服务端只需要验证签名即可。勿忘补充 JWT 的缺点——如无法主动失效这也体现了深入理解。第二个问题逻辑删除和物理删除的区别物理删除是真正的 DELETE数据无法找回逻辑删除是修改标记字段查询都带deleted0条件。逻辑删除的优势是保留历史数据方便统计和恢复缺点是所有查询语句都要加条件MyBatis Plus 的TableLogic自动做了这件事。第三个问题换乘方案最少换乘次数怎么保证答案是 BFS 逐层扩散。第一层是起点站直接可坐的所有线路第二层是这些线路经过的所有站点能换到的其他线路每层搜索对应一次换乘先搜索到终点站的层数就是最少换乘次数。数学约等于动态规划记忆每次出队可以按本站点能换乘线路继续入队本地加 visited 标记避免环线路。第四个问题MySQL 索引为什么能提升查询性能什么场景下会失效答案是索引基于 B 树结构能快速缩小查找范围。失效场景包括前模糊匹配 LIKE %路、对索引列使用函数运算、隐式类型转换等。最好结合系统里实际执行的查询语句举例说明。第五个问题数据一致性怎么保证解决思路是数据库事务重点讲Transactional的原子性——所有操作要么全部成功要么全部回滚。比如删除线路时同时删除中间表的关联数据、更新缓存、记录日志任何一个环节出错都不允许留下脏数据。7.2 演示流程的设计建议答辩演示顺序建议按亮点前置 操作稳走的原则安排。整个演示的黄金五分钟可以这样设计第一步演示无登录状态下的线路查询和站点查询展示核心功能。第二步演示换乘方案输入人民广场到火车站展示算法计算出的换乘方案包括线路方向、经过站数和换乘点。第三步演示登录后的收藏功能和管理员后台的线路增删改。第四步快速提一句系统的扩展性——如果把 BFS 换成 Dijkstra加入实时路况权重就能支持最快路线。演示过程中注意一件事不要在答辩现场联网依赖外部的 API 或地图服务确保离线也能完整跑通。地图加载如果是用的是第三方 JS API答辩前检查网络环境或者准备静态兜底图不然演示现场加载不出地图是整个演示过程中最尴尬的事情。7.3 源码阅读顺序与二次扩展方向如果你是拿到这套源码学习的同学推荐的阅读顺序是先看数据库的建表脚本理解表之间的关系然后看后端项目结构从 controller 入手指到 service看每个接口做了什么再打开前端项目从路由配置开始梳理页面跳转逻辑重点看 axios 请求是怎么对接后端接口的最后把整个流程跑通之后尝试自己动手加一个功能模块。扩展方向的话最容易做出新意的是两个一是给系统加一个实时车辆位置模拟功能前端定时请求后端把车辆坐标推送到地图上移动做成类似实时公交的效果二是加一个乘车记录统计分析用户在收藏和乘坐记录的基础上用 ECharts 可视化自己每个月的出行站点分布。这两个扩展方向都跟公交场景高度契合而且实现难度可控答辩时额外加分。公交线路查询系统这个项目我在给学生们指导的时候反复强调一件事——它真正锻炼的不是某个单一框架的 API 熟练度而是让你把 Java、数据库、前端三块知识通过一个真实业务场景串联起来。做完这一个项目你对 SpringBoot 如何处理请求、MySQL 如何建模和查询、Vue 如何与后端交互就会有一个完整的认知。这也是为什么这类系统一直是毕设和课设中的常青树。如果你正在做这个项目建议找一条自己最熟悉的真实公交线路把站点和坐标数据填进去演示效果会比随便造的数据好很多。