文章目录

    • 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/diannao/88245.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/88245.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/88245.shtml

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

相关文章

Linux中使用grep查看日志

Linux中使用grep查看日志 文章目录 Linux中使用grep查看日志1、使用 grep 查找字符或字符串示例常用选项例子 2、显示前后上下文选项说明示例命令 结果示例 3、显示出现的次数使用示例选项说明示例其他方法总结 4、其他命令1. 基本用法2. 常用选项3. 正则表达式支持4. 其他实用…

DataWhale-零基础络网爬虫技术(二er数据的解析与提取)

课程链接先给各位 ↓↓↓ (点击即可食用.QAQ Datawhale-学用 AI,从此开始 一、数据的解析与提取 数据提取的几种方式: re解析bs4解析xpath解析 1.1正则表达式(Reuglar Experssion) RE是一种用于字符串匹配的规则描述方式。它…

Gin框架与Apifox

第一部分:技术栈概述 1. Go语言简介 Go(又称Golang)是Google开发的一门静态类型、编译型编程语言,具有以下特点: 高性能:编译为机器码,执行效率接近C/C 简洁语法:没有复杂的OOP概…

Docker 容器技术入门与环境部署

一、Docker 技术概述与核心概念解析 (一)Docker 技术本质与定位 Docker 是当前主流的操作系统级容器虚拟化技术,其核心价值在于通过轻量化隔离机制解决开发、测试与生产环境的一致性问题。与传统虚拟机(如 VMware)相…

π0源码(openpi)剖析——从π0模型架构的实现:如何基于PaLI-Gemma和扩散策略去噪生成动作,到基于C/S架构下的模型训练与部署

前言 ChatGPT出来后的两年多,也是我疯狂写博的两年多(年初deepseek更引爆了下),比如从创业起步时的15年到后来22年之间 每年2-6篇的,干到了23年30篇、24年65篇、25年前两月18篇,成了我在大模型和具身的原始技术积累 如今一转眼已…

Vui:轻量级语音对话模型整合包,让交互更自然

Vui:轻量级语音对话模型,让交互更自然 🗣️✨ Vui 是 Fluxions-AI 团队推出的一款开源轻量级语音对话模型,其核心架构基于 LLaMA。这款模型经过了长达 4 万小时的真实对话数据训练,能够逼真地模拟人类对话中的语气词、…

【STL】深入理解 string 的底层思想

一、STL的定义 STL是C标准库的一部分它不仅是一个可复用的组件库还是一个包含数据结构和算法的软件框架。 二、STL的历史和版本 原始版本: Alexander Stepanov、Meng Lee在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运…

深入剖析Linux epoll模型:从LT/ET模式到EPOLLONESHOT的实战指南

一、epoll:高性能I/O复用的核心引擎 epoll是Linux内核2.6引入的高效I/O多路复用机制,专为解决C10K问题而生。相比select/poll,epoll在连接数激增时性能优势显著: // 创建epoll实例 int epollfd epoll_create1(0);// 事件注册 s…

网络安全之某cms的漏洞分析

漏洞描述 该漏洞源于Appcenter.php存在限制,但攻击者仍然可以通过绕过这些限制并以某种方式编写代码,使得经过身份验证的攻击者可以利用该漏洞执行任意命令 漏洞分析 绕过编辑模板限制,从而实现RCE 这里可以修改模板文件,但是不…

Nginx-前端跨域解决方案!

1 Nginx 核心 Nginx 是一个开源的高性能 HTTP 和反向代理服务器,以轻量级、高并发处理能力和低资源消耗著称。除作为 Web 服务器外,还可充当邮件代理服务器和通用的 TCP/UDP 代理服务器,广泛应用于现代 Web 架构中。 在 Windows 系统中使用…

RedisVL 入门构建高效的 AI 向量搜索应用

一、前置条件 在开始之前,请确保: 已在 Python 环境中安装 redisvl。运行 Redis Stack 或 Redis Cloud 实例。 二、定义索引架构(IndexSchema) 索引架构(IndexSchema)用于定义 Redis 的索引配置和字段信…

基于ssm移动学习平台微信小程序源码数据库文档

摘 要 由于APP软件在开发以及运营上面所需成本较高,而用户手机需要安装各种APP软件,因此占用用户过多的手机存储空间,导致用户手机运行缓慢,体验度比较差,进而导致用户会卸载非必要的APP,倒逼管理者必须改…

【Python】Tkinter模块(巨详细)

专栏文章索引:Python 有问题可私聊:QQ:3375119339 本文内容系本人根据阅读的《Python GUI设计tkinter从入门到实践》所得,以自己的方式进行总结和表达。未经授权,禁止在任何平台上以任何形式复制或发布原始书籍的内容。如有侵权,请联系我删除。 目录 一、Tkinter与GUI …

【C++特殊工具与技术】局部类

在 C 的类体系中,除了全局类、嵌套类(在类内部定义的类),还有一种特殊的存在 ——局部类(Local Class)。它像函数内部的 “封闭王国”,作用域严格限制在所属函数内,既拥有类的封装特…

《C#图解教程 第5版》深度推荐

《C#图解教程 第5版》深度推荐 在 C# 编程语言的浩瀚学习资源中,《C#图解教程 第5版》宛如一座灯塔,为开发者照亮前行之路。通过其详实的目录,我们能清晰窥见这本书在知识架构、学习引导上的匠心独运,无论是编程新手还是进阶开发者…

【Kubernetes】配置自定义的 kube-scheduler 调度规则

在最近一次 K8s 环境的维护中,发现多个 Pod 使用相同镜像时,调度到固定节点的问题导致集群节点资源分配不均的情况。 启用调度器的打分日志后发现这一现象是由 ImageLocality 打分策略所引起的(所有的节点中,只有一个节点有运行该…

跟着AI学习C# Day21

📅 Day 21:动态类型与动态语言运行时(Dynamic Types & DLR) ✅ 学习目标: 理解什么是 dynamic 类型;掌握 dynamic 与 object 的区别;理解 DLR(Dynamic Language Runtime&#…

leetcode-3085.成为K字符串需要删除的最小字符串数

题目描述 解题思路 这题不难想到需要统计每个字母的出现频率,一共有26个字母,故cnt数组有26维。我们可以枚举其中一种作为「删除操作结束后出现频率最低的字符」,将其设置为 c,那么所有频率小于 c 的字符都会被删除,所…

Android 中 解析 XML 文件的几种方式

在 Android 开发中,解析 XML 文件有多种方式,每种方式都有其特点和适用场景。常见的 XML 解析方式有 DOM 解析、SAX 解析 和 XmlPullParser 解析。 一、xml 文件及数据类 1、xml 文件 将测试用 book.xml 文件放在项目的 app/src/main/assets 目录下,文件内容如下:<lib…

python里的abc库是什么东西

Python 中的 ABC&#xff1a;为什么你需要抽象基类&#xff1f;告别“假鸭子”&#xff0c;拥抱真抽象&#xff01; 你是不是经常在 Python 项目中感到困惑&#xff1a;我定义了一个类&#xff0c;希望它能被其他类继承并实现某些特定功能&#xff0c;但又不想它被直接实例化&…