免费分享一套微信小程序外卖跑腿点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端技术实现) ,帅呆了~~

news2025/1/11 5:54:50

大家好,我是java1234_小锋老师,看到一个不错的微信小程序外卖跑腿点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端技术实现)  ,分享下哈。

项目视频演示

【免费】微信小程序外卖跑腿点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端技术实现) Java毕业设计,非常好的源码_哔哩哔哩_bilibili【免费】微信小程序外卖跑腿点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端技术实现) Java毕业设计,非常好的源码项目来自互联网,免费开源分享,严禁商业。更多毕业设源码:http://www.java1234.com/a/bysj/javaweb/, 视频播放量 547、弹幕量 0、点赞数 22、投硬币枚数 7、收藏人数 38、转发人数 4, 视频作者 java1234官方, 作者简介 公众号:java1234 微信:java9266,相关视频:【免费】微信小程序扫码点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端技术实现) Java毕业设计,非常好的源码,PyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~,【免费】Springboot+Vue个人博客系统 毕业设计 Java毕业设计,uniapp微信小程序投票系统实战课程 (SpringBoot2+vue3.2+element plus ) ( 火爆连载更新中... ),SpringBoot微信小程序电商实战项目课程 Vue3.2 Element Plus后台管理 ( 火爆连载更新中... ),2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中...,【免费】javaweb网络订餐系统毕业设计,打造前后端分离 权限系统 基于SpringBoot2+SpringSecurity+Vue3.2+Element Plus 视频教程 (火爆连载更新中..),【免费】Springboot+Vue停车场管理系统 Java毕业设计,【免费】javaweb房屋租赁管理信息系统毕业设计icon-default.png?t=N7T8https://www.bilibili.com/video/BV1r64y1w7NU/

项目介绍

自从计算机发展开始,计算机软硬件相关技术的发展速度越来越快,在信息化高速发展的今天,计算机应用技术似乎已经应用到了各个领域。

在餐饮行业,除了外卖以外就是到店里就餐,在店里就餐如果需要等待点餐的话,用户的体验度就会急剧下降,很多餐饮店也开始开发线上订餐的系统,这样的系统给用户带来了新的体验,尤其是在时间和空间上,让使用者不管身在何处,只要连上网就能够选购菜品,进行订餐。

外卖系统小程序的开发项目以Springboot框架为基础,基于B/S模式,采用Java编程语言,使用MySQL数据库,首选对外卖系统小程序的各个功能以及用户的需求做出了解释,然后根据用户线上订餐的需求,再介绍了系统的总体设计以及其详细设计,给用户提供了外卖系统小程序的总体结构的搭建方法。从而满足用户线上订餐的需求。

系统展示

部分代码

package com.yu.app.moudles.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yu.app.moudles.mapper.GoodsCategoryMapper;
import com.yu.app.moudles.mapper.GoodsMapper;
import com.yu.app.moudles.mapper.GoodsPropertyMapper;
import com.yu.common.common.constant.Const;
import com.yu.common.common.enums.GoodsPropertyCategory;
import com.yu.common.entity.app.Goods;
import com.yu.common.entity.app.GoodsCategory;
import com.yu.common.entity.app.GoodsProperty;
import com.yu.common.entity.app.vo.GoodsMenuVO;
import com.yu.common.entity.app.vo.GoodsVO;
import com.yu.common.entity.app.vo.SameCategoryPropertyVO;
import com.yu.common.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;


@Slf4j
@Service
public class GoodsServiceImpl {
    @Resource
    private GoodsCategoryMapper goodsCategoryMapper;
    @Resource
    private GoodsMapper goodsMapper;
    @Resource
    private GoodsPropertyMapper goodsPropertyMapper;
    @Resource
    private RedisService redisService;

    // TODO 本地商品菜单缓存
    private List<GoodsMenuVO> goodsMenuVOSLocalCache = new ArrayList<>();

