基于 Spring Boot + Vue 的 AI 智能在线订餐系统

基于 Spring Boot + Vue 的 AI 智能在线订餐系统:从点餐闭环到语义推荐

本文介绍一个由我完成的前后端分离在线订餐项目。系统采用 Spring Boot + Vue 2 + MySQL 开发,在常规点餐业务之外,还加入了多角色后台、WebSocket 在线沟通、协同过滤推荐,以及基于阿里云百炼 Embedding 的自然语言菜品推荐。

一、项目背景

传统在线订餐系统通常只解决"查看菜品---加入购物车---提交订单"这条基础链路。为了让项目更接近真实业务,我在此基础上补充了用户、商家和管理员三类角色,并将优惠券、积分、余额、资讯、评价、收藏、实时聊天等模块串联起来。

项目的另一个重点是智能推荐。用户不仅可以按照分类、价格、点击量和收藏量筛选菜品,还可以直接输入自然语言需求,例如:

text 复制代码
想吃清淡一点的素菜,最好烹饪时间不要太长
想找适合两个人吃的海鲜自助
推荐一些香辣口味的中式菜

后端会把用户描述转换为向量,与菜品向量计算语义相似度,再返回匹配度最高的菜品。

二、系统效果展示

1. 用户端首页

首页使用轮播图和"关于我们"区域展示平台信息,顶部导航可以进入菜品、美食资讯、购物车、在线客服和个人中心。

2. 菜品检索与 AI 推荐

菜品列表支持名称、价格区间、菜品分类等条件查询,同时可以按照价格、点击量、收藏数排序。页面右侧是 AI 推荐面板,输入需求后即可获取语义匹配结果。

3. 菜品详情

详情页展示菜品图片、价格、积分、库存、口味、烹饪时长、所属商家等信息,并提供收藏、加入购物车、立即购买、积分兑换、联系商家和富文本评价等功能。

4. 实时在线沟通

用户可以在菜品详情页联系商家,发送文字、表情和商品信息。通信层使用 WebSocket,实现消息的实时推送。

5. 购物车与订单确认

购物车支持勾选商品、修改数量、移除商品和金额汇总。进入结算页后,可以选择收货地址、确认商品清单、填写订单备注,并使用余额或积分完成业务流程。

6. 美食资讯与个人中心

资讯模块包含分类筛选、关键字搜索、热门排行、浏览、点赞和收藏等功能。个人中心集中管理资料、密码、聊天记录、优惠券、订单、地址和收藏。

7. 管理员端与商家端

管理员可以维护用户、商家、菜品分类、菜品、优惠券、充值记录、轮播图、资讯、订单和系统信息;商家则主要维护自己的菜品、优惠券、聊天和订单。

系统登录页支持管理员和商家角色选择,商家也可以通过入口完成注册。

三、技术选型

层次 技术 作用
用户前台 Vue 2.6、Element UI、Vue Router、Vuex 页面组件、路由和状态管理
管理后台 Vue 2.6、Element UI 管理员与商家业务界面
网络请求 Axios 调用后端接口
内容组件 Swiper、Vue Quill Editor 轮播图与富文本编辑
后端框架 Spring Boot 2.2.2 Web 服务与业务组织
持久层 MyBatis、MyBatis-Plus 2.3 数据访问、分页和条件查询
权限认证 Apache Shiro 登录与接口权限控制
实时通信 WebSocket 用户与商家实时聊天
数据库 MySQL 保存业务数据
AI 能力 DashScope SDK、text-embedding-v4 文本向量生成与语义推荐
开发环境 JDK 8、Maven、Node.js、npm 项目构建与运行

四、系统架构

