原创

基于SpringBoot2+vue2的安康旅游网站

温馨提示:
本文最后更新于 2026年06月04日,已超过 6 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

1. 资源

放到文章最后面

2. 项目简介

安康旅游网站旨在为游客提供在线旅游服务。系统主要功能包括:

  • 景点信息模块:展示景点详情、支持景点搜索、分类筛选、在线购票以及点赞/点踩。
  • 酒店信息模块:展示酒店详情、支持酒店搜索、在线预订。
  • 特产模块:展示特产详情、支持特产搜索、在线购买。
  • 旅游线路模块:游客可以规划和发布自己的旅游线路。
  • 订单管理模块:游客可以管理自己的景点购票订单、酒店预订订单和特产购买订单,并支持订单取消功能。
  • 个人中心:游客可以管理自己的个人信息、查看个人收藏。
  • 后台管理模块:管理员可以对游客信息、景点、酒店、特产、订单、留言板、轮播图、新闻公告等进行全面的管理。

3. 技术栈

后端

  • 核心框架: Spring Boot 2.2.2.RELEASE
  • 持久层框架: MyBatis Plus 2.3
  • 权限控制: Apache Shiro 1.3.2
  • 数据库: MySQL 5.7.32
  • 工具库: Hutool 4.0.12, Fastjson 1.2.8, Commons-lang3 3.0

前端

  • 后台管理界面:
    • 核心框架: Vue.js
    • UI 库: Element UI
    • HTTP 请求: Axios
  • 前台用户界面:
    • 核心库: Vue.js, Layui, JQuery
    • 地图: 高德地图 API (VueAMap)

4. 详细介绍

4.1. 前台用户端

  1. 用户登录/注册

    • 用户可以通过登录页面进入系统。
    • 新用户可以通过注册功能创建账号。
  2. 首页

    • 展示网站轮播图。
    • 提供景点信息、酒店信息、特产的推荐展示。
    • 展示最新的旅游新闻公告。
  3. 景点信息模块

    • 用户可以按省区、城市、地区等条件筛选和搜索景点。
    • 点击景点可查看详细信息(如介绍、开放时间、价格等)。
    • 在详情页,用户可以进行点赞/点踩、收藏、在线购票操作。
    • 用户可以对景点发表评论。
  4. 酒店信息模块

    • 用户可以按城市等条件筛选和搜索酒店。
    • 点击酒店可查看详细信息(如介绍、价格、房间数等)。
    • 在详情页,用户可以进行收藏、在线预订房间操作。
    • 用户可以对酒店发表评论。
  5. 特产模块

    • 用户可以按城市等条件筛选和搜索特产。
    • 点击特产可查看详细信息(如介绍、价格、库存等)。
    • 在详情页,用户可以进行收藏、在线购买操作。
    • 用户可以对特产发表评论。
  6. 旅游线路模块

    • 用户可以查看自己或其他游客分享的旅游线路规划。
  7. 个人中心

    • 用户可以修改自己的个人信息、密码和头像。
    • 用户可以查看和管理自己的景点购票订单、酒店订单、特产订单,并可以对未支付的订单进行支付或取消。
    • 用户可以查看和管理自己的收藏列表。
  8. 留言板模块

    • 用户可以在留言板中留言,与其他用户或管理员进行交流。
  9. 新闻公告模块

    • 用户可以查看网站发布的旅游相关新闻和公告。

4.2. 后台管理端

  1. 游客管理:对注册游客进行增删改查。
  2. 景点信息管理:对景点信息进行增删改查,并查看景点下的用户评论。
  3. 酒店信息管理:对酒店信息进行增删改查,并查看酒店下的用户评论。
  4. 特产管理:对特产信息进行增删改查,并查看特产下的用户评论。
  5. 地区管理:对省区、市区、地区等行政区域信息进行增删改查。
  6. 旅游线路管理:查看游客发布的旅游线路。
  7. 订单管理:对所有用户的景点购票订单、酒店订单、特产订单以及各类取消订单进行查看、审核、修改和删除操作。
  8. 留言板管理:查看和回复用户的留言。
  9. 系统管理
    • 管理旅游新闻公告。
    • 管理网站首页的轮播图。
    • 管理网站的其他基础配置。

5. 部分代码

5.1. 后端:景点信息实体类 (JingdianxinxiEntity.java)

package com.entity;

// ... 省略导入

@TableName("jingdianxinxi")
public class JingdianxinxiEntity<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    @TableId
    private Long id;
    private String jingdianmingcheng; // 景点名称
    private String jingdiandengji; // 景点等级
    private String jingdianjieshao; // 景点介绍
    private String suozaishengqu; // 所在省区
    private String suozaichengshi; // 所在城市
    private String suozaidiqu; // 所在地区
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat
    private Date meitiankaifangshijian; // 每天开放时间
    // ... 其他属性,如价格、图片、点击次数等
    // ... 省略 getter/setter
}

5.2. 后端:景点信息控制器 (JingdianxinxiController.java)

package com.controller;

// ... 省略导入

@RestController
@RequestMapping("/jingdianxinxi")
public class JingdianxinxiController {
    @Autowired
    private JingdianxinxiService jingdianxinxiService;