    public List<GoodsMenuVO> getGoodsMenuDetailList() {
        Object o = redisService.get(Const.CONST_goods_menu_vo_cache);
        if (o != null && !CollectionUtils.isEmpty(goodsMenuVOSLocalCache))
            return goodsMenuVOSLocalCache;

        List<GoodsCategory> goodsCategoryList = goodsCategoryMapper.selectList(null);
        // 使用2个map去关联关系
        HashMap<String, List<Goods>> sameCategoryGoodsMap = new HashMap<>(goodsCategoryList.size());
        HashMap<String, GoodsMenuVO> goodsMenuVOMap = new HashMap<>(goodsCategoryList.size());
        for (GoodsCategory goodsCategory : goodsCategoryList) {
            sameCategoryGoodsMap.put(goodsCategory.getName(), new ArrayList<>());
            GoodsMenuVO goodsMenuVO = new GoodsMenuVO();
            goodsMenuVO.setGoodsCategoryName(goodsCategory.getName());
            goodsMenuVO.setGoodsCategoryName(goodsCategory.getName());
            goodsMenuVO.setDisplayOrder(goodsCategory.getDisplayOrder());
            goodsMenuVO.setGoodsCategoryShow(goodsCategory.getShowStatus());
            goodsMenuVOMap.put(goodsCategory.getName(), goodsMenuVO);
        }

        List<Goods> allGoods = goodsMapper.selectList(null);
        // 将所有商品分类
        for (Goods good : allGoods)
            if (sameCategoryGoodsMap.containsKey(good.getGoodsCategoryName()))
                sameCategoryGoodsMap.get(good.getGoodsCategoryName()).add(good);

        Random random = new Random(10000);
        // 关联同类商品排好序后放到到对应的类别里
        for (Map.Entry<String, GoodsMenuVO> goodsMenuVOEntry : goodsMenuVOMap.entrySet()) {
            List<Goods> sameCategoryGoodsList = sameCategoryGoodsMap.get(goodsMenuVOEntry.getKey());
            sameCategoryGoodsList.sort((o1, o2) -> o1.getDisplayOrder() - o2.getDisplayOrder());
            List<GoodsVO> goodsVos = new ArrayList<>();
            // 填充商品的属性
            for (Goods goods : sameCategoryGoodsList) {
                List<GoodsProperty> goodsPropertyList = goodsPropertyMapper.selectList(
                        new QueryWrapper<GoodsProperty>().eq("goods_id", goods.getId()));
                HashMap<String, List<GoodsProperty>> propertyMap = new HashMap<>();
                for (GoodsProperty goodsProperty : goodsPropertyList) {
                    if (propertyMap.containsKey(goodsProperty.getCategory())) {
                        propertyMap.get(goodsProperty.getCategory()).add(goodsProperty);
                    } else {
                        propertyMap.put(goodsProperty.getCategory(), new ArrayList<GoodsProperty>() {{
                            add(goodsProperty);
                        }});
                    }
                    if (goodsProperty.getIsDefault() && GoodsPropertyCategory.ENUM_size.value.equals(goodsProperty.getCategory()))
                        goods.setDefaultPrice(goodsProperty.getRebasePrice()); // 重新设置商品的默认价格
                }
                List<SameCategoryPropertyVO> goodsPropertyVos = new ArrayList<>();
                for (Map.Entry<String, List<GoodsProperty>> entry : propertyMap.entrySet()) {
                    // 属性类别->属性列表  转换成对象
                    SameCategoryPropertyVO goodsPropertyVo = new SameCategoryPropertyVO();
                    goodsPropertyVo.setCategory(entry.getKey());
                    goodsPropertyVo.setRequired(!GoodsPropertyCategory.ENUM_jia_liao.value.equalsIgnoreCase(entry.getKey())); // 除了加料其他全部必选
                    goodsPropertyVo.setPropertyList(entry.getValue());
                    goodsPropertyVos.add(goodsPropertyVo);
                }
                GoodsVO goodsVo = new GoodsVO();
                BeanUtils.copyProperties(goods, goodsVo);
                goodsVo.setGoodsPropertyVos(goodsPropertyVos);
                goodsVo.setRealPrice(goods.getDefaultPrice());
                goodsVo.setImage(goodsVo.getImage() + "?random=" + random.nextInt()); // 动态刷新小程序里的图片
                goodsVos.add(goodsVo);
            }
            goodsMenuVOEntry.getValue().setGoodsList(goodsVos);
        }

        List<GoodsMenuVO> goodsMenuVOList = new ArrayList<>(goodsMenuVOMap.values());
        // 最后对菜单进行排序
        goodsMenuVOList.sort((o1, o2) -> o1.getDisplayOrder() - o2.getDisplayOrder());
        redisService.set(Const.CONST_goods_menu_vo_cache, true, Const.CONST_one_hour); // 失效时间
        this.goodsMenuVOSLocalCache = goodsMenuVOList;
        return goodsMenuVOList;
    }
}
<template>
  <div>
    <div style="text-align: left; margin: 5px 10px">
    </div>

    <!--增加或更新的表单弹窗-->
    <el-dialog :title=formTitle :visible.sync="formDialogVisible">
      <el-form ref="form" :model="formData" :rules="rules" size="large" label-width="100px">
        <el-form-item label="姓名" prop="name">
          <el-input v-model="formData.name" placeholder="姓名"></el-input>
        </el-form-item>
        <el-form-item label="手机号" prop="phone">
          <el-input v-model="formData.phone" placeholder="手机号"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button @click="resetForm">重置</el-button>
          <el-button type="primary" @click="handelConfirm">确定</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <!--列表-->
    <div style="margin: 0px 10px;text-align: left;">
      <el-table
        :data="userAdmins"
        stripe
        :default-sort="{prop: 'name', order: 'ascending'}">
        <el-table-column prop="name" label="姓名"></el-table-column>
        <el-table-column prop="phone" label="手机号"></el-table-column>
        <el-table-column prop="wxAvatar" label="微信头像">
          <template slot-scope="scope">
            <img :src="scope.row.wxAvatar" alt="" style="width: 50px; height: 50px; border-radius: 50%;">
          </template>
        </el-table-column>
        <!-- 账号状态-->
        <el-table-column label="账号状态">
          <template slot-scope="scope">
            <el-switch
              v-model="scope.row.status"
              active-color="green"
              inactive-color="red"
              @change="(value) => commitStatusChange(value, scope.row)">
            </el-switch>
          </template>
        </el-table-column>

        <el-table-column label="操作" width="120">
          <template slot-scope="scope">
            <el-button type="text" size="mini"  @click="toEdit(scope.row)">编辑</el-button>