项目采用典型的前后端分离结构,用户前台与后台管理端共用一套 Spring Boot 接口。
#mermaid-svg-rn6EGUe3HbH8n2IY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rn6EGUe3HbH8n2IY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rn6EGUe3HbH8n2IY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rn6EGUe3HbH8n2IY .error-icon{fill:#552222;}#mermaid-svg-rn6EGUe3HbH8n2IY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rn6EGUe3HbH8n2IY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rn6EGUe3HbH8n2IY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rn6EGUe3HbH8n2IY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rn6EGUe3HbH8n2IY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rn6EGUe3HbH8n2IY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rn6EGUe3HbH8n2IY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rn6EGUe3HbH8n2IY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rn6EGUe3HbH8n2IY .marker.cross{stroke:#333333;}#mermaid-svg-rn6EGUe3HbH8n2IY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rn6EGUe3HbH8n2IY p{margin:0;}#mermaid-svg-rn6EGUe3HbH8n2IY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rn6EGUe3HbH8n2IY .cluster-label text{fill:#333;}#mermaid-svg-rn6EGUe3HbH8n2IY .cluster-label span{color:#333;}#mermaid-svg-rn6EGUe3HbH8n2IY .cluster-label span p{background-color:transparent;}#mermaid-svg-rn6EGUe3HbH8n2IY .label text,#mermaid-svg-rn6EGUe3HbH8n2IY span{fill:#333;color:#333;}#mermaid-svg-rn6EGUe3HbH8n2IY .node rect,#mermaid-svg-rn6EGUe3HbH8n2IY .node circle,#mermaid-svg-rn6EGUe3HbH8n2IY .node ellipse,#mermaid-svg-rn6EGUe3HbH8n2IY .node polygon,#mermaid-svg-rn6EGUe3HbH8n2IY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rn6EGUe3HbH8n2IY .rough-node .label text,#mermaid-svg-rn6EGUe3HbH8n2IY .node .label text,#mermaid-svg-rn6EGUe3HbH8n2IY .image-shape .label,#mermaid-svg-rn6EGUe3HbH8n2IY .icon-shape .label{text-anchor:middle;}#mermaid-svg-rn6EGUe3HbH8n2IY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rn6EGUe3HbH8n2IY .rough-node .label,#mermaid-svg-rn6EGUe3HbH8n2IY .node .label,#mermaid-svg-rn6EGUe3HbH8n2IY .image-shape .label,#mermaid-svg-rn6EGUe3HbH8n2IY .icon-shape .label{text-align:center;}#mermaid-svg-rn6EGUe3HbH8n2IY .node.clickable{cursor:pointer;}#mermaid-svg-rn6EGUe3HbH8n2IY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rn6EGUe3HbH8n2IY .arrowheadPath{fill:#333333;}#mermaid-svg-rn6EGUe3HbH8n2IY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rn6EGUe3HbH8n2IY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rn6EGUe3HbH8n2IY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rn6EGUe3HbH8n2IY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rn6EGUe3HbH8n2IY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rn6EGUe3HbH8n2IY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rn6EGUe3HbH8n2IY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rn6EGUe3HbH8n2IY .cluster text{fill:#333;}#mermaid-svg-rn6EGUe3HbH8n2IY .cluster span{color:#333;}#mermaid-svg-rn6EGUe3HbH8n2IY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rn6EGUe3HbH8n2IY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rn6EGUe3HbH8n2IY rect.text{fill:none;stroke-width:0;}#mermaid-svg-rn6EGUe3HbH8n2IY .icon-shape,#mermaid-svg-rn6EGUe3HbH8n2IY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rn6EGUe3HbH8n2IY .icon-shape p,#mermaid-svg-rn6EGUe3HbH8n2IY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rn6EGUe3HbH8n2IY .icon-shape .label rect,#mermaid-svg-rn6EGUe3HbH8n2IY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rn6EGUe3HbH8n2IY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rn6EGUe3HbH8n2IY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rn6EGUe3HbH8n2IY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 实时消息
实时消息
用户前台 Vue
Spring Boot API
商家/管理员后台 Vue
WebSocket
业务 Service
MyBatis-Plus
MySQL
DashScope Embedding
向量相似度排序 Top-K

后端按照 Controller、Service、DAO、Entity 分层组织。Controller 负责接收请求,Service 处理业务逻辑,DAO 与 Mapper 完成数据库访问,最终以统一响应对象返回给前端。

五、角色与功能设计

1. 普通用户

  • 注册、登录、资料维护和密码修改;
  • 按名称、分类、价格搜索和排序菜品;
  • 查看菜品详情,收藏、评价、点赞或点踩评论;
  • 领取优惠券,管理个人优惠券;
  • 加入购物车、确认地址、创建订单和支付;
  • 使用账户余额或积分,查看充值记录;
  • 查看订单状态和历史订单;
  • 与商家在线聊天;
  • 浏览、点赞和收藏美食资讯;
  • 使用 AI 自然语言推荐。

2. 商家

  • 注册并等待审核;
  • 维护店铺资料和菜品信息;
  • 管理菜品上下架、库存、价格与积分;
  • 发布和维护优惠券;
  • 接收用户消息并实时沟通;
  • 处理订单及查看不同状态的订单。

