Vue.js+SpringBoot开发海南旅游景点推荐系统

目录
- 一、摘要
- 1.1 项目介绍
- 1.2 项目录屏
- 二、功能模块
- 2.1 用户端
- 2.2 管理员端
- 三、系统展示
- 四、核心代码
- 4.1 随机景点推荐
- 4.2 景点评价
- 4.3 协同推荐算法
- 4.4 网站登录
- 4.5 查询景点美食
- 五、免责说明
一、摘要
1.1 项目介绍
基于Vue+SpringBoot+MySQL的海南旅游推荐系统,基于协同推荐算法,包括用户网页和管理后台,包含景点类型模块、旅游景点模块、行程推荐模块、美食推荐模块、景点排名模块,还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块,海南旅游推荐系统基于角色的访问控制,给景点管理员、游客使用,可将权限精确到按钮级别,您可以自定义角色并分配权限,系统适合设计精确的权限约束需求。
1.2 项目录屏
二、功能模块
2.1 用户端
- 景点推荐:根据用户个性化偏好给用户推荐感兴趣的景点
【景点信息包含:景点名称、景点类型、评分、收藏量、门票价格、门票预订(提供购买链接,用户可以通过点击链接到其他平台购买门票)、开放时间、景区地址(所在市区、详细地址)、景点介绍】 - 景点筛选:用户可通过设置自己想要的景点类型、景点门票价格范围、景区地址(海口市、三亚市、儋州市、三沙市等)来筛选满足自身需求的景点
筛选:【注:若用户只设置了一个筛选条件则只需满足一个筛选条件就推荐给用户,若设置两个以上,则需都满足才给用户推荐】 - 旅游攻略:用户可以通过搜索景点名称来获取景点周边美食以及行程路线的相关信息
(1)交通指南:起点、终点、交通方式、行程路线
(2)周边美食:美食图片、名称、类型、简介、人均消费 - 景点数据:景点数据可视化
(1)好评度排名:管理员可以看到好评度高的前十个景点【排名、景点名称、好评度】
(2)景点收藏量:管理员可以看到收藏量排名前十的景点【排名、景点名称、收藏量】 - 个人中心:
(1)个人信息:账号、姓名、联系方式、身份证号(用户可以更新个人信息、退出登录)
(2)景点收藏:用户可以查看、取消收藏过的景点
2.2 管理员端
- 个人中心:管理员个人信息
- 景点信息管理:
(1)查询:可通过搜索景点名称、地址、景点类型来获取需要的景点数据(搜索到需要的景点数据后可进行查看、修改、删除景点信息操作)
(2)添加:可以添加新的景点信息 - 用户信息管理:
(1)查询:可通过搜索用户账号来查询需要的用户(查询到需要的用户后可对用户信息进行查看、修改、删除操作)
(2)添加:可添加新用户信息 - 行程信息管理:
(1)查询:可通搜索景点地址来获取景点行程路线信息(查询到需要的行程信息后可对其进行查看、修改、删除操作)
(2)添加:可添加信息 - 美食信息管理:
(1)查询:可通搜索景点地址来获取景点周边美食信息(查询到需要的信息后可对其进行查看、修改、删除操作)
(2)添加:可添加新的美食信息 - 景点数据:景点数据可视化(同用户端的景点数据可视化)
(1)好评度排名:管理员可以看到好评度高的前十个景点【排名、景点名称、好评度】
(2)景点收藏量:管理员可以看到收藏量排名前十的景点【排名、景点名称、收藏量】
三、系统展示