<!--            <el-button type="text" size="mini"  @click="toDelete(scope.row.wxOpenid)">删除</el-button>-->
          </template>
        </el-table-column>
      </el-table>
      <!--分页组件-->
      <el-row style="float: right">
        <el-pagination
          @current-change="changePageNo"
          @size-change="changePageSize"
          :current-page.sync="searchParams.pageNo"
          :page-sizes="[5, 10, 20, 30, 50, 100]"
          :page-size.sync="searchParams.pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total">
        </el-pagination>
      </el-row>

    </div>
  </div>
</template>

<script>
  import {addUserAdmin, deleteUserAdmins, getUserAdmins, updateUserAdmin} from "@/api/modules/app/userAdminApi.js";

  export default {
    name: "userAdminComponent",
    data() {
      return {
        // 查询参数
        searchParams: {
          searchParam1: null,
          pageNo: 1,
          pageSize: 10,
        },
        total: 0,
        userAdmins: [],
        formDialogVisible: false,
        formTitle: '添加',
        formData: {
          wxOpenid: null, name: null, phone: null, sex: null, wxAvatar: null, status: null
        },
        rules: {
          name: [
            {required: true, message: '姓名不能为空', trigger: 'blur'}
          ], phone: [
            {required: true, message: '手机号不能为空', trigger: 'blur'}
          ]
        }
      }
    },
    mounted() {
      this.getUserAdmins()
    },
    methods: {
      // 获取数据
      getUserAdmins() {
        let that = this;
        getUserAdmins(that.searchParams.pageNo, that.searchParams.pageSize).then(result => {
          that.userAdmins = result.data.records;
          that.total = result.data.total;
        })
      },
      // 切换页数
      changePageNo(pageNo) {
        this.searchParams.pageNo = pageNo;
        this.getUserAdmins()
      },
      // 改变页面大小
      changePageSize(pageSize) {
        this.searchParams.pageSize = pageSize;
        this.getUserAdmins()
      },
      // 清除查询参数
      clearSearchParams() {
        this.searchParams.searchParam1 = null;
      },
      // 重置表单
      resetForm() {
        // 手动重置 不然数据被绑定在toEdit时深克隆出来的对象
        this.formData = {
          wxOpenid: null, name: null, phone: null, sex: null, wxAvatar: null, status: null
        }
      },
      // 增加
      toAdd() {
        this.resetForm()
        this.formDialogVisible = true
        this.formTitle = '添加'
      },
      // 删除
      toDelete(id) {
        let that = this;
        this.$confirm("提示", "是否删除", {}).then(() => {
          deleteUserAdmins([id]).then(() => {
            this.$notify.success("删除成功");
            that.getUserAdmins();
          })
        }).catch(() => {
        })
      },
      // 编辑
      toEdit(selectedUserAdmin) {
        // 深拷贝一个对象 不然在表格显示的数据会受到印象
        this.formData = JSON.parse(JSON.stringify(selectedUserAdmin));
        this.formDialogVisible = true
        this.formTitle = '更新'
      },
      // 提交表单
      handelConfirm() {
        this.$refs['form'].validate(valid => {
          console.log(this.formTitle)
          if (!valid)
            return

          this.formDialogVisible = false;
          if (this.formTitle.startsWith('添加')) {
            addUserAdmin(this.formData).then(result => {
              this.$notify.success("添加成功");
              this.getUserAdmins()
            })
          } else if (this.formTitle.startsWith('更新')) {
            updateUserAdmin(this.formData).then(result => {
              this.$notify.success("更新成功");
              this.getUserAdmins()
            })
          }
        })
      },
      // 改变状态
      commitStatusChange(value, userAdmin) {
        this.$confirm(value === false ? '冻结?' : '激活?').then(() => {
          let obj = {
            wxOpenid: userAdmin.wxOpenid,
            status: userAdmin.status
          }
          updateUserAdmin(obj).then(() => {
            this.$notify.success(value === false ? "已冻结" : "已激活")
          }).catch(() => {
            userAdmin.status = !userAdmin.status;
          })
        }).catch(() => {
          userAdmin.status = !userAdmin.status;
        })
      },
    }
  }