3. 管理员

  • 管理用户与商家账号;
  • 审核商家和业务数据;
  • 管理菜品分类、菜品、评价和优惠券;
  • 管理订单、充值记录和聊天信息;
  • 维护轮播图、美食资讯、资讯分类、关于我们等内容。

六、核心业务流程

一笔订单的主要流程如下:
#mermaid-svg-C5hLLFHzV5aeAUUB{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-C5hLLFHzV5aeAUUB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-C5hLLFHzV5aeAUUB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-C5hLLFHzV5aeAUUB .error-icon{fill:#552222;}#mermaid-svg-C5hLLFHzV5aeAUUB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-C5hLLFHzV5aeAUUB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-C5hLLFHzV5aeAUUB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-C5hLLFHzV5aeAUUB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-C5hLLFHzV5aeAUUB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-C5hLLFHzV5aeAUUB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-C5hLLFHzV5aeAUUB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-C5hLLFHzV5aeAUUB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-C5hLLFHzV5aeAUUB .marker.cross{stroke:#333333;}#mermaid-svg-C5hLLFHzV5aeAUUB svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-C5hLLFHzV5aeAUUB p{margin:0;}#mermaid-svg-C5hLLFHzV5aeAUUB .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-C5hLLFHzV5aeAUUB .cluster-label text{fill:#333;}#mermaid-svg-C5hLLFHzV5aeAUUB .cluster-label span{color:#333;}#mermaid-svg-C5hLLFHzV5aeAUUB .cluster-label span p{background-color:transparent;}#mermaid-svg-C5hLLFHzV5aeAUUB .label text,#mermaid-svg-C5hLLFHzV5aeAUUB span{fill:#333;color:#333;}#mermaid-svg-C5hLLFHzV5aeAUUB .node rect,#mermaid-svg-C5hLLFHzV5aeAUUB .node circle,#mermaid-svg-C5hLLFHzV5aeAUUB .node ellipse,#mermaid-svg-C5hLLFHzV5aeAUUB .node polygon,#mermaid-svg-C5hLLFHzV5aeAUUB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-C5hLLFHzV5aeAUUB .rough-node .label text,#mermaid-svg-C5hLLFHzV5aeAUUB .node .label text,#mermaid-svg-C5hLLFHzV5aeAUUB .image-shape .label,#mermaid-svg-C5hLLFHzV5aeAUUB .icon-shape .label{text-anchor:middle;}#mermaid-svg-C5hLLFHzV5aeAUUB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-C5hLLFHzV5aeAUUB .rough-node .label,#mermaid-svg-C5hLLFHzV5aeAUUB .node .label,#mermaid-svg-C5hLLFHzV5aeAUUB .image-shape .label,#mermaid-svg-C5hLLFHzV5aeAUUB .icon-shape .label{text-align:center;}#mermaid-svg-C5hLLFHzV5aeAUUB .node.clickable{cursor:pointer;}#mermaid-svg-C5hLLFHzV5aeAUUB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-C5hLLFHzV5aeAUUB .arrowheadPath{fill:#333333;}#mermaid-svg-C5hLLFHzV5aeAUUB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-C5hLLFHzV5aeAUUB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-C5hLLFHzV5aeAUUB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-C5hLLFHzV5aeAUUB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-C5hLLFHzV5aeAUUB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-C5hLLFHzV5aeAUUB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-C5hLLFHzV5aeAUUB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-C5hLLFHzV5aeAUUB .cluster text{fill:#333;}#mermaid-svg-C5hLLFHzV5aeAUUB .cluster span{color:#333;}#mermaid-svg-C5hLLFHzV5aeAUUB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-C5hLLFHzV5aeAUUB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-C5hLLFHzV5aeAUUB rect.text{fill:none;stroke-width:0;}#mermaid-svg-C5hLLFHzV5aeAUUB .icon-shape,#mermaid-svg-C5hLLFHzV5aeAUUB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-C5hLLFHzV5aeAUUB .icon-shape p,#mermaid-svg-C5hLLFHzV5aeAUUB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-C5hLLFHzV5aeAUUB .icon-shape .label rect,#mermaid-svg-C5hLLFHzV5aeAUUB .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-C5hLLFHzV5aeAUUB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-C5hLLFHzV5aeAUUB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-C5hLLFHzV5aeAUUB :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 加入购物车
立即购买
浏览/搜索菜品
查看详情
购买方式
购物车结算
确认订单
选择收货地址
优惠券/积分/余额处理
创建订单
商家处理
订单完成