    // 前端列表查询接口
    @IgnoreAuth
    @RequestMapping("/list")
    public R list(@RequestParam Map<String, Object> params, JingdianxinxiEntity jingdianxinxi,
                  HttpServletRequest request) {
        EntityWrapper<JingdianxinxiEntity> ew = new EntityWrapper<JingdianxinxiEntity>();
        PageUtils page = jingdianxinxiService.queryPage(params,
                MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, jingdianxinxi), params), params));
        return R.ok().put("data", page);
    }

    // 前端详情接口(增加点击次数)
    @RequestMapping("/detail/{id}")
    public R detail(@PathVariable("id") Long id) {
        JingdianxinxiEntity jingdianxinxi = jingdianxinxiService.selectById(id);
        jingdianxinxi.setClicknum(jingdianxinxi.getClicknum() + 1);
        jingdianxinxi.setClicktime(new Date());
        jingdianxinxiService.updateById(jingdianxinxi);
        return R.ok().put("data", jingdianxinxi);
    }

    // ... 其他接口
}

5.3. 后端:通用接口(如省市区联动) (CommonController.java)

package com.controller;

// ... 省略导入

@RestController
public class CommonController {
    @Autowired
    private CommonService commonService;

    // 获取table表中的column列表(联动接口)
    @IgnoreAuth
    @RequestMapping("/option/{tableName}/{columnName}")
    public R getOption(@PathVariable("tableName") String tableName,
                       @PathVariable("columnName") String columnName,
                       String level, String parent) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("table", tableName);
        params.put("column", columnName);
        // ... 处理 level 和 parent 参数
        List<String> data = commonService.getOption(params);
        return R.ok().put("data", data);
    }
    // ... 其他接口
}

5.4. 前端:酒店信息列表页 (list.html)

<!-- 省略头部和样式 -->
<body>
  <div id="app">
    <!-- 轮播图区域 -->
    <div class="banner">...</div>

    <div class="recommend index-pv1">
      <div class="box" style='width:90%'>
        <!-- 搜索筛选区域 -->
        <form class="layui-form filter">
          <div class="item-list">
            <div class="lable">酒店名称</div>
            <input type="text" name="jiudianmingcheng" id="jiudianmingcheng" placeholder="酒店名称" autocomplete="off">
          </div>
          <!-- 其他筛选项 -->
          <button id="btn-search" type="button" class="layui-btn">搜索</button>
          <button v-if="isAuth('jiudianxinxi','新增')" @click="jump('../jiudianxinxi/add.html')" type="button" class="layui-btn btn-theme">添加</button>
        </form>

        <!-- 数据列表区域 -->
        <div class="list news">
          <div @click="jump('../jiudianxinxi/detail.html?id='+item.id)" v-for="(item,index) in dataList" :key="index" class="list-item">
            <div class="list-item-body animation-box">
              <img :src="item.tupian?item.tupian.split(',')[0]:''">
              <div class="item-info">
                <div class="name">{{item.jiudianmingcheng}}</div>
              </div>
            </div>
          </div>
        </div>
        <!-- 分页 -->
        <div class="pager" id="pager"></div>
      </div>
    </div>
  </div>
  <script src="../../layui/layui.js"></script>
  <script src="../../js/vue.js"></script>
  <script>
    // Vue实例和分页请求逻辑...
  </script>
</body>
</html>

5.5. MyBatis Mapper XML 配置 (JingdianxinxiDao.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.dao.JingdianxinxiDao">

    <resultMap type="com.entity.JingdianxinxiEntity" id="jingdianxinxiMap">
        <result property="jingdianmingcheng" column="jingdianmingcheng"/>
        <result property="jingdiandengji" column="jingdiandengji"/>
        <!-- ... 其他字段映射 -->
        <result property="clicknum" column="clicknum"/>
    </resultMap>

    <select id="selectListVO" resultType="com.entity.vo.JingdianxinxiVO">
        SELECT * FROM jingdianxinxi jingdianxinxi
        <where> 1=1 ${ew.sqlSegment}</where>
    </select>
    <!-- ... 其他查询 -->
</mapper>

6. 部分截图

img1
img2
img3
img4
img5
img6
img7
img8
img9
img10
img11
img12
img13
img14
img15
img16
img17
img18
img19
img20
img21
img22
img23
img24
img25
img26
img27
img28
img29
img30
img31
img32
img33
img34
img35
img36
img37
img38
img39
img40
img41

7. 项目总结

本项目是一个功能完备的旅游网站系统,涵盖了在线旅游服务商所需的核心功能,如资源展示、在线预订/购买、订单管理、用户互动等。

  • 优点:

    • 功能全面:系统覆盖了前台用户浏览、交易和后台管理员维护的全流程,业务逻辑清晰。
    • 技术栈成熟:采用 Spring Boot + MyBatis Plus + Shiro 构建后端,开发效率高,结构清晰,安全可控。前端使用 Vue.js 和 Layui,兼顾了后台管理的组件化需求和前台展示的灵活性。
    • 交互友好:前台页面提供了详细的筛选和搜索功能,支持地图、点赞、评论等丰富交互,用户体验较好。
  • 待优化点:

    • 前后端分离不彻底:项目中的前台页面 (/front 目录) 仍使用传统的 HTML + Vue.js CDN 方式渲染,未与后台管理一样使用完整的 Node.js 构建工具链,不利于大型项目的工程化维护。
    • 代码生成器痕迹:代码结构具有明显的 MyBatis Plus 代码生成器特征,如大量的 VO、View 类,部分代码存在冗余。通用的 Controller 和服务层逻辑在真实项目中可能需要进一步抽象。
    • 支付与安全:项目仅演示了订单状态(ispay 字段),未集成真实的第三方支付接口。同时,生产环境需加强 XSS、CSRF 等安全防护,并优化 Shiro 的 Session 管理策略。
    • 前端UI一致性:后台使用 Element UI,前台使用 Layui,两套UI库可能导致开发风格和维护成本的不一致。

代码:https://fifteen.xiaobias.com/source/102

正文到此结束
本文目录