</script>

源码下载

CSDN 1积分下载:https://download.csdn.net/download/caofeng891102/88785846

或者免费领取加小锋老师wx:java9266

热门推荐

免费分享一套微信小程序扫码点餐(订餐)系统(uni-app+SpringBoot后端+Vue管理端技术实现) ,帅呆了~~-CSDN博客

免费分享一套Springboot+Vue前后端分离的在线教育平台系统,挺漂亮的-CSDN博客

免费分享一套Springboot+Vue前后端分离的停车场管理系统,挺漂亮的-CSDN博客

免费分享一套Springboot+Vue前后端分离的个人博客系统,挺漂亮的_免费的开源的springboot+vue项目-CSDN博客

免费分享一套 SpringBoot + Vue + ElementUI 的人力资源管理系统,挺漂亮的_element+springboot员工工资管理-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1417882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解锁亚马逊鲲鹏系统奥秘:自动生成AI角色,随心定制养号计划

亚马逊鲲鹏系统是一款强大的软件&#xff0c;是一款可以批量注册亚马逊买家账号并能自动化养号的软件。其独特的功能和操作流程使得用户能够轻松管理多个账号&#xff0c;实现高效的运营和管理。 首先&#xff0c;该软件提供了AI智能养号功能&#xff0c;用户可以自动生成具有真…