订单数据不仅记录订单号、商品、数量、原价和实付金额,还关联用户、商家、地址、联系方式、优惠券和订单状态,使用户端查询与商家端处理能够使用同一套数据模型。

七、AI 推荐的实现思路

1. 菜品向量初始化

系统启动后会异步读取已上架菜品,将菜品名称、分类、口味、烹饪时长、主要食材和菜品介绍拼接为文本,再分批调用 text-embedding-v4 生成向量。每批最多处理 10 条,并将结果保存到菜品表的 embedding 字段中。

示意文本如下:

text 复制代码
菜品名称:宫保鸡丁,分类:中式菜肴,口味:麻辣,
烹饪时长:25分钟,食材主料:鸡胸肉、花生米,
菜品介绍:经典川味,鸡肉滑嫩,花生酥脆,麻辣鲜香

向量初始化任务采用异步线程执行,不阻塞 Spring Boot 主启动流程。

2. 用户查询向量化

用户提交自然语言需求后,请求会进入 /dashscope/chat 接口。后端先筛选"已上架且存在向量"的菜品,再为用户问题生成查询向量。

核心过程可以概括为:

java 复制代码
List<CaipinxinxiEntity> candidates = dishService.selectAllByQuery(wrapper);
float[] queryVector = dashScopeService.getQueryEmbedding(question);
List<CaipinxinxiEntity> result =
        dashScopeService.getEmbeddingTopk(candidates, queryVector, 5);

3. 余弦相似度与 Top-K

系统逐一计算查询向量和候选菜品向量的余弦相似度:

text 复制代码
similarity(A, B) = (A · B) / (||A|| × ||B||)

相似度越高,表示菜品描述与用户需求在语义上越接近。计算完成后按得分降序排序,取前 5 个结果返回前端。

这种方式比单纯的 LIKE 查询更灵活。例如用户输入"想吃暖胃又不油腻的东西",即使菜品名称中没有这些字,模型仍可根据菜品描述和食材语义找到合适结果。

4. 基于订单的协同过滤

除了主动输入需求,项目还实现了基于用户的协同过滤:根据历史订单构建"用户---菜品"偏好矩阵,计算用户之间的相似度,再从相似用户购买过、当前用户尚未购买的菜品中生成推荐。

当推荐结果不足时,接口会使用其他已上架菜品补齐列表,从而兼顾个性化推荐与冷启动场景。

因此,系统中存在两类互补的推荐能力:

  • 语义推荐:理解用户当下输入的自然语言需求;
  • 协同推荐:利用历史订单发现相似用户的消费偏好。

八、WebSocket 实时聊天

后端通过 @ServerEndpoint("/ws") 提供 WebSocket 连接,并使用线程安全的 ConcurrentHashMap 保存在线客户端。连接参数中包含发送方与接收方 ID,消息到达服务端后会被推送给指定用户;同时保留 ping/pong 心跳处理。

java 复制代码
@OnMessage
public void onMessage(String message) {
    if ("ping".equals(message)) {
        sendMessage("pong", fromUserId, toUserId);
    } else {
        sendMessage(message, fromUserId, toUserId);
    }
}

业务消息还会写入聊天相关数据表,既保证在线时的实时体验,也支持用户之后查看历史聊天记录。

九、数据库设计

项目数据库包含 22 张主要业务表,核心表如下:

数据表 说明
yonghu 用户账号、资料、积分与余额
shangjia 商家账号、门店资料、审核状态与余额
users 管理员账号
caipinfenlei 菜品分类
caipinxinxi 菜品详情、库存、价格、积分、上下架和向量
cart 购物车
orders 订单主数据与状态
address 用户收货地址
coupon / mycoupon 优惠券及用户领券记录
chargerecord 充值记录
storeup 收藏记录
discusscaipinxinxi 菜品评论、点赞与点踩
chat / chatmessage / friend 客服与用户、商家聊天关系
news / newstype 美食资讯及分类
config 轮播图配置
aboutus / systemintro 平台介绍信息
token 登录令牌

十、项目目录

text 复制代码
onlineorder-serve-master
├─ db                         # MySQL 脚本
├─ upload                     # 示例上传资源
├─ src/main/java/com
│  ├─ controller             # 接口控制器
│  ├─ service                # 业务服务
│  ├─ dao                    # 数据访问层
│  ├─ entity                 # 实体、VO、View、Model
│  ├─ dashscope              # Embedding 与语义推荐
│  ├─ ws                     # WebSocket
│  ├─ config                 # 框架配置
│  └─ utils                  # 工具与协同过滤算法
└─ src/main/resources
   ├─ mapper                 # MyBatis XML
   └─ application.yml        # 服务配置

