点餐小程序

sunshibo 305efb19c3 小城市 1 vecka sedan
.hbuilderx bf7cdff24f 初始化项目 2 månader sedan
api 305efb19c3 小城市 1 vecka sedan
components 305efb19c3 小城市 1 vecka sedan
hooks bf7cdff24f 初始化项目 2 månader sedan
node_modules bf7cdff24f 初始化项目 2 månader sedan
pages 305efb19c3 小城市 1 vecka sedan
settings 305efb19c3 小城市 1 vecka sedan
static 2a2dfaee9b 增加就餐信息和小程序整体修改 2 veckor sedan
store a6e3aac9f3 扫码打开小程序 手机号 桌号等修改 1 månad sedan
uni_modules 03a720969d 修改桌号 1 månad sedan
unpackage 9550274ba8 增加订单详情 2 månader sedan
utils 305efb19c3 小城市 1 vecka sedan
.gitignore 280e4fcaa6 增加忽略配置 2 månader sedan
App.vue 305efb19c3 小城市 1 vecka sedan
README.md bf7cdff24f 初始化项目 2 månader sedan
index.html bf7cdff24f 初始化项目 2 månader sedan
initConfig.js bf7cdff24f 初始化项目 2 månader sedan
main.js bf7cdff24f 初始化项目 2 månader sedan
manifest.json 97b70351a8 二维码扫码申请权限 1 månad sedan
package.json bf7cdff24f 初始化项目 2 månader sedan
pages.json 2a2dfaee9b 增加就餐信息和小程序整体修改 2 veckor sedan
project.config.json a6e3aac9f3 扫码打开小程序 手机号 桌号等修改 1 månad sedan
project.private.config.json a6e3aac9f3 扫码打开小程序 手机号 桌号等修改 1 månad sedan
routeInterceptor.js d1ed7a45ab 解决登录跳转 1 månad sedan
uni.scss bf7cdff24f 初始化项目 2 månader sedan
yarn.lock bf7cdff24f 初始化项目 2 månader sedan

README.md

点餐小程序

基于 uni-app 框架开发的微信点餐小程序,使用 Vue 3 + Pinia 构建。

📋 项目简介

这是一个功能完善的微信点餐小程序,提供完整的点餐流程,包括菜品浏览、购物车管理、优惠券使用、订单确认等功能。项目采用现代化的前端技术栈,代码结构清晰,易于维护和扩展。

主要业务场景

  • 🍽️ 扫码点餐: 用户扫描桌码进入点餐页面
  • 🛒 购物车管理: 实时管理已选菜品,支持增减数量
  • 🎫 优惠券系统: 优惠券领取和使用
  • 📝 订单确认: 确认订单信息并提交
  • 👤 个人中心: 用户信息管理和设置

🛠 技术栈

  • 框架: uni-app
  • Vue 版本: Vue 3
  • 状态管理: Pinia
  • 构建工具: HBuilderX / Vite
  • 主要依赖:
    • @vueuse/core: Vue Composition API 工具库
    • dayjs: 日期处理库
    • lodash-es: JavaScript 工具库
    • uqrcodejs: 二维码生成库

📁 项目结构

