旅游管理系统的设计与实现(SpringBoot + MySQL + Vue 前后端分离)
一套面向景点展示、门票预订与用户评价的完整旅游服务系统,管理员维护景点与门票,普通用户完成注册、浏览、预订、评价的完整闭环。
目录
一、项目概述 二、技术架构 三、数据库设计 四、用户体系与权限 五、核心业务流程 六、配置与部署 七、项目亮点 八、技术栈总览 九、适合谁用 十、结语
一、项目概述
旅游管理系统的设计与实现,是一套基于 SpringBoot + MySQL + Vue 的前后端分离 Web 应用。系统面向「景点介绍展示」和「门票在线预订」两类核心业务,把原本依赖人工窗口的景点售票流程拆成了可追溯的线上流程。
我把它的业务闭环拆成四条主线:
- 景点档案线 :
jingdianxinxi表承载景点名称、特色、服务保障、供应商、个人票价、景点介绍、旅游路线、预订须知、加入收藏数、点赞数等 13 个字段,是整个系统的数据中枢。 - 门票交易线 :
dingpiaoxinxi表记录每一次门票订单,包含订单编号、景点名称、参观日期、个人票价、购票数量、总费用、用户、订单生成时间、是否审核、是否支付等 12 个字段。 - 用户评价线 :
yonghupingjia表把用户对订单的评价沉淀下来,字段包含订单编号、景点名称、参观日期、用户名、评价内容、是否审核、是否回复、添加时间。 - 互动讨论线 :
discussjingdianxinxi表采用经典的refid + userid + nickname + content + reply结构,景点详情页的评论与回复都落在这张表里。
整个系统跑在一套清晰的技术栈上:SpringBoot 提供 REST 接口,MySQL 存业务数据,Vue 负责前台和后台界面。源码共 88 个 Java 文件、8089 行代码 ,拆出 10 个 Controller、108 个 REST 端点 ,数据库侧设计 9 张表。
系统架构:SpringBoot 接口层 + MySQL 数据层 + Vue 前台后台
关键指标:88 个 Java 文件、10 个 Controller、108 个端点、9 张表、50 行演示数据
前台首页:景点展示、门票预订入口与评价看板,是游客侧的完整门面
后台管理:景点、门票订单、评价、讨论、新闻与配置的统一管理台
二、技术架构
2.1 后端结构
后端按标准的 entity / dao / controller / service 分层组织:
| 层次 | 数量 | 说明 |
|---|---|---|
| Entity 实体 | 9 | 每张业务表一个实体类,字段与表结构一一对应 |
| Controller 控制器 | 10 | 覆盖景点、门票、评价、讨论、新闻、用户、配置、文件、公共接口 |
| Java 文件总数 | 88 | 含 entity / dao / controller / service / util / config |
| Java 代码行数 | 8089 | 全部主业务代码 |
Controller 层的端点分布如下:
| Controller | 端点数 | 职责 |
|---|---|---|
YonghuController |
17 | 普通用户注册、登录、资料维护、个人中心 |
JingdianxinxiController |
13 | 景点列表、详情、收藏、点赞、后台增删改查 |
DingpiaoxinxiController |
12 | 门票订单生成、查询、审核、支付标记 |
YonghupingjiaController |
12 | 用户评价提交、审核、回复 |
DiscussjingdianxinxiController |
12 | 景点评论与回复管理 |
NewsController |
12 | 旅游资讯公告的增删改查与展示 |
CommonController |
9 | 公共工具接口,如文件上传下载 |
UserController |
8 | 管理员登录与权限校验 |
ConfigController |
8 | 系统参数配置维护 |
FileController |
3 | 文件上传、下载、图片地址生成 |
值得注意的是,10 个 Controller 里没有一个是「凑数」的 。最小的 FileController 只有 3 个端点但功能明确(上传、下载、图片地址),最大的 YonghuController 承担了完整的用户生命周期。每个 Controller 都能在论文里独立写成一节「功能设计与实现」。
2.2 前端与后台
前台是标准的 Vue 单页应用,位于 src/main/resources/front/front/,按业务模块拆成 pages/ 目录:
front/front/pages/
├── jingdianxinxi/ # 景点列表、详情、发布
├── dingpiaoxinxi/ # 门票信息
├── yonghupingjia/ # 用户评价
├── discussjingdianxinxi/ # 景点讨论
├── news/ # 旅游资讯
├── yonghu/ # 用户注册、登录、个人中心
├── users/ # 管理员信息
├── config/ # 参数配置
└── login/ # 登录页
每个模块都是标准的 list.html + detail.html + add.html 三件套。这套约定让页面职责非常清晰:列表页负责分页和筛选,详情页负责单条数据展示和关联信息聚合,表单页负责新增和编辑。三个页面对应后端 Controller 里的三个端点方法,前后端一一对齐。
后台管理端位于 src/main/resources/admin/admin/,打包为 dist/index.html,通过 hash 路由切换模块。相比前台,后台是典型的单页管理界面形态:左侧菜单树 + 右侧内容区,所有表格统一走 ElementUI 的 el-table,弹窗统一用 el-dialog。
三、数据库设计
数据库共 9 张表,其中 8 张是业务表,1 张是令牌表。
| 表名 | 行数 | 用途 |
|---|---|---|
jingdianxinxi |
6 | 景点档案主表 |
dingpiaoxinxi |
8 | 门票订单表 |
yonghupingjia |
7 | 用户评价表 |
yonghu |
7 | 普通用户表 |
discussjingdianxinxi |
8 | 景点讨论表 |
news |
6 | 旅游资讯表 |
config |
4 | 系统配置表 |
token |
3 | 登录令牌表 |
users |
1 | 管理员表 |
演示数据共 50 行,分布在 9 张表中。
3.1 景点档案表
jingdianxinxi 是整个系统的数据中枢,13 个字段分四类:
| 类别 | 字段 |
|---|---|
| 基础信息 | id、jingdianmingcheng(景点名称)、jingdiantese(景点特色) |
| 服务信息 | fuwubaozhang(服务保障)、gongyingshang(供应商)、gerenpiaojia(个人票价) |
| 内容信息 | jingdianjieshao(景点介绍)、lvyouluxian(旅游路线)、yudingxuzhi(预订须知)、ruheyuding(如何预订) |
| 展示与统计 | jingdiantupian(景点图片)、thumbsupnum(点赞数)、crazilynum(收藏数)、addtime(添加时间) |
ruheyuding(如何预订)这个字段是我觉得设计得比较用心的地方 ------ 它把「怎么用这个系统订票」写成了数据而不是代码。景点介绍页直接展示这段文本,业务方要改文案不用发版。
3.2 订单表的冗余策略
dingpiaoxinxi 有 12 个字段:订单编号、景点名称、参观日期、个人票价、购票数量、总费用、用户名、订单生成时间、是否审核、是否回复、是否支付、添加时间。
它直接存了 jingdianmingcheng 和 yonghuming,没有做外键关联。 好处是订单历史不会因为景点改名而「漂移」------ 用户看到的是订单生成当时的名字,这在票务场景里是合理的:一张三个月前买的门票,景点后来改名了,票面信息不该跟着变。代价是数据冗余,改景点名要同步刷订单表。
价格相关的四个字段也是刻意分开的:gerenpiaojia(订单生成时的个人票价)、goumaipiaoshu(购票数量)、zongfeiyong(总费用)分开存,而不是只存总价。这样订单历史能还原出当时的单价,即使后来景点调价也不影响已有订单。
3.3 评价表与讨论表
yonghupingjia 通过 dingdanbianhao(订单编号)而不是 dingpiaoxinxi.id 与门票表松耦合。效果是评价天然绑定在一次具体交易上,不会出现「评价了一个不存在的景点」的数据。
discussjingdianxinxi 走的是另一个套路 ------ 经典的 refid + userid + nickname + content + reply 五段式结构:
private Long id;
private Long refid; // 指向被评论的景点 ID
private Long userid; // 评论人 ID
private String nickname; // 昵称(冗余存一份用于展示)
private String content; // 评论内容
private String reply; // 回复内容
private Date addtime;
refid 这个设计让同一张表可以复用到其它模块 ------ 只要换掉 refid 指向的对象类型,评论系统就能给新闻、用��模块复用,不需要另建表。
3.4 令牌表与两套用户体系
token 表只有 3 行,配套 TokenEntity 承载登录态。系统里的令牌生成逻辑在两处:
// UserController.java ------ 管理员侧
String token = generateToken(newValue, "users", "(动态表达式)");
// YonghuController.java ------ 普通用户侧
String token = generateToken(newValue, "yonghu", "(动态表达式)");
从 token.tablename 的实际取值也能交叉验证:数据库里存的值是 用户,说明普通用户侧的令牌确实写进了 token 表。用户体系是「管理员 + 普通用户」两套,没有会员等级或付费分级。
3.5 外键约束为 0
建表脚本没有写外键。这意味着 ER 图上的关联线不能直接读 DDL 画出来 ,得从字段语义和实际数据反推 ------ 比如 dingpiaoxinxi.yonghuming 指向 yonghu.yonghuming 这种关系,DDL 里没有任何声明。
这在教学项目里是常见做法(生成器模板不写外键),但对做毕设的人是提醒:论文里的 ER 图要自己按业务语义补全,不能只贴建表语句就完事。
四、用户体系与权限
系统有两套独立的账号体系。
管理员(users 表,5 个字段) 负责后台管理:景点增删改查、门票订单审核、评价审核与回复、讨论管理、资讯发布、参数配置。
普通用户(yonghu 表,9 个字段) 负责前台使用:
| 字段 | 含义 |
|---|---|
id |
主键 |
yonghuming |
用户名 |
mima |
口令(散列存储) |
xingming |
姓名 |
xingbie |
性别 |
shouji |
手机号 |
youxiang |
邮箱 |
touxiang |
头像 |
addtime |
注册时间 |
两套体系走的是同一套通用 Controller 骨架 ------ 登录、注册、资料维护、个人中心、退出登录,接口形状一致,只是查询的表和令牌标识不同。这种设计的好处是新模块可以快速复用认证链路,坏处是初学者容易在两套代码之间看晕。
五、核心业务流程
5.1 景点浏览
前端进入首页后拉取景点列表,每条景点记录包含名称、特色、服务保障、供应商、个人票价、图片和统计数据。点击进入详情页,可以查看景点介绍、旅游路线、预订须知,同时看到该景点下的门票信息、用户评价和讨论区。
景点详情页的讨论区支持发评论和回复。点赞和收藏计数(thumbsupnum、crazilynum)直接记在景点表上,读景点列表时一次查询就能带上,不用额外聚合 ------ 这是典型的「读多写少场景下反范式」取舍。
5.2 门票预订
这是系统的业务核心,流程如下:
- 用户在景点详情页选择参观日期和票量;
- 前端计算总价并生成订单编号;
- 2.1 确认参观日期与票量;
- 提交到
dingpiaoxinxi表,记录景点、日期、个人票价、数量、总费用、用户名; - 订单初始为待审核状态(
sfsh= 否); - 管理员在后台审核订单,置为已审核;
- 用户完成支付标记(
ispay字段记录支付状态)。
订单状态由 sfsh(是否审核)、shhf(是否回复)和 ispay(是否支付)三个独立字段组合表达,而不是单一状态枚举。这种设计的取舍是:审核、回复、支付在业务上是三条独立的线,硬压成一个状态字段会导致状态组合爆炸(2³ = 8 种组合还得考虑非法组合)。
5.3 评价与互动
用户在参观后可以针对订单发表评价,评价内容落到 yonghupingjia 表。评价同样需要管理员审核(sfsh),审核通过后管理员可以回复(shhf)。景点上还有点赞和收藏计数,直接记在景点表上。
六、配置与部署
6.1 配置文件
application.yml 共 52 行,核心配置如下:
url: jdbc:mysql://127.0.0.1:3306/springbootul0e4?useUnicode=true&characterEncoding=utf-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8
username: root
password: 你的数据库密码
context-path: /springbootul0e4
port: 8080
static-locations: classpath:static/,file:static/
6.2 一个容易踩的坑:改端口要改 3 处
static-locations 没有映射 front/ 目录,前台页面走的是 SpringBoot 对 classpath:/ 的默认兜底。所以目录是双层的,但 URL 只写一层:
| 目录里的实际文件 | 访问地址 |
|---|---|
front/front/index.html |
/index.html |
admin/admin/dist/index.html |
/admin/admin/dist/index.html |
这个结构带来一个必须注意的部署细节:改端口不止改 application.yml 一处。前端还硬编码了接口地址:
| 文件 | 需要改的处数 |
|---|---|
front/front/modules/http/http.js |
2 |
front/front/js/config.js |
1 |
只改 application.yml 的后果是:后台能正常打开,前台一片白 ------ 因为前端还在往旧端口发请求。改端口时这三处要一起改。这个坑几乎每个第一次部署这套工程的人都会撞一次。
6.3 运行方式
数据库准备好后,直接用 java -jar 启动即可,不需要额外中间件:
# 1. 建库并导入脚本
mysql -u root -p < db.sql
# 2. 按实际环境修改 application.yml 中的数据库地址与口令
# 3. 打包运行
mvn clean package -DskipTests
java -jar target/*.jar
启动后访问 http://localhost:8080/springbootul0e4/ 就能看到前台。
七、项目亮点
1. 业务闭环完整,不是半成品
景点展示、门票预订、评价反馈、评论互动四条线互相咬合。门票订单表冗余景点名和用户名,评价表通过订单编号关联 ------ 这些字段设计都指向一个目标:订单历史稳定,不随主数据变更而漂移。
2. 订单状态用三个布尔位表达
sfsh(审核)、shhf(回复)、ispay(支付)三条独立线,避免了单一枚举的状态组合爆炸。这是做业务系统时很实用的一个建模经验。
3. 两套用户体系共用一套骨架
管理员和普通用户的 Controller 结构完全对称,认证链路(generateToken)也统一,只是表名和令牌标识不同。新增模块可以直接复制这套骨架,改造速度快。
4. 数据结构贴近真实票务场景
景点表带服务保障、供应商、旅游路线、预订须知;门票表带参观日期、购票数量、总费用;评价表带审核和回复标记。这些字段不是凑出来的,是照着实际票务流程逐项落的。
5. 演示数据覆盖全部业务表
50 行种子数据分布在 9 张表里,前台每个列表页打开就有内容,评价、讨论、订单这些关联表也都有对应记录,不用手工造数据就能看到完整效果。
6. 通用文件接口已经封装
CommonController 和 FileController 提供了统一的上传、下载、图片地址生成接口。景点图片、用户头像、评价配图都走同一套,扩展新模块时不用再写一遍。
八、技术栈总览
| 层次 | 技术选型 |
|---|---|
| 后端框架 | SpringBoot |
| 持久层 | MyBatis-Plus |
| 数据库 | MySQL 8 |
| 前端框架 | Vue |
| UI 组件 | ElementUI + Layui |
| 构建工具 | Maven |
| 接口风格 | REST + JSON |
| 认证方式 | Token 令牌表 |
九、适合谁用
这套系统的完整度适合直接作为本科毕业设计的底稿,也适合作为 SpringBoot 入门到进阶的学习项目:
- 做毕设 ------ 9 张表、10 个 Controller、108 个端点,够撑起一篇有内容的技术论文;业务流程完整,答辩时演示路径清晰(浏览景点 → 预订门票 → 提交评价 → 后台审核)。
- 学技术 ------ 前后端分离的标准结构,Vue 前台 + ElementUI 后台 + SpringBoot 接口,接口生成方式和分层写法都值得照着看一遍。
- 做参考 ------ 订单状态建模、多表冗余策略、双用户体系抽象,这几个点可以直接搬进自己的项目。
十、结语
旅游管理系统这个题目看着简单,真正做下来会发现难点全在「状态」上:订单要审核、要支付、要回复,评价要审核要回复,评论要回复。把这些拆成独立的状态位而不是一个枚举字段,是这个项目在建模上最值得复用的经验。
数据库脚本、工程源码、开发文档随项目资料一起交付,导入即可运行。
关键词:旅游管理系统、SpringBoot、MySQL、Vue、前后端分离、门票预订、景点管理、毕业设计