🎨 完善点餐订单功能

This commit is contained in:
2025-08-19 16:26:01 +08:00
parent 26f490de6e
commit 4e141ff951
5 changed files with 743 additions and 472 deletions

View File

@@ -7,20 +7,35 @@ const API = {
用户相关 用户相关
*/ */
login: data => net.post('/user/login', data, false), // 登录 login: data => net.post('/user/login', data, false), // 登录
getUserInfo: () => net.get('/user/info', {}, false), // 获取用户信息 getUserInfo: () => net.get('/user/info', {}, true), // 获取用户信息
updateUserInfo: data => net.put('/user/update', data, false), // 更新用户信息 updateUserInfo: data => net.put('/user/update', data, true), // 更新用户信息
upload: data => net.post('/user/upload', data, false), // 上传头像 upload: data => net.post('/user/upload', data, true), // 上传头像
getUserInfoById: (id) => net.get(`/user/info/${id}`, {}, false), // 根据ID获取用户信息 getUserInfoById: (id) => net.get(`/user/info/${id}`, {}, true), // 根据ID获取用户信息
getLoverInfo: () => net.get('/user/lover', {}, false), // 获取情侣关系信息(包含 startDate 与 loverId getLoverInfo: () => net.get('/user/lover', {}, true), // 获取情侣关系信息(包含 startDate 与 loverId
/* /*
纪念日相关 纪念日相关
*/ */
getMemorialDay: (id) => net.get(`/anniversary/${id}`, {}, false), // 获取纪念日详情 getMemorialDay: (id) => net.get(`/anniversary/${id}`, {}, true), // 获取纪念日详情
getMemorialDayList: () => net.get('/anniversary/list', {}, false), // 获取纪念日列表 getMemorialDayList: () => net.get('/anniversary/list', {}, true), // 获取纪念日列表
addMemorialDay: data => net.post('/anniversary', data, false), // 添加纪念日 addMemorialDay: data => net.post('/anniversary', data, true), // 添加纪念日
updateMemorialDay: data => net.put('/anniversary', data, false), // 更新纪念日 updateMemorialDay: data => net.put('/anniversary', data, true), // 更新纪念日
deleteMemorialDay: data => net.delete('/anniversary', data, false) // 删除纪念日 deleteMemorialDay: data => net.delete('/anniversary', data, true), // 删除纪念日
/*
菜品菜谱相关接口
*/
getFoodList: (params = {}) => net.get('/food/list', params, true), // 获取菜品菜谱列表(支持 page/pageSize
getFoodDetail: (id) => net.get(`/food/${id}`, {}, true), // 获取菜品菜谱详情
addFood: data => net.post('/food', data, true), // 添加菜品菜谱
updateFood: data => net.put('/food', data, true), // 更新菜品菜谱
deleteFood: data => net.delete('/food', data, true), // 删除菜品菜谱
createOrder: data => net.post('/order', data, true), // 创建订单
// 菜品分类相关接口
getFoodCategoryList: (params = {}) => net.get('/food/category/list', params, true), // 获取菜品分类列表(支持 page/pageSize
addFoodCategory: data => net.post('/food/category', data, true), // 添加菜品分类
updateFoodCategory: data => net.put('/food/category', data, true), // 更新菜品分类
deleteFoodCategory: data => net.delete('/food/category', data, true) // 删除菜品分类
}; };

View File