TensorFlow2实战-系列教程4:数据增强:keras工具包/Data Augmentation

&#x1f9e1;&#x1f49b;&#x1f49a;TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 对于图像数据&#xff0c;将其进行翻转、放缩、平移、旋转操作就可以得到一组新的数据…

【JavaScript基础入门】05 JavaScript基础语法(三)

JavaScript基础语法&#xff08;三&#xff09; 目录 JavaScript基础语法&#xff08;三&#xff09;数组概述数组语法多维数组 操作数组修改数组获取数组长度数组和字符串之间的转换添加和删除数组项 Null 和 Undefined字符串连接字符串字符串转换获取字符串的长度在字符串中查…

Python之代码覆盖率框架coverage使用介绍

Python代码覆盖率工具coverage.py其实是一个第三方的包&#xff0c;同时支持Python2和Python3版本。 安装也非常简单&#xff0c;直接运行&#xff1a; pip install coverage 安装完成后&#xff0c;会在Python环境下的\Scripts下看到coverage.exe&#xff1b; 首先我们编写…

Linux(4)——Linux用户和用户组管理

Linux用户和用户组管理 插播&#xff01;插播&#xff01;插播&#xff01;亲爱的朋友们&#xff0c;我们的Cmake/Makefile/Shell这三个课程上线啦&#xff01;感兴趣的小伙伴可以去下面的链接学习哦~ 构建工具大师-CSDN程序员研修院 Linux用户和用户组管理是系统管理中非常重…

SharedPreferences卡顿分析

SP的使用及存在的问题 SharedPreferences(以下简称SP)是Android本地存储的一种方式&#xff0c;是以key-value的形式存储在/data/data/项目包名/shared_prefs/sp_name.xml里&#xff0c;SP的使用示例及源码解析参见&#xff1a;Android本地存储之SharedPreferences源码解析。以…

条件变量、线程池以及线程的GDB调试学习笔记

目录 一、条件变量 二、线程池概念和实现 三、线程的GDB调试 一、条件变量 应用场景&#xff1a;生产者消费者问题&#xff0c;是线程同步的一种手段。 必要性&#xff1a;为了实现等待某个资源&#xff0c;让线程休眠&#xff0c;提高运行效率 使用步骤&#xff1a; 初始…

【ArcGIS微课1000例】0096:dem三维块状表达(层次地形模型)

文章目录 一、DEM表达方式二、层次模型表达三、注意事项一、DEM表达方式 DEM数字高程模型的表达方式通常有以下4种: 1. 规则格网 2. 不规则三角网 3. 等高线 4. 层次地形模型 作为栅格地理数据,DEM 数据具有2.5维的特征,能够以三维表面的形式进行三维空间表达。但受其数…

幻兽帕鲁Linux私服搭建备份迁移指南

幻兽帕鲁Linux私服搭建指南 文档参考 &#xff01;&#xff01;&#xff01;说明&#xff1a;不只是幻兽帕鲁&#xff0c;后续大家想自己搭私服玩别的Steam游戏&#xff0c;大部分内容都可以做一个参考 Linux安装steamcmd Linux开服步骤 游戏配置修改 Youtobe视频教程 配…

Linux中禅道12.5一键部署安装过程笔记

1. Linux中禅道12.5一键部署安装过程笔记 文章目录 1. Linux中禅道12.5一键部署安装过程笔记1. 安装1.将安装包直接解压到/opt目录下2. Apache和Mysql常用命令3. 访问和登录禅道4. 其他 2. 访问数据库1. 网页登录数据库2. 命令行连接数据库 3. 9.2.stable版本起Linux一键安装包…