四、核心代码
4.1 随机景点推荐
@RequestMapping(value = "/getRecommendList2OnWeb", method = RequestMethod.GET)
@ApiOperation(value = "查询推荐的景点")
public Result<List<ScenicSpot>> getRecommendList2(){List<ScenicSpot> spotList = iScenicSpotService.list();int[] arr = new int[spotList.size()];for(int i = 1; i < spotList.size(); i ++) {arr[i - 1] = i;}int[] ints = selectM(arr, 10);List<ScenicSpot> ans = new ArrayList<>();for (int i : ints) {ans.add(spotList.get(i));}return new ResultUtil<List<ScenicSpot>>().setData(ans);
}public static int[] selectM(int[] arr,int m){int len=arr.length;if(m>arr.length) {throw new RuntimeException("xxxxx");}int[] res=new int[m];for(int i=0;i<m;i++){int randomIndex=len-1-new Random().nextInt(len-i);res[i]=arr[randomIndex];int tmp=arr[randomIndex];arr[randomIndex]=arr[i];arr[i]=tmp;}return res;
}
4.2 景点评价
@RequestMapping(value = "/addEvaluate", method = RequestMethod.GET)
@ApiOperation(value = "新增评价")
public Result<Evaluate> addEvaluate(@RequestParam String id, @RequestParam BigDecimal level, @RequestParam String message){ScenicSpot ss = iScenicSpotService.getById(id);if(ss == null) {return ResultUtil.error("景点不存在");}User currUser = securityUtil.getCurrUser();QueryWrapper<Evaluate> qw = new QueryWrapper<>();qw.eq("spot_id",ss.getId());qw.eq("user_id",currUser.getId());qw.last("limit 1");Evaluate evaluate = iEvaluateService.getOne(qw);if(evaluate == null) {evaluate = new Evaluate();evaluate.setSpotId(ss.getId());evaluate.setSpotName(ss.getTitle());evaluate.setUserId(currUser.getId());evaluate.setUserName(currUser.getNickname());}evaluate.setLevel(level);evaluate.setMessage(message);evaluate.setTime(DateUtil.now());iEvaluateService.saveOrUpdate(evaluate);return ResultUtil.success();
}
4.3 协同推荐算法
@Scheduled(cron = "0 0/1 * * * ?")
@ApiOperation(value = "景点数据更新")
public void job(){List<ScenicSpot> spotList = iScenicSpotService.list();for (ScenicSpot vo : spotList) {Long evaluateSum = 0L;QueryWrapper<Evaluate> evalQw = new QueryWrapper<>();evalQw.eq("spot_id",vo.getId());List<Evaluate> evaluateList = iEvaluateService.list(evalQw);for (Evaluate evaluate : evaluateList) {evaluateSum += evaluate.getLevel().longValue();}// 收藏 10分QueryWrapper<Collection> coQw = new QueryWrapper<>();coQw.eq("spot_id",vo.getId());evaluateSum += iCollectionService.count(coQw);// 浏览 1分String viewStr = redisTemplate.get("SPOT_VIEW:" + vo.getId());if(!ZwzNullUtils.isNull(viewStr)) {try {long viewNumber = Long.parseLong(viewStr);evaluateSum += viewNumber;} catch (Exception e) {}}vo.setValue(evaluateSum);}Collections.sort(spotList, new Comparator<ScenicSpot>() {@Overridepublic int compare(ScenicSpot o1, ScenicSpot o2) {return (int)(o2.getValue() - o1.getValue());}});if(spotList.size() > 10) {spotList = spotList.subList(0,10);}for (ScenicSpot vo1 : spotList) {// 评分BigDecimal evaluateSum = BigDecimal.ZERO;QueryWrapper<Evaluate> evalQw = new QueryWrapper<>();evalQw.eq("spot_id",vo1.getId());List<Evaluate> evaluateList = iEvaluateService.list(evalQw);for (Evaluate evaluate : evaluateList) {evaluateSum = evaluateSum.add(evaluate.getLevel());}if(evaluateList.size() > 0) {vo1.setStar(evaluateSum.divide(BigDecimal.valueOf(evaluateList.size()),2, RoundingMode.DOWN));} else {vo1.setStar(BigDecimal.valueOf(-1));}// 收藏QueryWrapper<Collection> coQw = new QueryWrapper<>();coQw.eq("spot_id",vo1.getId());vo1.setCollection(iCollectionService.count(coQw));}redisTemplate.set("SPOT_JOB_DATA", JSON.toJSONString(spotList));System.out.println("缓存完毕!");
}
4.4 网站登录
@RequestMapping(value = "/loginOnWeb", method = RequestMethod.GET)
@ApiOperation(value = "网站前台登陆")
public Result<String> loginOnWeb(@RequestParam String userName, @RequestParam String password){QueryWrapper<User> qw = new QueryWrapper<>();qw.eq("username",userName);List<User> userList = iUserService.list(qw);if(userList.size() < 1) {return ResultUtil.error("用户不存在");}User user = userList.get(0);if(!new BCryptPasswordEncoder().matches(password, user.getPassword())){return ResultUtil.error("密码不正确");}String accessToken = securityUtil.getToken(user.getUsername(), true);UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(new SecurityUserDetails(user), null, null);SecurityContextHolder.getContext().setAuthentication(authentication);return new ResultUtil<String>().setData(accessToken);
}
4.5 查询景点美食
@RequestMapping(value = "/getByPage", method = RequestMethod.GET)
@ApiOperation(value = "查询美食")
public Result<IPage<DeliciousFood>> getByPage(@ModelAttribute DeliciousFood deliciousFood ,@ModelAttribute PageVo page){QueryWrapper<DeliciousFood> qw = new QueryWrapper<>();if(!ZwzNullUtils.isNull(deliciousFood.getTitle())) {qw.like("title",deliciousFood.getTitle());}if(!ZwzNullUtils.isNull(deliciousFood.getContent())) {qw.like("content",deliciousFood.getContent());}if(!ZwzNullUtils.isNull(deliciousFood.getSpotId())) {qw.eq("spot_id",deliciousFood.getSpotId());}IPage<DeliciousFood> data = iDeliciousFoodService.page(PageUtil.initMpPage(page),qw);return new ResultUtil<IPage<DeliciousFood>>().setData(data);
}
五、免责说明
- 本项目仅供个人学习使用,商用授权请联系博主,否则后果自负。
- 博主拥有本软件构建后的应用系统全部内容所有权及独立的知识产权,拥有最终解释权。
- 如有问题,欢迎在仓库 Issue 留言,看到后会第一时间回复,相关意见会酌情考虑,但没有一定被采纳的承诺或保证。
下载本系统代码或使用本系统的用户,必须同意以下内容,否则请勿下载!
- 出于自愿而使用/开发本软件,了解使用本软件的风险,且同意自己承担使用本软件的风险。
- 利用本软件构建的网站的任何信息内容以及导致的任何版权纠纷和法律争议及后果和博主无关,博主对此不承担任何责任。
- 在任何情况下,对于因使用或无法使用本软件而导致的任何难以合理预估的损失(包括但不仅限于商业利润损失、业务中断与业务信息丢失),博主概不承担任何责任。
- 必须了解使用本软件的风险,博主不承诺提供一对一的技术支持、使用担保,也不承担任何因本软件而产生的难以预料的问题的相关责任。

相关文章:
Vue.js+SpringBoot开发海南旅游景点推荐系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统ÿ…...
mysql笔记:11. 性能优化
文章目录 概览查询速度优化1. 分析查询语句1.1 EXPLAIN1.2 DESCRIBE 2. 使用索引优化查询3. 优化子查询 数据库结构优化1. 分解表2. 建立中间表3. 增加冗余字段4. 优化插入速度4.1. MyISAM引擎表4.2. InnoDB引擎表 5. 分析表、检查表和优化表5.1. 分析表5.2. 检查表5.3. 优化表…...
基于Docker搭建Maven私服仓库(Linux)详细教程
文章目录 1. 下载镜像并启动容器2. 配置Nexus3. 配置本地Maven仓库 1. 下载镜像并启动容器 下载Nexus3镜像 docker pull sonatype/nexus3查看Nexus3镜像是否下载成功 docker images创建Nexus3的挂载文件夹 mkdir /usr/local/nexus-data && chown -R 200 /usr/local…...
IPSEC VPPN 实验
背景:FW1和FW2为双机热备 要求:在FW5和FW3之间建立一条IPSEC通道,保证10.0.2.0/24网段可以正常访问到192.168.1.0/24IPSEC VPPN实验配置 fw2配置 加密数据流 新建对应IKE...
基于单片机的视觉导航小车设计
目 录 摘 要 I Abstract II 引 言 1 1 总体方案设计 3 1.1 方案论证 3 1.2 项目总体设计 3 2 项目硬件设计 4 2.1 主控模块设计 4 2.1.1单片机选型 4 2.1.2 STM32F103RCT6芯片 4 2.2单片机最小系统电路 5 2.3电机驱动模块设计 7 2.4红外模块设计 8 2.5红外遥控模块设计 9 2.6超…...
Autosar教程-Mcal教程-GPT配置教程
3.3GPT配置、生成 3.3.1 GPT配置所需要的元素 GPT实际上就是硬件定时器,需要配置的元素有: 1)定时器时钟:定时器要工作需要使能它的时钟源 2)定时器分步:时钟源进到定时器后可以通过分频后再给到定时器 定时器模块选择:MCU有多个定时器模块,需要决定使用哪个定时器模块作…...
力扣--动态规划5.最长回文子串
class Solution { public:string longestPalindrome(string s) {// 获取输入字符串的长度int n s.size();// 如果字符串长度为1,直接返回原字符串,因为任何单个字符都是回文串if (n 1)return s;// 创建一个二维数组dp,用于记录子串是否为回…...
PokéLLMon 源码解析(一)
.\PokeLLMon\poke_env\concurrency.py # 导入必要的模块 import asyncio import atexit import sys from logging import CRITICAL, disable from threading import Thread from typing import Any, List# 在新线程中运行事件循环 def __run_loop(loop: asyncio.AbstractEvent…...
银河麒麟服务器操作系统V10【vnc配置多用户登录】
1.添加多用户(规划kingbase使用5901窗口,root使用5903); adduser kingbase 2.配置文件; cp -rp /lib/systemd/system/vncserver.service /etc/systemd/system/vncserver:1.servicecp -rp /lib/systemd/system/vncse…...
Logseq电脑端+安卓端同步gitee或github
文章目录 0.初衷1.电脑端1.1 新建仓库1.2 克隆项目,生成秘钥1.3 添加图谱,选择文件目录,我是原本就有笔记,所以会如下所示。1.4 下载脚本文件1.5赋权限 (windows可跳过)1.6 修改脚本命令1.7 logseq设置同步…...
【FAQ】HarmonyOS SDK 闭源开放能力 —Map Kit
1.问题描述 在App中供用户在地图上选择地址,目前在使用Map Kit结合geolocationManager逆地理编码时获取的地址信息描述不准确,希望能提供相应的Demo参考。 解决方案 Demo代码示例: getLocation() { let requestInfo: geoLocationManager.…...
【ros2 control 机器人驱动开发】双关节多控制器机器人学习-example 6
【ros2 control 机器人驱动开发】双关节多控制器机器人学习-example 6 文章目录 前言一、创建controller相关二、逻辑分析RRBotModularJoint类解析ros2_control.xacro解析三、测试运行测试forward_position_controller总结前言 本篇文章在上篇文章的基础上主要讲解双轴机器人驱…...
Learn OpenGL 07 摄像机
定义摄像机参数 glm::vec3 cameraPos glm::vec3(0.0f, 0.0f, 3.0f);//摄像机位置glm::vec3 cameraTarget glm::vec3(0.0f, 0.0f, 0.0f);glm::vec3 cameraDirection glm::normalize(cameraPos - cameraTarget);//摄像机方向,指向z轴正方向 glm::vec3 up glm::vec…...
Linux系统部署火狐浏览器结合内网穿透实现公网访问
目录 前言 1. 部署Firefox 2. 本地访问Firefox 3. Linux安装Cpolar 4. 配置Firefox公网地址 5. 远程访问Firefox 6. 固定Firefox公网地址 7. 固定地址访问Firefox 结语 前言 作者简介: 懒大王敲代码,计算机专业应届生 今天给大家聊聊Linux系统…...
Elastic Stack--05--聚合、映射mapping
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1.聚合(aggregations)基本概念桶(bucket)度量(metrics) 案例 11. 接下来按price字段进行分组:2. 若想对所…...
【嵌入式——QT】Model/View
【嵌入式——QT】Model/View 基本原理数据模型视图组件代理Model/View结构的一些概念QFileSystemModelQStringListModelQStandardItemModel自定义代理 基本原理 GUI应用程序的一个很重要的功能是由用户在界面上编辑和修改数据,典型的如数据库应用程序,数…...
向量化编程书籍推荐
文章目录 1. 书籍清单 1. 书籍清单 《Linear Algebra and Its Applications》 by Gilbert Strang 这本书是线性代数的经典教材,线性代数是向量化编程的基础。它涵盖了向量、矩阵、线性变换等内容,对理解向量化编程的数学概念非常有帮助《NumPy Beginner…...
算法D43 | 动态规划5 | 1049. 最后一块石头的重量 II 494. 目标和 474.一和零
1049. 最后一块石头的重量 II 本题就和 昨天的 416. 分割等和子集 很像了,可以尝试先自己思考做一做。 视频讲解:动态规划之背包问题,这个背包最多能装多少?LeetCode:1049.最后一块石头的重量II_哔哩哔哩_bilibili 代…...
设计模式—桥接模式
定义: 桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interfce)模式。 本章代码:小麻雀icknn/设计模式练习 - Gitee.com 结构: 抽象化(Abstraction)角色:…...
伊萨卡训练代码
我们建议创建并激活 conda 环境,以确保在下面安装正确的软件包版本的干净环境。 # Optional but recommended: conda create -n ithaca python3.9 conda activate ithaca 克隆此存储库并进入其根目录。通过以下方式安装完整的 ithaca 依赖项(包括训练&am…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
Vue 3 + WebSocket 实战:公司通知实时推送功能详解
📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...
如何通过git命令查看项目连接的仓库地址?
要通过 Git 命令查看项目连接的仓库地址,您可以使用以下几种方法: 1. 查看所有远程仓库地址 使用 git remote -v 命令,它会显示项目中配置的所有远程仓库及其对应的 URL: git remote -v输出示例: origin https://…...
