# 点餐小程序
基于 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
- 微信开发者工具
### 安装依赖
```bash
# 使用 yarn
yarn install
# 或使用 npm
npm install
```
### 开发运行
1. 使用 HBuilderX 打开项目
2. 选择运行到微信小程序
3. 或使用命令行:
```bash
# 开发环境
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 基础地址:
```javascript
// 开发环境 / 生产环境 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.json` 的 `h5.sdkConfigs.maps.qqmap` 中配置地图 Key(仅 H5 端使用):
```json
{
"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 请求自动添加时间戳防缓存
- ✅ 网络错误提示
**请求配置选项**:
```javascript
{
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` 决定是否弹出错误提示
**使用示例**:
```javascript
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**:
```javascript
{
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)` - 退出登录(清除存储,可配置是否跳转首页)
**使用示例**:
```javascript
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.vue` 的 `onLaunch` 中调用):
**功能**:
1. **网络检测**: 检测当前网络状态
- 无网络时提示用户开启网络
- 有网络时继续后续流程
2. **版本更新检测**: 使用 `uni.getUpdateManager()` 检测小程序更新
- 检测到新版本时自动下载
- 下载完成后提示用户重启应用
- 下载失败时提示用户卸载重装
**更新流程**:
```
启动 → 检测网络 → 检测更新 → 下载更新 → 提示重启 → 应用更新
```
**注意事项**:
- 仅在微信小程序环境执行(`#ifdef MP-WEIXIN`)
- 网络检测失败时不会阻止应用启动
## 🎨 样式规范
项目使用 SCSS,全局样式定义在 `App.vue` 和 `uni.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 自动安装
**使用**:
```vue
弹窗内容
```
### 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 (`