WechatApp/
├── api/                    # API 接口定义
│   ├── index.js           # 通用接口
│   ├── dining.js          # 点餐相关接口
│   └── login.js           # 登录相关接口
├── components/             # 公共组件
│   ├── Modal/             # 弹窗组件
│   │   ├── BasicModal.vue
│   │   └── ScrollPopup.vue
│   ├── NavBar/            # 导航栏组件
│   │   ├── index.vue
│   │   └── StatusBar.vue
│   ├── Share/             # 分享组件
│   │   ├── hook.js
│   │   └── ShareBtn.vue
│   ├── TabBar.vue         # 底部导航栏(首页/扫码点餐/我的)
│   └── Upload/            # 文件上传组件
│       ├── index.vue
│       └── upload.js
├── hooks/                  # 自定义 Hooks
│   ├── libs/              # 第三方库
│   │   └── qqmap-wx-jssdk.min.js  # 腾讯地图 SDK
│   └── usePay.js          # 支付相关 Hook
├── pages/                  # 页面目录
│   ├── index/             # 首页(菜品展示)
│   │   └── index.vue
│   ├── numberOfDiners/    # 扫码点餐(选择就餐人数)
│   │   └── index.vue
│   ├── orderFood/         # 点餐页面
│   │   ├── index.vue
│   │   └── components/    # 点餐相关组件
│   │       ├── FoodCard.vue        # 菜品卡片
│   │       ├── BottomActionBar.vue # 底部操作栏
│   │       ├── CartModal.vue       # 购物车弹窗
│   │       ├── CouponModal.vue     # 优惠券弹窗
│   │       └── SelectCouponModal.vue # 选择优惠券弹窗
│   ├── foodDetail/        # 菜品详情页
│   │   └── index.vue
│   ├── placeOrder/        # 确认订单页
│   │   └── index.vue
│   ├── result/            # 订单结果页
│   │   └── index.vue
│   ├── personal/          # 个人中心
│   │   ├── index.vue      # 个人中心首页
│   │   ├── userInfo.vue   # 个人信息
│   │   └── setPhone.vue   # 设置手机号
│   ├── webview/           # WebView 页面
│   │   └── index.vue
│   └── components/        # 页面级组件
│       └── LoginModal.vue # 登录弹窗
├── settings/              # 配置文件
│   ├── enums.js           # 枚举常量(存储键名等)
│   └── siteSetting.js     # 站点配置(API地址、CDN地址等)
├── store/                 # 状态管理(Pinia)
│   ├── app.js             # 应用状态
│   └── user.js            # 用户状态(登录、用户信息等)
├── utils/                 # 工具函数
│   ├── index.js           # 工具函数入口
│   ├── request.js         # HTTP 请求封装
│   ├── utils.js           # 通用工具函数
│   ├── share.js           # 分享工具
│   ├── file.js            # 文件处理(CDN地址处理等)
│   ├── is.js              # 类型判断工具
│   └── uuid.js            # UUID 生成
├── static/                # 静态资源
│   └── img/               # 图片资源
│       ├── tabbar/        # 底部导航图标
│       └── orderFood/     # 点餐相关图片
├── uni_modules/           # uni-app 插件模块
│   ├── uni-popup/         # 弹窗组件
│   ├── uni-scss/          # 样式工具
│   └── uni-transition/    # 过渡动画
├── App.vue                # 应用入口(全局样式、生命周期)
├── main.js                # 主入口文件(应用初始化)
├── initConfig.js          # 初始化配置(版本更新检测等)
├── routeInterceptor.js    # 路由拦截器(登录验证)
├── pages.json             # 页面路由配置
├── manifest.json          # 应用配置文件(AppID、权限等)
└── uni.scss               # 全局样式变量

🚀 功能特性

核心功能

  • 用户认证: 微信登录、手机号登录、token 管理、自动登录
  • 路由拦截: 自动检测登录状态,保护需要登录的页面
  • 请求封装: 统一的 HTTP 请求处理,自动处理 token、loading、错误提示
  • 状态管理: 基于 Pinia 的用户状态管理
  • 小程序更新: 自动检测并提示小程序版本更新
  • 网络检测: 启动时检测网络状态

业务功能

点餐流程

  • 🍽️ 扫码点餐: 扫描桌码进入点餐流程
  • 👥 选择人数: 选择就餐人数
  • 🍜 菜品浏览: 分类浏览菜品,查看菜品详情
  • 🛒 购物车: 实时管理已选菜品,支持增减数量
  • 🎫 优惠券: 优惠券领取、选择和使用
  • 📝 订单确认: 确认订单信息、桌号、人数、优惠等
  • 订单提交: 提交订单并查看结果

其他功能

  • 📱 首页: 店铺信息展示、菜品推荐、登录引导
  • 👤 个人中心: 用户信息管理、手机号设置
  • 📤 文件上传: 支持图片、文件上传到 OSS
  • 📍 地理位置: 集成腾讯地图 SDK(H5端)
  • 💰 支付功能: 微信支付集成(预留接口)