@@ -297,7 +297,7 @@ const goToDiary = () => {
} }
const goToOrder = () => { const goToOrder = () => {
uni.navigateTo({ url: '/pages/order/order' }) uni.switchTab({ url: '/pages/order/order' })
} }
const addAnniversary = () => { const addAnniversary = () => {

127
src/pages/order/confirm.vue Normal file
View File

@@ -0,0 +1,127 @@
<template>
<view class="confirm-container">
<view class="card">
<view class="card-title">已选菜品</view>
<view v-for="item in items" :key="item.id" class="row">
<image :src="item.img" class="thumb" mode="aspectFill" />
<view class="meta">
<text class="name">{{ item.name }}</text>
<text class="price">¥{{ item.price || 0 }}</text>
</view>
<text class="qty">×{{ item.qty }}</text>
</view>
<view class="total">合计<text class="price">¥{{ totalPrice }}</text></view>
</view>
<view class="card">
<view class="card-title">留言</view>
<uni-easyinput v-model="remark" placeholder="请输入备注(可选)"></uni-easyinput>
</view>
<view class="submit-bar">
<text class="sum">合计<text class="price">¥{{ totalPrice }}</text></text>
<button class="submit" :loading="submitting" @click="create">提交订单</button>
</view>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import api from '@/api'
const items = ref([])
const ids = ref('')
const userId = ref(null)
const remark = ref('')
const submitting = ref(false)
onMounted(() => {
const channel = getCurrentPages().pop()?.getOpenerEventChannel?.()
channel?.on('initData', (payload) => {
items.value = payload.items || []
ids.value = payload.ids || ''
userId.value = payload.userId || null
})
})
const totalPrice = computed(() => items.value.reduce((s, it) => s + (it.price || 0) * it.qty, 0))
const create = async () => {
if (!ids.value) {
uni.showToast({ title: '未选择菜品', icon: 'none' })
return
}
try {
submitting.value = true
const payload = {
food_ids: ids.value,
user_id: userId.value,
remark: remark.value
}
const res = await api.createOrder(payload)
if (res?.code === 0) {
uni.showToast({ title: '下单成功', icon: 'success' })
setTimeout(() => {
uni.redirectTo({ url: `/pages/order/result?id=${res.data?.ID || ''}` })
}, 600)
} else {
uni.showToast({ title: res?.msg || '下单失败', icon: 'none' })
}
} catch (e) {
console.error('create order failed', e)
uni.showToast({ title: '下单失败', icon: 'none' })
} finally {
submitting.value = false
}
}
</script>
<style lang="scss" scoped>
.confirm-container {
min-height: 100vh;
background: #f5f5f5;
padding-bottom: 140rpx;
}
.card {
background: #fff;
margin: 20rpx;
padding: 20rpx;
border-radius: 16rpx;
.card-title {
font-size: 28rpx;
font-weight: 600;
margin-bottom: 16rpx;
}
.row {
display: flex;
align-items: center;
padding: 16rpx 0;
border-bottom: 1rpx solid #f5f5f5;
&:last-child { border-bottom: none; }
.thumb { width: 120rpx; height: 120rpx; border-radius: 12rpx; margin-right: 16rpx; }
.meta { flex: 1; .name { display:block; font-size: 28rpx; } .price { color:#FF6B9D; margin-top: 6rpx; display:block; } }
.qty { color: #666; }
}
.total { text-align: right; margin-top: 10rpx; .price{ color:#FF6B9D; font-weight: 700; } }
}
.submit-bar {
position: fixed;
left: 0; right: 0; bottom: 0;
background: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
box-shadow: 0 -4rpx 20rpx rgba(0,0,0,0.06);
.sum { font-size: 28rpx; .price{ color:#FF6B9D; font-weight:700; }}
.submit { background: linear-gradient(135deg, #FF6B9D 0%, #FF8E9E 100%); color:#fff; border:none; border-radius: 30rpx; padding: 16rpx 28rpx; font-size: 28rpx; }
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
<template>
<view class="result-container">
<view class="card">
<view class="title">下单成功</view>
<view class="desc">订单已创建等待商家接单</view>
<button class="btn" @click="goBack">返回点餐</button>
</view>
</view>
</template>
<script setup>
const goBack = () => {
const pages = getCurrentPages()
if (pages.length > 1) {
uni.navigateBack({ delta: pages.length - 1 })
} else {
uni.switchTab({ url: '/pages/order/order' })
}
}
</script>
<style lang="scss" scoped>
.result-container {
min-height: 100vh; display:flex; align-items:center; justify-content:center; background:#f5f5f5;
}
.card { background:#fff; padding:40rpx; border-radius:20rpx; text-align:center; box-shadow:0 4rpx 20rpx rgba(0,0,0,.06); }
.title { font-size:36rpx; font-weight:700; color:#333; }
.desc { margin: 16rpx 0 24rpx; color:#666; }
.btn { background: linear-gradient(135deg, #FF6B9D 0%, #FF8E9E 100%); color:#fff; border:none; border-radius: 30rpx; padding: 16rpx 28rpx; font-size: 28rpx; }
</style>