基于微信小程序的美食点餐订餐系统

文章目录

    • 1. 项目概述
    • 2. 项目思维导图
    • 3. 系统架构特点
    • 4. 核心模块实现代码
        • 1. 登录注册
        • 2. 首页模块实现
        • 4. 分类模块实现
        • 5. 购物车模块实现
        • 6. 订单模块实现
    • 5. 注意事项
    • 6. 项目效果截图
    • 7. 关于作者其它项目视频教程介绍

1. 项目概述

在移动互联网时代,餐饮行业数字化转型已成为必然趋势。今天我想分享一个基于小程序的美食点餐/订餐系统的设计与实现,该系统包含用户模块、首页模块、分类模块、购物车模块和个人中心等核心功能模块。

2. 项目思维导图

在这里插入图片描述

3. 系统架构特点

  • 纯前端实现:不依赖服务器,所有数据存储在本地
  • 基于微信小程序API数据存储:主要使用wx.setStorageSync/wx.getStorageSync
  • 数据持久化:关闭小程序后数据不会丢失

4. 核心模块实现代码

1. 登录注册

//用户注册
onRegisterHandle(){if(this.data.username==='' || this.data.password ===''){wx.showToast({title: '注册信息不能为空',icon :'error'})return}let users =wx.getStorageSync('users') ||[]if(users.some(item => item.username === this.data.username)){wx.showToast({title: '用户名已存在',icon: 'error'})return}let user ={username: this.data.username,password: this.data.password}users.push(user)wx.setStorageSync("users",users)wx.showToast({title: '注册成功',icon :'success'})setTimeout(() => {wx.navigateBack()},500)}//用户登录
onLoginHandle(options) {if (this.data.username === '' || this.data.password === '') {wx.showToast({title: '登录信息不能为空',icon: 'error'})return}let users = wx.getStorageSync('users') || []if (users.some(item => item.username === this.data.username && item.password === this.data.password)) {wx.showToast({title: '登录成功',icon: 'success'})let user = {username: this.data.username,password: this.data.password}//保存当前用户登录信息wx.setStorageSync("user", user)setTimeout(() => {wx.navigateBack()}, 500)} else {wx.showToast({title: '用户名或密码错误',icon: 'error'})}},
2. 首页模块实现
//导入数据
import { bannerList, startList, produtList } from '../../utils/dataservice'Page({data: {bannerList: [],startList: [],produtList: []},onLoad() {this.setData({//加载轮播图数据bannerList: bannerList,//加载精刚区数据startList: startList,//加载首页商品列表数据produtList: produtList})},/*** 列表点击事件*/onItemClickHandle(options) {const item = encodeURIComponent(JSON.stringify(options.currentTarget.dataset.item))wx.navigateTo({url: `/pages/detail/detail?productInfo=${item}`,})},
})
4. 分类模块实现
// pages/category/category.js//导入数据
import getCategoryList from '../../utils/dataservice';
Page({/*** 页面的初始数据*/data: {categoryList: [{ "category_id": 0, "category_name": "新品推荐" },{ "category_id": 1, "category_name": "招牌爆款" },{ "category_id": 2, "category_name": "主厨推荐" },{ "category_id": 3, "category_name": "开胃前菜" },{ "category_id": 4, "category_name": "美味主食" },{ "category_id": 5, "category_name": "美味甜品" },{ "category_id": 6, "category_name": "鲜榨果品" },{ "category_id": 7, "category_name": "蔬菜沙拉" },{ "category_id": 8, "category_name": "轻食小吃" },],productList: [],selectedIndex: 0},/*** 生命周期函数--监听页面加载*/onLoad(options) {//获取商品分类列表数据this.getCategoryListData(this.data.selectedIndex)},/*** 商品分类选择*/onSelectedHandle(options) {this.setData({selectedIndex: options.currentTarget.dataset.item.category_id})//获取商品分类列表数据this.getCategoryListData(this.data.selectedIndex)},/*** 获取商品分类列表数据*/getCategoryListData(selectedIndex) {const result = getCategoryList(selectedIndex)this.setData({productList: result})},/*** 列表点击事件*/onItemClickHandle(options) {const item = encodeURIComponent(JSON.stringify(options.currentTarget.dataset.item))wx.navigateTo({url: `/pages/detail/detail?productInfo=${item}`,})},})
5. 购物车模块实现
// pages/cart/cart.js
Page({/*** 页面的初始数据*/data: {carts: [],totalPrice: 0},/*** 生命周期函数--监听页面加载*/onShow(options) {this.loadCartData();},/*** 加载购物车数据*/loadCartData() {const user = wx.getStorageSync('user') || {};const allCarts = wx.getStorageSync('carts') || [];// 提取当前用户的数据const userCart = allCarts.find(cart => cart.username === user.username) || { items: [] };this.setData({carts: userCart.items,totalPrice: this.calculateTotalPrice(userCart.items)});},// 计算总价方法  calculateTotalPrice(cartItems) {// 使用 reduce 方法累加每个商品的总价return cartItems.reduce((total, item) => {return total + (item.price * item.count);}, 0).toFixed(2) * 100; // 保留两位小数},/*** 加购*/plus(options) {const user = wx.getStorageSync('user') || {};const item = options.currentTarget.dataset.item;// 1. 获取所有用户的购物车数据const allCarts = wx.getStorageSync('carts') || [];// 2. 找到当前用户的购物车(没有则初始化)let userCart = allCarts.find(cart => cart.username === user.username);if (!userCart) {userCart = { username: user.username, items: [] };allCarts.push(userCart);}// 3. 修改当前用户的购物车商品数量const updatedItems = userCart.items.map(cartItem => {return cartItem.product_id === item.product_id ? { ...cartItem, count: cartItem.count + 1 } : cartItem;});// 4. 更新数据userCart.items = updatedItems;wx.setStorageSync('carts', allCarts);// 5. 更新页面显示(只展示当前用户的数据)this.setData({carts: updatedItems,totalPrice: this.calculateTotalPrice(updatedItems)});},// 更新购物车数据updateCart(updatedCart) {wx.setStorageSync('carts', updatedCart);this.setData({carts: updatedCart,totalPrice: this.calculateTotalPrice(updatedCart)});},/*** 减购*/minus(options) {// 获取当前点击商品数据const product = options.currentTarget.dataset.item;const allCarts = wx.getStorageSync('carts') || [];const user = wx.getStorageSync('user');// 1. 找到当前用户的购物车const userCart = allCarts.find(cart => cart.username === user.username);if (!userCart) return; // 无购物车则退出// 2. 找到商品在购物车中的索引const itemIndex = userCart.items.findIndex(item => item.product_id === product.product_id);if (itemIndex === -1) return; // 商品不存在则退出// 3. 减少数量userCart.items[itemIndex].count -= 1;// 4. 保存数据并更新 UIwx.setStorageSync('carts', allCarts);this.setData({carts: userCart.items || [], // 确保空购物车时传空数组totalPrice: this.calculateTotalPrice(userCart.items || [])});},/*** 删除商品*/removeItemHandle(options) {// 获取要删除的商品const product = options.currentTarget.dataset.item;wx.showModal({title: '温馨提示',content: '确定要从购物车移除该商品吗?',complete: (res) => {if (res.confirm) {const user = wx.getStorageSync('user');const allCarts = wx.getStorageSync('carts') || [];// 1. 找到当前用户的购物车const userCartIndex = allCarts.findIndex(cart => cart.username === user.username);if (userCartIndex === -1) return; // 用户购物车不存在则退出// 2. 从该用户的 items 中移除目标商品const updatedItems = allCarts[userCartIndex].items.filter(item => item.product_id !== product.product_id);// 3. 更新数据allCarts[userCartIndex].items = updatedItems;// 4. 保存数据并更新 UIwx.setStorageSync('carts', allCarts);this.setData({carts: updatedItems, // 更新当前页面的购物车列表totalPrice: this.calculateTotalPrice(updatedItems)});}}})},/*** 提交订单*/onSubmit(options) {const user = wx.getStorageSync('user')if (!user) {wx.showModal({title: '温馨提示',content: '系统检测到您未登录,请先登录',complete: (res) => {if (res.confirm) {wx.navigateTo({url: '/pages/login/login',})}}})return;}if (this.data.totalPrice === 0) {wx.showToast({title: '购物车空空如也,去看看吧~',icon: 'error',success: () => {setTimeout(() => {wx.switchTab({url: '/pages/category/category',})}, 500)}})return;}wx.showModal({title: '温馨提示',content: '您确定下单吗?',complete: (res) => {if (res.confirm) {// 1. 获取当前用户的购物车数据const allCarts = wx.getStorageSync('carts') || [];const userCartIndex = allCarts.findIndex(cart => cart.username === user.username);if (userCartIndex === -1 || allCarts[userCartIndex].items.length === 0) {wx.showToast({ title: '购物车为空', icon: 'error' });return;}const userCartItems = allCarts[userCartIndex].items;// 2. 生成订单(添加订单时间、状态等元信息)const newOrder = {order_id: Date.now().toString(), // 简单生成订单ID(实际项目建议更严谨的方式)username: user.username,items: userCartItems,create_time: new Date().toLocaleString(),status: '支付成功'}// 3. 保存订单(多用户订单隔离)const allOrders = wx.getStorageSync('orders') || [];allOrders.push(newOrder); // 将新订单追加到订单列表wx.setStorageSync('orders', allOrders);// 4. 清空当前用户的购物车(不影响其他用户)allCarts[userCartIndex].items = []; // 清空items而非删除用户条目,保留用户购物车结构wx.setStorageSync('carts', allCarts);// 5. 更新页面状态this.setData({carts: [],totalPrice: 0});wx.showToast({title: '下单成功',})}}})}
})
6. 订单模块实现
// pages/order/order.js
Page({/*** 页面的初始数据*/data: {orderList: []},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.loadUserOrders();},/*** 订单加载方法中预处理数据*/loadUserOrders() {const { username } = wx.getStorageSync('user');// 1. 获取所有订单(假设数据结构为订单数组,每个订单包含items)const result = wx.getStorageSync('orders') || [];//2. 过滤出当前用户的订单,并平铺itemsconst userOrder = result.filter(item => item.username === username).flatMap(order => {// 为每个商品添加订单元信息(可选)return order.items.map(item => ({...item,order_id: order.order_id,     // 关联订单IDorder_status: order.status,    // 订单状态create_time: order.create_time, // 下单时间unique_id: `${order.order_id}${item.product_id}`}));})// 3. 更新数据this.setData({orderList: userOrder})},/*** 删除订单*/removeOrderHandle(options) {const orderInfo = options.currentTarget.dataset.item;const user = wx.getStorageSync('user')wx.showModal({title: '温馨提示',content: '确定要从订单中删除该商品吗?',complete: (res) => {if (res.confirm) {// 1. 获取所有订单数据const allOrders = wx.getStorageSync('orders') || [];// 2. 遍历查找目标商品const updatedOrders = allOrders.map(order => {// 2.1 检查订单归属if (order.username !== user.username) {return order;}// 2.2 过滤掉目标商品const updatedItems = order.items.filter(item => `${order.order_id}${item.product_id}` !== orderInfo.unique_id)// 2.3  updatedItems 可能返回空items的订单,所有加判空处理return updatedItems.length > 0 ? { ...order, items: updatedItems } : null;}).filter(Boolean) // 移除null(即空订单)console.log(updatedOrders)// 4. 保存数据wx.setStorageSync('orders', updatedOrders);// 5. 重新加载this.loadUserOrders();wx.showToast({title: '删除成功',})}}})}
})

5. 注意事项

  1. 存储限制:wx.setStorageSync有10MB大小限制
  2. 多设备同步:本地存储无法实现多设备同步
  3. 数据持久性:用户清理缓存会丢失所有数据

这个纯前端实现方案适合作为学习项目或个人小店使用,如果要开发商业应用,建议还是使用后端数据库存储数据。

6. 项目效果截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7. 关于作者其它项目视频教程介绍

本人在b站录制的一些视频教程项目,免费供大家学习

  1. Android新闻资讯app实战:https://www.bilibili.com/video/BV1CA1vYoEad/?vd_source=984bb03f768809c7d33f20179343d8c8
  2. Androidstudio开发购物商城实战:https://www.bilibili.com/video/BV1PjHfeXE8U/?vd_source=984bb03f768809c7d33f20179343d8c8
  3. Android开发备忘录记事本实战:https://www.bilibili.com/video/BV1FJ4m1u76G?vd_source=984bb03f768809c7d33f20179343d8c8&spm_id_from=333.788.videopod.sections
  4. Androidstudio底部导航栏实现:https://www.bilibili.com/video/BV1XB4y1d7et/?spm_id_from=333.337.search-card.all.click&vd_source=984bb03f768809c7d33f20179343d8c8
  5. Android使用TabLayout+ViewPager2实现左右滑动切换:https://www.bilibili.com/video/BV1Mz4y1c7eX/?spm_id_from=333.337.search-card.all.click&vd_source=984bb03f768809c7d33f20179343d8c8

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

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

相关文章

[neo4j]介绍4个开源的知识图谱项目

项目主要介绍几个开源项目: QASystemOnMedicalKG:医疗知识图谱问答 https://github.com/liuhuanyong/QASystemOnMedicalKG Agriculture_KnowledgeGraph:农业知识图谱 Financial-Knowledge-Graphs:小型金融知识图谱 stock-know…

20倍光学镜头怎么实现20+20倍数实现

1. 硬件选择 球机摄像头 选择40倍光学变焦的摄像头 :确保摄像头具有足够的变焦能力,同时考虑摄像头的分辨率、帧率、夜视功能等。 内置云台 :许多高端摄像头已经内置了云台功能,如果是这样,可以简化机械设计和电机控制…

Axios 在 Vue3 项目中的使用:从安装到组件中的使用

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…

【Python打卡Day50】预训练模型与CBAM注意力@浙大疏锦行

现在我们思考下,是否可以对于预训练模型增加模块来优化其效果,这里我们会遇到一个问题: 预训练模型的结构和权重是固定的,如果修改其中的模型结构,是否会大幅影响其性能。其次是训练的时候如何训练才可以更好的避免破坏原有的特征…

ONLYOFFICE Jira 集成应用程序 4.0.0 发布,含新的文件格式支持等多个重大更新!

ONLYOFFICE 与 Jira 集成的重大更新现已发布!使用 ONLYOFFICE Docs 在 Jira Software 中处理各种办公文档,从 4.0.0 版本开始,ONLYOFFICE 连接器允许您编辑 PDF 文件和表单、直接从编辑器创建新文件、可视化用户头像、在 Jira 平台内处理新文…

安装区块链相关Geth(基于CentOS7)

注:由于版本冲突问题,请严格按如下介绍版本进行安装 安装所需资料:通过网盘分享的文件:区块链_CSDN 链接: https://pan.baidu.com/s/1dn5xcLtwwFy90xhOWKiWyA?pwdzgzs 提取码: zgzs --来自百度网盘超级会员v6的分享 一、安装运…

系统分析师——计算机系统基础

系统分析师——计算机系统基础 引言 作为系统分析师学习的第一节课,计算机系统基础部分构建了整个知识体系的核心框架。本文将围绕计算机系统的层次结构、硬件组成、软件分类以及关键技术点进行详细总结,为后续深入学习奠定基础。 本节学习内容如下图&…

JS常用设计模式汇总

1、基于类的单例模式 // PageManager.js class PageManager {constructor(config) {if (!PageManager.instance) {this.config config;this.initialized false;PageManager.instance this;this.init();}return PageManager.instance;}init() {if (this.initialized) return…

迈向软件开发 T 型人才之路:构建多元能力体系

在软件开发的广袤天地里,T 型人才备受瞩目。这类人才犹如具备强大能量的 “多面手”,既有深入专精的技术能力,又有广泛多元的知识与技能储备,能够从容应对复杂多变的项目需求,引领行业创新发展。于当今社会而言&#x…

SALMONN-omni论文阅读

论文链接 项目链接 名词理解: backchanneling: 指的是听话人在不打断说话人的情况下,用简短的语气词或动作表示“我在听”“我理解了”的反馈。 常见示例包括: “嗯哼”(“uh-huh”) “对的”&#xff08…

区块链:什么是DeFi?

DeFi(去中心化金融,Decentralized Finance) 是一种基于区块链技术的金融生态系统,旨在通过去中心化的方式提供传统金融服务(如借贷、交易、储蓄等),无需依赖银行、经纪商等中介机构。DeFi主要构…

idea编译器使用git拉取、提交非常慢的原因和解决方案

前言 最近在公司换了一个电脑,但是发现这个电脑用idea编译器使用git拉取、提交各种操作非常慢,有时候需要等10分钟左右,这明显是不对劲的,说明电脑的某些环境影响到git和idea之间的整合了。 目录 在idea拉取代码非常慢的原因 解决方案 在idea拉取代码非常慢的原因 经过排查…

C语言变量的奇妙世界:探秘作用域

资料合集下载链接: ​​https://pan.quark.cn/s/472bbdfcd014​​ 在C语言的编程世界里,变量是我们存储和操作数据的基础。然而,仅仅知道如何定义和使用变量是远远不够的。一个更深层次的理解,在于掌握变量的“作用域”——也就是变量在程序中可以被访问和使用的范围。这就…

恒流源和直流稳压电源 电路

目录 前言一、恒流源电路1.低端反馈2.低端反馈注意事项注意1:电阻Rx注意2:三极管和运放的限制 3.高端反馈注意:自激振荡方案二 二、直流稳压电源电流1.带反馈2.不带反馈3.区别 前言 基础知识可以看个人笔记:个人笔记 一、恒流源…

那些年,曾经辉煌过的数据库

滚滚长江东逝水,浪花淘尽英雄! 数据库的演进史,正是这样一部“英雄迭代”的壮阔史诗。从早期数据模型的拓荒者,到关系型数据库的商业巨头;从桌面应用的普及者,再到开源与大数据时代的弄潮儿;每…

2D曲线点云平滑去噪

2D曲线点云,含许多噪声,采用类似移动最小二乘的方法(MLS)分段拟合抛物线并投影至抛物线,进行点云平滑去噪。 更通俗的说法是让有一定宽度的曲线点云,变成一条细曲线上的点。 分两种情况进行讨论: 1&#…

【平面波导外腔激光器专题系列】用于精密测量的平面波导外腔激光器特性

----翻译自Kenji Numata等人的文章 摘要 1542 nm平面波导外腔激光器PW-ECL具有足够低的噪声非常适合精密测量应用。与 0.1mHz至100kHz 之间,其频率和强度噪声与非平面环形振荡器 NPRO和光纤激光器相当或更好。通过将 PW-ECL 的频率稳定在乙炔(13C2H2&a…

文件时间修改器

文件时间修改器是一款帮助用户修改文件创建时间的软件,支持毫秒级时间的修改,包括文件的创建时间、修改时间、访问时间等时间都支持修改,可以批量处理文件。 飞猫云下载 | 备用下载1 |备用下载2 基本简介 本软件主要为批量修改文件的创建时…

仓颉语言实战:MQTT物联网开发

目录 引言 mqtt4cj库的使用 申请仓颉编程语言内测 下载STDX 测试程序 结束语 引言 最近一直在学习仓颉语言,由于我对物联网比较感兴趣,自然想到写一个MQTT的程序,好在找到了mqtt4cj库,今天分享一下学习心得。 mqtt4cj库的…

OpenCV CUDA模块设备层-----用于在 CUDA 核函数中访问纹理数据的一个封装类TexturePtr()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 TexturePtr<T, R> 是 OpenCV 的 opencv_cudev 模块中用于在 CUDA 核函数中访问纹理数据的一个封装类。它主要用于将一个已创建好的 cudaTe…