onlineorder-web-master
├─ front                     # 用户前台,默认端口 8082
└─ admin                     # 管理员/商家后台,默认端口 8081

十一、本地运行

1. 环境准备

建议准备以下环境:

  • JDK 8;
  • Maven 3.6 或更高版本;
  • MySQL 5.7/8.0;
  • Node.js 12/14(项目使用较早版本的 node-sass,使用新版本 Node.js 时可能需要调整依赖);
  • npm。

2. 初始化数据库

创建数据库并导入项目 SQL:

sql 复制代码
CREATE DATABASE db_bs2026_onlineorder
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;

随后导入:

text 复制代码
onlineorder-serve-master/db/db_bs2026_onlineorder.sql

3. 修改后端配置

编辑 src/main/resources/application.yml

yaml 复制代码
server:
  port: 8080
  servlet:
    context-path: /onlineorder

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/db_bs2026_onlineorder?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
    username: root
    password: 你的数据库密码

dashscope:
  api_key: 你的阿里云百炼API-Key
  model: text-embedding-v4

不要把真实 API Key 提交到公开仓库。更推荐通过环境变量或外部配置文件注入密钥。

4. 启动后端

bash 复制代码
cd onlineorder-serve-master
mvn spring-boot:run

后端默认地址:http://localhost:8080/onlineorder

5. 启动用户前台

bash 复制代码
cd onlineorder-web-master/front
npm install
npm run serve

用户前台默认地址:http://localhost:8082

6. 启动管理后台

bash 复制代码
cd onlineorder-web-master/admin
npm install
npm run serve

管理后台默认地址:http://localhost:8081

SQL 示例数据中包含本地体验账号:

角色 账号 密码
管理员 admin admin
用户 user001 123456
商家 shangjia010 123456

这些账号仅用于本地演示。部署到公网前必须删除示例账号、修改默认密码,并对密码进行不可逆哈希存储。

十二、项目亮点总结

这个项目并非只有基本的增删改查,而是围绕订餐场景完成了多个业务模块的组合:

  1. 用户、商家、管理员三端角色和差异化菜单;
  2. 从菜品检索、购物车到订单处理的完整业务闭环;
  3. 优惠券、积分、余额、充值等营销与账户能力;
  4. WebSocket 用户---商家实时聊天;
  5. 富文本评价、点赞、点踩、收藏和资讯互动;
  6. 基于历史订单的用户协同过滤推荐;
  7. 基于 DashScope Embedding 的自然语言语义推荐;
  8. 异步批量生成菜品向量,降低初始化过程对启动的影响。

在开发过程中,我对前后端分离项目的权限设计、订单状态流转、关系型数据库建模、实时通信和 AI 能力接入都有了更完整的实践。后续还可以继续加入 Redis 缓存、消息队列、支付沙箱、配送轨迹、Elasticsearch 搜索,以及向量数据库等能力,让系统进一步向生产级架构演进。

如果这篇文章对你有帮助,欢迎点赞、收藏和交流。


推荐标签: Spring BootVueMySQLJavaWebSocket人工智能推荐系统毕业设计

相关推荐
mmsx1 小时前
我明明调用了 zoomToBounds,地图却总是停在别处?延迟加到 5 秒也没用,真相只有一个
android·人工智能·bug·地图
PNP机器人1 小时前
康奈尔联合Kinova研发自适应触感护理机械臂
人工智能·力控机器人
六年码农1 小时前
2026最新开源 屏译ScreenTranslator 0.4.4 开源 全屏实时翻译教程
运维·人工智能·flutter·开源
gb42152871 小时前
智能客服或AI对话系统里的召回
人工智能
课件帮1 小时前
PPT动画与数字人讲解如何精准同步?2026年微课制作技术新趋势
人工智能·语音识别
向日的葵0061 小时前
项目博客-AI旅行规划平台
人工智能
软件开发JR1 小时前
基于Web的足球青训俱乐部管理后台系统的设计与开发
java·前端·spring boot·毕业设计
小马9261 小时前
智能体时代的两块基石:DeepSeek Harness 开源与“认知基础设施“数据库
数据库·人工智能·开源·agent
Lumistory1 小时前
照明工程落地效果评判与改造的实践参考
大数据·人工智能·光照贴图