vue3前端开发,vue-router路由的配置和解释

vue3前端开发,vue-router路由的配置和解释&#xff01;为了实现本次springbootvue3.测试支付宝在线支付沙盒测试的效果&#xff0c;我们现在已经开始搭建了一个基础的vue3项目。今天这篇文章是为大家提前普及一下&#xff0c;vue-router的一些基础内容。 如图&#xff0c;我们在…

从零开始:CentOS系统下搭建DNS服务器的详细教程

前言 如果你希望在CentOS系统上建立自己的DNS服务器,那么这篇文章绝对是你不容错过的宝藏指南。我们提供了详尽的步骤和实用技巧,让你能够轻松完成搭建过程。从安装必要的软件到配置区域文件,我们都将一一为你呈现。无论你的身份是运维人员,还是程序员,抑或是对网络基础设…

C++多线程1(复习向笔记)

创建线程以及相关函数 当用thread类创建线程对象绑定函数后&#xff0c;该线程在主线程执行时就已经自动开始执行了,join起到阻塞主线程的作用 #include <iostream> #include <thread> #include <string> using namespace std; //测试函数 void printStrin…

实习日志7

1.试试pdf发票识别 1.1.添加文件类型判断 //判断文件类型 if (getFileType(imgCodeCell.getValue()) "jpg"||getFileType(imgCodeCell.getValue()) "png"||getFileType(imgCodeCell.getValue()) "jpeg"||getFileType(imgCodeCell.getValue(…

LabVIEW继电器触点接触电阻自动测试

继电器作为工业中的重要组件&#xff0c;其性能直接影响着整个生产线的可靠性和安全性。触点接触电阻是衡量继电器性能的重要参数&#xff0c;传统的测试方法效率低下且成本高昂。为了解决这些问题&#xff0c;采用LabVIEW软件&#xff0c;结合专业的硬件平台&#xff0c;实现了…

armv8 - GIC-V2 中断控制器

GIC起源 上一节中&#xff0c;粗略讲了hylicos上用的armv7上的一个通用中断控制器&#xff0c;其只支持60个中断源。但现代SoC上&#xff0c;中断系统正变得越来越复杂&#xff0c;旧的中断控制器已经无法胜任这些系统&#xff0c;主要体现在以下几点上&#xff1a; 中断源越…

(二十一)Flask之上下文管理第二篇(细细扣一遍源码)

每篇前言&#xff1a; &#x1f3c6;&#x1f3c6;作者介绍&#xff1a;【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者 &#x1f525;&#x1f525;本文已收录于Flask框架从入门到实战专栏&#xff1a;《Flask框架从入…

Linux文件管理(下)

上上篇介绍了Linux文件管理的上部分内容&#xff0c;这次继续将 Linux文件管理的剩余部分说完。内容如下。 一、查看文件内容 1、cat 命令 1.1 输出文件内容 基本语法&#xff1a; cat 文件名称主要功能&#xff1a;正序输出文件的内容。 eg&#xff1a;输出 readme.txt文…

内网安全:NTLM-Relay

目录 NTLM认证过程以及攻击面 NTLM Relay攻击 NTLM攻击总结 实验环境说明 域横向移动&#xff1a;NTLM中继攻击 攻击条件 实战一&#xff1a;NTLM中继攻击-CS转发上线MSF 原理示意图 一. CS代理转发 二. MSF架设路由 三. 适用smb_relay模块进行中继攻击 域横向移动…

Scratch:塑造孩子思维能力的魔法工具

在当今的数字化时代&#xff0c;编程已经成为一项重要的技能&#xff0c;而Scratch正是引领孩子们迈入编程世界的一扇大门。它不仅教会孩子们如何编写代码&#xff0c;更重要的是培养了孩子们的思维能力&#xff0c;为他们的成长奠定了坚实的基础。 Scratch是一款由麻省理工学…