UI 组件

  • 自定义导航栏: 支持状态栏适配,自定义样式
  • 底部 TabBar: 三栏导航(首页/扫码点餐/我的),中间为特殊圆形按钮
  • 模态弹窗: 基础弹窗、滚动弹窗组件
  • 菜品卡片: 菜品信息展示,支持加购操作
  • 购物车弹窗: 购物车管理,支持修改数量、清空
  • 优惠券弹窗: 优惠券列表展示和领取
  • 登录弹窗: 快速登录入口

📦 安装与运行

环境要求

  • Node.js >= 14.0.0
  • HBuilderX 或 支持 uni-app 的 IDE
  • 微信开发者工具

安装依赖

# 使用 yarn
yarn install

# 或使用 npm
npm install

开发运行

  1. 使用 HBuilderX 打开项目
  2. 选择运行到微信小程序
  3. 或使用命令行:

    # 开发环境
    npm run dev:mp-weixin
    
    # 生产构建
    npm run build:mp-weixin
    

配置说明

1. 小程序配置 (manifest.json)

  • AppID: wxc9598c736783dfa9(当前配置)
  • 版本号: 1.0.0 (versionName) / 100 (versionCode)
  • 权限配置:
    • scope.userLocation: 位置信息权限
    • scope.record: 录音权限
  • 网络配置: urlCheck: false(开发环境可关闭域名校验)

2. API 配置

settings/siteSetting.js 中配置 API 基础地址:

// 开发环境 / 生产环境 API 地址
export const BASE_API_URL = process.env.NODE_ENV === 'development' 
  ? 'http://192.168.1.91:8000/aliendining' 
  : 'http://192.168.1.91:8000/aliendining';

// 文件上传地址
export const UPLOAD_URL = 'https://api.xxxxxx.cn/File/UploadImg';

// CDN 地址
export const DEFAULT_CDN_URL = 'https://alien-volume.oss-cn-beijing.aliyuncs.com/';
export const UPLOAD = 'https://alien-volume.oss-cn-beijing.aliyuncs.com/';

3. 腾讯地图配置

manifest.jsonh5.sdkConfigs.maps.qqmap 中配置地图 Key(仅 H5 端使用):

{
  "h5": {
    "sdkConfigs": {
      "maps": {
        "qqmap": {
          "key": ""
        }
      }
    }
  }
}

4. 页面路由配置 (pages.json)

主要页面路由:

  • /pages/index/index - 首页
  • /pages/numberOfDiners/index - 扫码点餐(选择人数)
  • /pages/orderFood/index - 点餐页面
  • /pages/foodDetail/index - 菜品详情
  • /pages/placeOrder/index - 确认订单
  • /pages/result/index - 订单结果
  • /pages/personal/index - 个人中心
  • /pages/personal/userInfo - 个人信息
  • /pages/personal/setPhone - 设置手机号
  • /pages/webview/index - WebView 页面

🔧 核心模块说明

路由拦截 (routeInterceptor.js)

自动拦截需要登录的页面访问,未登录用户将被引导至登录页,登录成功后自动跳转回原页面。

拦截的路由方法:

  • uni.navigateTo
  • uni.reLaunch
  • uni.redirectTo

需要登录的页面列表(在 routeInterceptor.js 中配置)

工作原理:

  1. 检测目标页面是否在登录列表中
  2. 检查用户 token 是否存在
  3. 未登录时弹出提示,用户确认后跳转登录页
  4. 登录成功后从 REDIRECT_KEY 读取原目标地址并跳转

请求封装 (utils/request.js)

统一的 HTTP 请求处理类,提供以下特性:

  • ✅ 自动添加 token 到请求头(Authorization)
  • ✅ 自动显示/隐藏 loading(支持并发请求计数)
  • ✅ 统一错误处理(根据 code 码处理)
  • ✅ 请求超时处理(默认 180 秒)
  • ✅ GET 请求自动添加时间戳防缓存
  • ✅ 网络错误提示

请求配置选项:

{
  url: string,              // 请求路径(相对路径)
  params: object,          // 请求参数
  headers: object,         // 自定义请求头
  loading: boolean,        // 是否显示 loading(默认 true)
  timeout: number,         // 超时时间(默认 180000ms)
  returnResponse: boolean, // 是否返回原生响应(默认 false)
  message: boolean,        // 是否显示消息提示(默认 true)
  hideErrorModal: boolean, // 是否隐藏错误弹窗(默认 false)
  customizeUrl: string     // 自定义完整 URL
}

响应码处理:

  • code: 200 - 成功,返回 data 字段
  • code: 400 - 系统异常,弹出错误提示
  • 其他 code - 根据 hideErrorModal 决定是否弹出错误提示

使用示例:

import { api } from '@/utils/request.js';

// GET 请求
const userInfo = await api.get({
  url: '/api/user/info',
  params: { id: 1 }
});

// POST 请求
const result = await api.post({
  url: '/api/user/update',
  params: { name: 'test' },
  loading: true,        // 显示 loading
  hideErrorModal: false // 显示错误弹窗
});

// 静默请求(不显示 loading 和错误提示)
const data = await api.get({
  url: '/api/check',
  loading: false,
  hideErrorModal: true
});

状态管理 (store/user.js)

用户状态管理 Store(基于 Pinia),提供以下功能:

  • ✅ 用户信息管理(内存 + 本地存储)
  • ✅ Token 管理(自动同步到本地存储)
  • ✅ OpenId 管理
  • ✅ SiteId 管理
  • ✅ 登录/登出(带确认提示)
  • ✅ 自动持久化(使用 uni.setStorageSync

State:

{
  userInfo: null,    // 用户信息对象
  token: undefined,  // 用户 token
  siteId: undefined, // 站点 ID
  openId: undefined  // 微信 OpenId
}

Getters:

  • getUserInfo - 获取用户信息(优先内存,其次本地存储)
  • getToken - 获取 token
  • getOpenId - 获取 OpenId

Actions:

  • setUserInfo(e) - 设置用户信息
  • login(e) - 登录(保存用户信息、token、siteId,显示成功提示)
  • beforeLogout() - 退出前确认
  • logout(option) - 退出登录(清除存储,可配置是否跳转首页)

使用示例:

import { useUserStore } from '@/store/user.js';

const userStore = useUserStore();

// 获取用户信息
const userInfo = userStore.getUserInfo;

// 获取 token
const token = userStore.getToken;

// 登录
userStore.login({
  token: 'xxx',
  siteId: 'xxx',
  ...userData
});

// 退出登录(带确认)
userStore.beforeLogout();

// 直接退出(不确认)
userStore.logout({ redirct: true });

初始化配置 (initConfig.js)

应用启动时的初始化逻辑(在 App.vueonLaunch 中调用):

功能:

  1. 网络检测: 检测当前网络状态
    • 无网络时提示用户开启网络
    • 有网络时继续后续流程
  2. 版本更新检测: 使用 uni.getUpdateManager() 检测小程序更新
    • 检测到新版本时自动下载
    • 下载完成后提示用户重启应用
    • 下载失败时提示用户卸载重装

更新流程:

启动 → 检测网络 → 检测更新 → 下载更新 → 提示重启 → 应用更新

注意事项:

  • 仅在微信小程序环境执行(#ifdef MP-WEIXIN
  • 网络检测失败时不会阻止应用启动

🎨 样式规范

项目使用 SCSS,全局样式定义在 App.vueuni.scss 中。

常用工具类

  • .flex: Flex 布局
  • .flex-center: 水平垂直居中
  • .flex-between: 两端对齐
  • .ellipsis: 单行省略
  • .ellipsis-2: 两行省略(支持 2-10 行)
  • .safe-area: 底部安全区适配

📱 页面说明

首页 (pages/index/index)

  • 功能: 店铺信息展示、菜品推荐、登录引导
  • 特性:
    • 支持下拉刷新
    • 自定义导航栏
    • 未登录时显示登录卡片
    • 菜品列表展示(图片、名称、价格、月售等)
    • 菜品加购功能

扫码点餐 (pages/numberOfDiners/index)

  • 功能: 选择就餐人数
  • 入口: 底部 TabBar 中间圆形按钮
  • 流程: 选择人数 → 进入点餐页面

点餐页面 (pages/orderFood/index)

  • 功能: 浏览菜品、管理购物车、使用优惠券
  • 特性:
    • 左侧分类导航
    • 右侧菜品列表
    • 实时购物车管理
    • 优惠券领取和使用
    • 底部操作栏(购物车、优惠券、下单)
  • 组件:
    • FoodCard: 菜品卡片
    • BottomActionBar: 底部操作栏
    • CartModal: 购物车弹窗
    • CouponModal: 优惠券弹窗
    • SelectCouponModal: 选择优惠券弹窗

菜品详情 (pages/foodDetail/index)

  • 功能: 查看菜品详细信息
  • 特性: 自定义导航栏、菜品详情展示

确认订单 (pages/placeOrder/index)

  • 功能: 确认订单信息并提交
  • 内容: 订单详情、桌号、人数、优惠信息等

订单结果 (pages/result/index)

  • 功能: 显示订单提交结果
  • 状态: 成功/失败提示

个人中心 (pages/personal/index)

  • 功能: 用户信息展示、功能入口
  • 特性: 自定义导航栏、用户信息卡片

个人信息 (pages/personal/userInfo)

  • 功能: 查看和编辑个人信息

设置手机号 (pages/personal/setPhone)

  • 功能: 设置或修改手机号

WebView 页面 (pages/webview/index)

  • 功能: 内嵌网页展示
  • 特性: 自定义导航栏、支持外部链接加载

登录弹窗 (pages/components/LoginModal.vue)

  • 功能: 快速登录入口
  • 使用: 在需要登录的页面中调用

🔌 插件说明

uni-popup 弹窗组件

uni-app 官方弹窗组件,用于各种弹窗场景。

安装: 通过 uni_modules 自动安装

使用:

<uni-popup ref="popup" type="bottom">
  <view>弹窗内容</view>
</uni-popup>

uni-scss 样式工具

uni-app 官方样式工具库,提供统一的样式变量和工具类。

uni-transition 过渡动画

uni-app 官方过渡动画组件,用于页面和组件过渡效果。

📦 依赖说明

核心依赖

  • @dcloudio/uni-ui: uni-app UI 组件库
  • @vueuse/core: Vue Composition API 工具库(Vue 3 版本)
  • dayjs: 轻量级日期处理库
  • lodash-es: JavaScript 工具库(ES 模块版本)
  • uqrcodejs: 二维码生成库

开发依赖

项目使用 HBuilderX 或 Vite 进行构建,具体构建工具根据开发环境而定。

📝 开发规范

代码规范

Vue 组件规范

  • ✅ 使用 Vue 3 Composition API (<script setup>)
  • ✅ 组件命名采用 PascalCase(如 FoodCard.vue
  • ✅ 文件命名采用 camelCase(如 userInfo.vue
  • ✅ 使用 TypeScript 或 JSDoc 注释(可选)

目录结构规范

  • ✅ 工具函数统一放在 utils 目录
  • ✅ API 接口统一放在 api 目录
  • ✅ 公共组件放在 components 目录
  • ✅ 页面组件放在对应页面的 components 目录

样式规范

  • ✅ 使用 SCSS 预处理器
  • ✅ 使用 rpx 作为尺寸单位(适配不同屏幕)
  • ✅ 使用全局样式类(.flex, .ellipsis 等)
  • ✅ 组件样式使用 scoped

命名规范

  • ✅ 变量和函数使用 camelCase
  • ✅ 常量使用 UPPER_SNAKE_CASE
  • ✅ 组件名使用 PascalCase
  • ✅ 文件名使用 camelCase

提交规范

建议使用约定式提交(Conventional Commits):

  • feat: 新功能
  • fix: 修复 bug
  • docs: 文档更新
  • style: 代码格式调整(不影响代码运行)
  • refactor: 代码重构
  • perf: 性能优化
  • test: 测试相关
  • chore: 构建/工具相关
  • revert: 回滚提交

示例:

feat: 添加优惠券选择功能
fix: 修复购物车数量计算错误
docs: 更新 README 文档
style: 调整菜品卡片样式
refactor: 重构请求封装代码

代码审查清单

提交代码前请检查:

  • 代码格式正确,无语法错误
  • 已测试功能正常
  • 无控制台错误和警告
  • 样式在不同设备上显示正常
  • API 请求错误处理完善
  • 登录状态检查正确
  • 图片资源路径正确

🐛 常见问题

1. 小程序版本更新

问题: 小程序如何检测和更新版本?

解答:

  • 小程序会自动检测新版本并提示用户更新
  • 更新逻辑在 initConfig.js 中实现
  • 使用 uni.getUpdateManager() API
  • 下载完成后会提示用户重启应用

2. 登录状态管理

问题: 如何判断用户是否已登录?

解答:

  • 通过 useUserStore().getToken 获取 token
  • token 存储在 Pinia store 和本地存储中
  • 路由拦截器会自动检查需要登录的页面

3. 网络请求失败

问题: 网络请求失败时如何处理?

解答:

  • 网络请求失败时会自动提示"网络不稳定,请稍后刷新重试"
  • 自动隐藏 loading
  • 不会阻止后续代码执行(需要自行处理 reject)

4. 图片资源加载

问题: 如何正确加载静态图片?

解答:

  • 使用 getFileUrl() 工具函数处理图片路径
  • 支持 CDN 地址和本地路径
  • 示例: getFileUrl('img/tabbar/index1.png')

5. 底部 TabBar 不显示

问题: 为什么底部导航栏不显示?

解答:

  • 检查页面中是否引入了 TabBar 组件
  • 确认 TabBar 组件的 fixed 属性设置
  • 检查页面样式是否遮挡了 TabBar

6. 路由跳转被拦截

问题: 为什么跳转到某些页面会被拦截?

解答:

  • 检查目标页面是否在 routeInterceptor.jsloginList
  • 确认用户是否已登录(token 是否存在)
  • 未登录时会弹出提示,确认后跳转登录页

7. API 请求地址配置

问题: 如何修改 API 请求地址?

解答:

  • 修改 settings/siteSetting.js 中的 BASE_API_URL
  • 支持根据 process.env.NODE_ENV 区分开发/生产环境
  • 修改后需要重新编译小程序

8. 微信开发者工具报错

问题: 在微信开发者工具中运行报错?

解答:

  • 检查 manifest.json 中的 AppID 是否正确
  • 确认网络请求域名是否在微信后台配置
  • 开发环境可设置 urlCheck: false 关闭域名校验
  • 检查是否有语法错误或缺少依赖

9. 样式不生效

问题: 为什么某些样式不生效?

解答:

  • 检查是否使用了正确的选择器(小程序不支持部分 CSS 选择器)
  • 确认样式作用域(scoped 样式)
  • 检查全局样式是否被覆盖
  • 使用 rpx 单位而非 px

10. 本地存储数据

问题: 如何管理本地存储数据?

解答:

  • 使用 uni.setStorageSyncuni.getStorageSync
  • 存储键名定义在 settings/enums.js
  • 用户信息、token 等会自动同步到本地存储

🔐 环境变量

项目支持通过环境变量配置不同环境:

  • NODE_ENV: 环境标识(development / production
  • API 地址根据环境自动切换(在 settings/siteSetting.js 中配置)

📊 项目信息

  • 项目名称: 点餐小程序
  • 框架版本: uni-app (Vue 3)
  • 小程序 AppID: wxc9598c736783dfa9
  • 版本号: 1.0.0
  • 构建工具: HBuilderX / Vite

🗺️ 开发路线图

  • 完善支付功能集成
  • 添加订单历史查询
  • 优化购物车性能
  • 添加菜品搜索功能
  • 支持多店铺切换
  • 添加评价功能

📄 许可证

MIT License

👥 贡献

欢迎提交 Issue 和 Pull Request。

贡献指南

  1. Fork 本项目
  2. 创建特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交更改 (git commit -m 'feat: Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 开启 Pull Request

📞 联系方式

如有问题或建议,请联系项目维护者。


注意:

  • 本项目为微信小程序项目,部分功能仅在微信小程序环境中可用
  • 开发时请使用微信开发者工具进行调试
  • 生产环境部署前请确保所有配置正确(AppID、API 地址、权限等)