| @ -0,0 +1,237 @@ | |||||
| <template> | |||||
| <view class="order-item" @click="clickOrder"> | |||||
| <!-- 订单头部 - 商家信息 --> | |||||
| <view class="order-header"> | |||||
| <view class="shop-info"> | |||||
| <image class="shop-logo" :src="order.shopLogo" mode="aspectFill"></image> | |||||
| <text class="shop-name">{{ order.shopName }}</text> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 订单内容 - 菜品展示 --> | |||||
| <view class="order-content"> | |||||
| <view class="food-list"> | |||||
| <view class="food-scroll"> | |||||
| <view class="food-item" v-for="(food, index) in fourImage" :key="index"> | |||||
| <image class="food-image" :src="food.image" mode="aspectFill"></image> | |||||
| </view> | |||||
| </view> | |||||
| <view class="food-count" v-if="order.foodCount > 4">共{{ order.foodCount }}个</view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 订单信息 - 下单时间和价格 --> | |||||
| <view class="order-info"> | |||||
| <view class="order-time">下单时间:{{ order.orderTime }}</view> | |||||
| <view class="order-price"> | |||||
| <text>合计:</text> | |||||
| <text class="price">¥{{ order.totalPrice.toFixed(2) }}</text> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 订单操作 --> | |||||
| <view class="order-actions"> | |||||
| <view | |||||
| class="order-toast" | |||||
| v-if="order.status === 'shipping' || order.status === 'delivered'" | |||||
| :style="{ backgroundColor: order.status === 'shipping' ? '#ECFEF4' : '#FFDBDB', color: order.status === 'shipping' ? '#019245' : '#FF2A2A' }"> | |||||
| <uv-icon name="info-circle" size="34" :color="order.status === 'shipping' ? '#019245' : '#FF2A2A'"></uv-icon> | |||||
| <text v-show="order.status === 'shipping'">全力奔跑中,请耐心等待哦!</text> | |||||
| <text v-show="order.status === 'delivered'">您的餐点已送到取餐点,请尽快取餐</text> | |||||
| </view> | |||||
| <view class="action-btn cancel" v-show="order.status === 'pending'" @click="cancelOrder"> | |||||
| 取消订单 | |||||
| </view> | |||||
| <view class="action-btn confirm" v-show="order.status === 'pending'" @click="payOrder"> | |||||
| 立即下单 | |||||
| </view> | |||||
| <view class="action-btn confirm" v-show="order.status === 'processing' || order.status === 'shipping'" | |||||
| @click="payOrder"> | |||||
| 查看订单 | |||||
| </view> | |||||
| <view class="action-btn confirm" v-show="order.status === 'completed'" @click="gotoSale"> | |||||
| 订单售后 | |||||
| </view> | |||||
| <view class="action-btn confirm" v-show="order.status === 'delivered'" @click="payOrder"> | |||||
| 取餐完成 | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| name: 'OrderItem', | |||||
| props: { | |||||
| // 订单数据对象 | |||||
| order: { | |||||
| type: Object, | |||||
| required: true, | |||||
| default: () => ({ | |||||
| id: '', | |||||
| shopName: '', | |||||
| shopLogo: '', | |||||
| foods: [], | |||||
| foodCount: 0, | |||||
| orderTime: '', | |||||
| totalPrice: 0, | |||||
| status: 'pending' // pending, processing, shipping, completed, delivered, canceled | |||||
| }) | |||||
| } | |||||
| }, | |||||
| computed: { | |||||
| fourImage() { | |||||
| return this.order.foods.slice(0, 4) | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 取消订单 | |||||
| cancelOrder() { | |||||
| this.$emit('cancel', this.order.id); | |||||
| }, | |||||
| // 支付订单 | |||||
| payOrder() { | |||||
| this.$emit('pay', this.order.id); | |||||
| }, | |||||
| // 点击整个订单项 | |||||
| clickOrder() { | |||||
| this.$emit('click', this.order); | |||||
| }, | |||||
| gotoSale() { | |||||
| this.$utils.navigateTo({ | |||||
| url: '/pages_order/order/afterSale?id=' + this.order.id | |||||
| }) | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .order-item { | |||||
| background-color: #ffffff; | |||||
| margin: 20rpx 0; | |||||
| border-radius: 16rpx; | |||||
| padding: 20rpx; | |||||
| .order-header { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: space-between; | |||||
| padding-bottom: 20rpx; | |||||
| border-bottom: 1rpx solid #f5f5f5; | |||||
| .shop-info { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| .shop-logo { | |||||
| width: 70rpx; | |||||
| height: 70rpx; | |||||
| border-radius: 6rpx; | |||||
| margin-right: 10rpx; | |||||
| } | |||||
| .shop-name { | |||||
| font-size: 28rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| .order-content { | |||||
| padding: 20rpx 0; | |||||
| .food-list { | |||||
| white-space: nowrap; | |||||
| height: 150rpx; | |||||
| width: 100%; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| .food-scroll { | |||||
| display: inline-flex; | |||||
| } | |||||
| .food-item { | |||||
| height: 140rpx; | |||||
| width: 130rpx; | |||||
| margin-right: 10rpx; | |||||
| display: inline-block; | |||||
| .food-image { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| border-radius: 8rpx; | |||||
| } | |||||
| } | |||||
| .food-count { | |||||
| flex: 1; | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| text-align: center; | |||||
| margin-top: 10rpx; | |||||
| } | |||||
| } | |||||
| .order-info { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| align-items: center; | |||||
| padding: 10rpx 0; | |||||
| border-top: 1rpx solid #f5f5f5; | |||||
| .order-time { | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| } | |||||
| .order-price { | |||||
| font-size: 24rpx; | |||||
| .price { | |||||
| color: #f00; | |||||
| font-weight: 500; | |||||
| margin-left: 8rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| .order-actions { | |||||
| display: flex; | |||||
| justify-content: flex-end; | |||||
| align-items: center; | |||||
| padding: 20rpx; | |||||
| gap: 20rpx; | |||||
| .order-toast { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| // justify-content: flex-start; | |||||
| flex: 1; | |||||
| // text-align: left; | |||||
| gap: 10rpx; | |||||
| font-size: 24rpx; | |||||
| background-color: pink; | |||||
| border-radius: 10rpx; | |||||
| padding: 10rpx; | |||||
| } | |||||
| .action-btn { | |||||
| padding: 12rpx 30rpx; | |||||
| border-radius: 30rpx; | |||||
| font-size: 24rpx; | |||||
| font-weight: 500; | |||||
| &.cancel { | |||||
| background-color: #fff; | |||||
| color: $uni-color-third; | |||||
| border: 3rpx solid $uni-color-third; | |||||
| } | |||||
| &.confirm { | |||||
| background-color: $uni-color; | |||||
| color: #fff; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,189 @@ | |||||
| <template> | |||||
| <view class="page"> | |||||
| <!-- 导航栏 --> | |||||
| <navbar title="取餐点" leftClick @leftClick="$utils.navigateBack" bgColor="#019245" color="#fff" /> | |||||
| <view class="container"> | |||||
| <view class="header"> | |||||
| <view class="title">附近取餐点</view> | |||||
| </view> | |||||
| <!-- 取餐点列表 --> | |||||
| <view class="pickup-list"> | |||||
| <view class="pickup-item" v-for="(item, index) in pickupPoints" :key="index"> | |||||
| <view class="left"> | |||||
| <image :src="item.image" class="shop-image" mode="aspectFill"></image> | |||||
| </view> | |||||
| <view class="center"> | |||||
| <view class="shop-name">{{item.name}}</view> | |||||
| <view class="shop-address"> | |||||
| <uv-icon name="map-fill" color="#019245" size="34rpx"></uv-icon> | |||||
| <text class="address-text">{{item.address}}</text> | |||||
| </view> | |||||
| <view class="shop-phone"> | |||||
| <uv-icon name="phone-fill" color="#019245" size="34rpx"></uv-icon> | |||||
| <text class="phone-text">{{item.phone}}</text> | |||||
| </view> | |||||
| </view> | |||||
| <view class="right"> | |||||
| <button class="select-btn" hover-class="select-btn-active" @click="selectPoint(item)">选择</button> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 无数据提示 --> | |||||
| <uv-empty v-if="pickupPoints.length === 0" text="暂无取餐点" mode="list"></uv-empty> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import navbar from '@/components/base/navbar.vue' | |||||
| export default { | |||||
| components: { | |||||
| navbar | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| pickupPoints: [ | |||||
| { | |||||
| id: '1', | |||||
| name: '轻奢时代芙蓉兴盛', | |||||
| address: '长沙市雨花区时代阳光大道轻奢时代芙蓉兴盛', | |||||
| phone: '15070023168', | |||||
| image: '/static/image/古茗店面.webp' | |||||
| }, | |||||
| { | |||||
| id: '2', | |||||
| name: '芙蓉兴盛小文轩便利店', | |||||
| address: '长沙市芙蓉区牛津街7栋102', | |||||
| phone: '15070023168', | |||||
| image: '/static/image/古茗店面.webp' | |||||
| } | |||||
| ] | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 选择取餐点 | |||||
| selectPoint(point) { | |||||
| // 将选择的取餐点信息存储到 store 或 storage 中 | |||||
| uni.setStorageSync('selectedPickupPoint', JSON.stringify(point)); | |||||
| // 通知上一页面已选择取餐点,并返回 | |||||
| // const pages = getCurrentPages(); | |||||
| // const prevPage = pages[pages.length - 2]; | |||||
| // if (prevPage) { | |||||
| // // 如果需要可以设置上一页的数据 | |||||
| // prevPage.$vm.pickupPoint = point; | |||||
| // } | |||||
| uni.$emit('updatePickupPoint', point); | |||||
| uni.showToast({ | |||||
| title: '已选择取餐点', | |||||
| icon: 'success', | |||||
| duration: 400 | |||||
| }); | |||||
| setTimeout(() => { | |||||
| // uni.navigateBack(); | |||||
| this.$utils.navigateBack() | |||||
| }, 800); | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .page { | |||||
| background-color: #f5f5f5; | |||||
| min-height: 100vh; | |||||
| } | |||||
| .container { | |||||
| padding: 0 20rpx; | |||||
| } | |||||
| .header { | |||||
| margin-top: 20rpx; | |||||
| background-color: #f2f2f2; | |||||
| border-radius: 8rpx; | |||||
| .title { | |||||
| font-size: 32rpx; | |||||
| // font-weight: bold; | |||||
| padding: 20rpx; | |||||
| } | |||||
| } | |||||
| .pickup-list { | |||||
| margin-top: 20rpx; | |||||
| .pickup-item { | |||||
| display: flex; | |||||
| background-color: #fff; | |||||
| padding: 20rpx; | |||||
| margin-bottom: 20rpx; | |||||
| border-radius: 8rpx; | |||||
| .left { | |||||
| width: 160rpx; | |||||
| height: 160rpx; | |||||
| margin-right: 20rpx; | |||||
| .shop-image { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| border-radius: 8rpx; | |||||
| } | |||||
| } | |||||
| .center { | |||||
| flex: 1; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| justify-content: space-between; | |||||
| // gap: 8rpx; | |||||
| .shop-name { | |||||
| font-size: 32rpx; | |||||
| // font-weight: bold; | |||||
| margin-bottom: 10rpx; | |||||
| } | |||||
| .shop-address, .shop-phone { | |||||
| font-size: 24rpx; | |||||
| color: #999; | |||||
| display: flex; | |||||
| align-items: start; | |||||
| margin-bottom: 6rpx; | |||||
| gap: 8rpx; | |||||
| width: 90%; | |||||
| } | |||||
| } | |||||
| .right { | |||||
| width: 100rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| .select-btn { | |||||
| width: 90rpx; | |||||
| height: 60rpx; | |||||
| line-height: 60rpx; | |||||
| text-align: center; | |||||
| background-color: $uni-color; | |||||
| color: #fff; | |||||
| font-size: 24rpx; | |||||
| border-radius: 12rpx; | |||||
| padding: 0; | |||||
| } | |||||
| .select-btn-active { | |||||
| background-color: #106035; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,296 @@ | |||||
| <template> | |||||
| <view class="page"> | |||||
| <!-- 导航栏 --> | |||||
| <navbar title="订单售后" leftClick @leftClick="navigateBack" bgColor="#019245" color="#fff" /> | |||||
| <!-- 售后表单 --> | |||||
| <view class="after-sale-form"> | |||||
| <!-- 问题描述区域 --> | |||||
| <view class="form-section"> | |||||
| <view class="section-title"> | |||||
| <view class="title-indicator"></view> | |||||
| <text>请描述具体问题</text> | |||||
| </view> | |||||
| <view class="text-area-container"> | |||||
| <textarea class="problem-textarea" v-model="problemDescription" placeholder="请在此输入详细问题或意见" | |||||
| placeholder-style="color: #999; font-size: 28rpx;" maxlength="500" /> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 图片上传区域 --> | |||||
| <view class="form-section"> | |||||
| <view class="section-title"> | |||||
| <view class="title-indicator"></view> | |||||
| <text>请提供相关问题的截图或图片</text> | |||||
| </view> | |||||
| <view class="upload-area"> | |||||
| <view class="image-grid"> | |||||
| <view class="image-item" v-for="(image, index) in uploadedImages" :key="'img-'+index"> | |||||
| <image :src="image" mode="aspectFill" class="preview-image"></image> | |||||
| <view class="delete-icon" @click="deleteImage(index)"> | |||||
| <uv-icon name="close" color="#fff" size="24rpx"></uv-icon> | |||||
| </view> | |||||
| </view> | |||||
| <view class="upload-button" @click="chooseImage" v-if="uploadedImages.length < 9"> | |||||
| <uv-icon name="plus" size="60rpx" color="#019245"></uv-icon> | |||||
| <text>添加图片</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 联系方式 --> | |||||
| <view class="form-section"> | |||||
| <view class="section-title"> | |||||
| <view class="title-indicator"></view> | |||||
| <text>联系方式</text> | |||||
| </view> | |||||
| <view class="contact-info"> | |||||
| <input class="contact-tip" placeholder="留下联系方式,方便我们向您回复" /> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 提交按钮 --> | |||||
| <view class="submit-button" @click="submitAfterSale"> | |||||
| 提交 | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import navbar from '@/components/base/navbar.vue' | |||||
| export default { | |||||
| components: { | |||||
| navbar | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| orderId: '', | |||||
| problemDescription: '', | |||||
| uploadedImages: [], | |||||
| contactInfo: '15070023168', // 默认联系方式,实际应该从用户信息中获取 | |||||
| orderDetail: null | |||||
| } | |||||
| }, | |||||
| onLoad(options) { | |||||
| if (options.id) { | |||||
| this.orderId = options.id | |||||
| // 获取订单详情 | |||||
| this.getOrderDetail(options.id) | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 返回上一页 | |||||
| navigateBack() { | |||||
| uni.navigateBack() | |||||
| }, | |||||
| // 获取订单详情 | |||||
| getOrderDetail(id) { | |||||
| // 从上一页获取订单信息 | |||||
| const pages = getCurrentPages() | |||||
| const prevPage = pages[pages.length - 2] | |||||
| if (prevPage && prevPage.route.includes('order')) { | |||||
| // 查找匹配ID的订单 | |||||
| const foundOrder = prevPage.$vm.orderList.find(order => order.id === id) | |||||
| if (foundOrder) { | |||||
| this.orderDetail = foundOrder | |||||
| } | |||||
| } | |||||
| }, | |||||
| // 选择图片 | |||||
| chooseImage() { | |||||
| uni.chooseImage({ | |||||
| count: 9 - this.uploadedImages.length, | |||||
| sizeType: ['compressed'], | |||||
| sourceType: ['album', 'camera'], | |||||
| success: (res) => { | |||||
| // 预览图片 | |||||
| this.uploadedImages = [...this.uploadedImages, ...res.tempFilePaths] | |||||
| } | |||||
| }) | |||||
| }, | |||||
| // 删除图片 | |||||
| deleteImage(index) { | |||||
| this.uploadedImages.splice(index, 1) | |||||
| }, | |||||
| // 提交售后申请 | |||||
| submitAfterSale() { | |||||
| // 表单验证 | |||||
| if (!this.problemDescription.trim()) { | |||||
| uni.showToast({ | |||||
| title: '请描述您的问题', | |||||
| icon: 'none' | |||||
| }) | |||||
| return | |||||
| } | |||||
| // 显示提交中提示 | |||||
| uni.showLoading({ | |||||
| title: '正在提交...' | |||||
| }) | |||||
| // 模拟上传图片 | |||||
| setTimeout(() => { | |||||
| // 模拟表单提交 | |||||
| setTimeout(() => { | |||||
| uni.hideLoading() | |||||
| uni.showToast({ | |||||
| title: '提交成功', | |||||
| icon: 'success', | |||||
| duration: 2000 | |||||
| }) | |||||
| // 延迟后返回 | |||||
| setTimeout(() => { | |||||
| this.navigateBack() | |||||
| }, 1500) | |||||
| }, 1000) | |||||
| }, 1000) | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .page { | |||||
| background-color: #f5f5f5; | |||||
| min-height: 100vh; | |||||
| padding-bottom: 150rpx; | |||||
| } | |||||
| .after-sale-form { | |||||
| margin: 20rpx; | |||||
| } | |||||
| .form-section { | |||||
| // background-color: #fff; | |||||
| border-radius: 10rpx; | |||||
| padding: 30rpx; | |||||
| margin-bottom: 20rpx; | |||||
| .section-title { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| margin-bottom: 30rpx; | |||||
| .title-indicator { | |||||
| width: 8rpx; | |||||
| height: 30rpx; | |||||
| background-color: #019245; | |||||
| border-radius: 4rpx; | |||||
| margin-right: 16rpx; | |||||
| } | |||||
| text { | |||||
| font-size: 30rpx; | |||||
| font-weight: 500; | |||||
| } | |||||
| } | |||||
| } | |||||
| .text-area-container { | |||||
| background-color: #fff; | |||||
| border-radius: 8rpx; | |||||
| .problem-textarea { | |||||
| width: 100%; | |||||
| height: 200rpx; | |||||
| font-size: 28rpx; | |||||
| padding: 20rpx; | |||||
| } | |||||
| } | |||||
| .upload-area { | |||||
| background-color: #fff; | |||||
| padding: 30rpx; | |||||
| .image-grid { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| gap: 30rpx; | |||||
| } | |||||
| .image-item { | |||||
| width: 160rpx; | |||||
| height: 160rpx; | |||||
| position: relative; | |||||
| .preview-image { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| border-radius: 8rpx; | |||||
| } | |||||
| .delete-icon { | |||||
| position: absolute; | |||||
| top: -20rpx; | |||||
| right: -20rpx; | |||||
| width: 40rpx; | |||||
| height: 40rpx; | |||||
| background-color: rgba(0,0,0,0.6); | |||||
| border-radius: 50%; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| } | |||||
| } | |||||
| .upload-button { | |||||
| width: 160rpx; | |||||
| height: 160rpx; | |||||
| color: $uni-color; | |||||
| border: 4rpx dashed $uni-color; | |||||
| border-radius: 8rpx; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| // margin-right: 20rpx; | |||||
| // margin-bottom: 20rpx; | |||||
| font-size: 24rpx; | |||||
| gap: 10rpx; | |||||
| } | |||||
| } | |||||
| .contact-info { | |||||
| background-color: #fff; | |||||
| border-radius: 8rpx; | |||||
| padding: 30rpx; | |||||
| .contact-tip { | |||||
| font-size: 26rpx; | |||||
| color: #999; | |||||
| // margin-bottom: 10rpx; | |||||
| display: block; | |||||
| } | |||||
| .contact-value { | |||||
| font-size: 28rpx; | |||||
| color: #333; | |||||
| } | |||||
| } | |||||
| .submit-button { | |||||
| position: fixed; | |||||
| bottom: 30rpx; | |||||
| left: 50%; | |||||
| transform: translateX(-50%); | |||||
| width: 90%; | |||||
| height: 90rpx; | |||||
| background-color: #019245; | |||||
| color: #fff; | |||||
| font-size: 32rpx; | |||||
| border-radius: 45rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,554 @@ | |||||
| <template> | |||||
| <view class="page"> | |||||
| <!-- 导航栏 --> | |||||
| <navbar :title="orderStatus === 'pending' ? '待支付订单' : '订单详情' " leftClick @leftClick="navigateBack" bgColor="#019245" color="#fff" /> | |||||
| <!-- 店铺信息 --> | |||||
| <view class="shop-info"> | |||||
| <view class="shop-header"> | |||||
| <image class="shop-logo" :src="orderDetail.shopLogo" mode="aspectFill"></image> | |||||
| <view class="shop-name-container"> | |||||
| <text class="shop-name">{{orderDetail.shopName}}</text> | |||||
| <view class="shop-address"> | |||||
| <view style="padding-top: 7rpx;"> | |||||
| <!-- 需要置顶 --> | |||||
| <uv-icon name="map-fill" color="#019245" size="28rpx"></uv-icon> | |||||
| </view> | |||||
| <text class="address-text">{{orderDetail.shopAddress}}</text> | |||||
| </view> | |||||
| <view class="shop-phone"> | |||||
| <view style="padding-top: 7rpx;"> | |||||
| <!-- 需要置顶 --> | |||||
| <uv-icon name="phone-fill" color="#019245" size="28rpx"></uv-icon> | |||||
| </view> | |||||
| <text class="phone-text">{{orderDetail.shopPhone}}</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="order-status"> | |||||
| <!-- 商品列表 --> | |||||
| <view class="food-list"> | |||||
| <view class="food-item" v-for="(food, index) in showedFoods" :key="index"> | |||||
| <image class="food-image" :src="food.image" mode="aspectFill" /> | |||||
| <view class="food-info"> | |||||
| <text class="food-name">{{food.name}}</text> | |||||
| <view class="food-sold"> | |||||
| <uv-icon name="bag" size="28rpx"></uv-icon> | |||||
| <text>已售出 {{food.soldCount}}单</text> | |||||
| </view> | |||||
| <text class="food-price"> <text style="font-size: 20rpx;">¥</text> {{food.price.toFixed(1)}}</text> | |||||
| <text class="food-count">×{{food.count}}</text> | |||||
| </view> | |||||
| </view> | |||||
| <view class="expand-more" @click="showAllFoods = !showAllFoods" v-if="orderDetail.foods.length > 3"> | |||||
| <text>{{showAllFoods ? '收起' : '展开'}} (共{{orderDetail.foodCount}}个)</text> | |||||
| <uv-icon :name="showAllFoods ? 'arrow-up' : 'arrow-down'" size="28rpx"></uv-icon> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 订单信息 --> | |||||
| <view class="order-info"> | |||||
| <view class="info-item"> | |||||
| <text class="info-label">合计:</text> | |||||
| <text class="info-value price">¥{{orderDetail.totalPrice.toFixed(2)}}</text> | |||||
| </view> | |||||
| <view class="info-item"> | |||||
| <text class="info-label">创建时间:</text> | |||||
| <text class="info-value">{{orderDetail.orderTime}}</text> | |||||
| </view> | |||||
| <view class="info-item"> | |||||
| <text class="info-label">订单编号:</text> | |||||
| <text class="info-value">{{orderDetail.id}}</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="discount-info-container"> | |||||
| <!-- 优惠信息 --> | |||||
| <view class="discount-info"> | |||||
| <view class="discount-header"> | |||||
| <text>优惠</text> | |||||
| </view> | |||||
| <view class="discount-item"> | |||||
| <view class="discount-left"> | |||||
| <image src="@/static/image/券.webp" mode="aspectFill" class="coupon-icon" /> | |||||
| <view>新用户立减</view> | |||||
| </view> | |||||
| <text class="discount-amount">-¥2</text> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 备注 --> | |||||
| <view class="remark-section"> | |||||
| <view class="remark-header"> | |||||
| <text>备注</text> | |||||
| </view> | |||||
| <view class="remark-content"> | |||||
| <input type="text" v-model="orderDetail.remark" placeholder="请输入您要备注的内容" | |||||
| placeholder-style="font-size: 28rpx" /> | |||||
| <!-- <text>{{orderDetail.remark || '无备注信息'}}</text> --> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 支付方式 --> | |||||
| <uv-radio-group v-model="payMethod" v-if="orderStatus === 'pending'"> | |||||
| <view class="payment-methods"> | |||||
| <view class="payment-item"> | |||||
| <uv-icon name="weixin-circle-fill" size="70rpx" color="#019245"></uv-icon> | |||||
| <text class="payment-name">微信支付</text> | |||||
| <uv-radio activeColor="#019245" size="40rpx" name="weixin"></uv-radio> | |||||
| </view> | |||||
| <view class="payment-item"> | |||||
| <uv-icon name="red-packet" size="70rpx" color="#019245"></uv-icon> | |||||
| <text class="payment-name">账户余额<text class="balance-text">(余额: ¥0)</text></text> | |||||
| <uv-radio activeColor="#019245" size="40rpx" name="account"></uv-radio> | |||||
| </view> | |||||
| </view> | |||||
| </uv-radio-group> | |||||
| <!-- 底部支付栏 --> | |||||
| <view class="bottom-bar"> | |||||
| <view class="total-section"> | |||||
| <text class="total-label">共{{orderDetail.foodCount}}个,<text style="color: black;">合计</text> </text> | |||||
| <text class="total-price">¥{{(orderDetail.totalPrice - 2).toFixed(1)}}</text> | |||||
| </view> | |||||
| <view class="pay-button" @click="handlePay" v-if="orderStatus === 'pending'">立即下单</view> | |||||
| <view class="pay-button" @click="handlePay" v-if="orderStatus === 'delivered'">立即取餐</view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import navbar from '@/components/base/navbar.vue' | |||||
| export default { | |||||
| components: { | |||||
| navbar | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| id: '', | |||||
| payMethod: 'weixin', | |||||
| showAllFoods: false, | |||||
| orderStatus: '', | |||||
| orderDetail: { | |||||
| id: '324563256386532', | |||||
| status: 'pending', | |||||
| shopName: '轻奢时代芙蓉兴盛', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| shopAddress: '长沙市雨花区时代阳光大道轻奢时代芙蓉兴盛', | |||||
| shopPhone: '15070023168', | |||||
| foods: [ | |||||
| { | |||||
| id: 1, | |||||
| name: '茄子肉沫', | |||||
| image: '/static/image/红烧肉.png', | |||||
| price: 9.9, | |||||
| count: 1, | |||||
| soldCount: 100 | |||||
| }, | |||||
| { | |||||
| id: 2, | |||||
| name: '豆角炒鸡蛋', | |||||
| image: '/static/image/红烧肉.png', | |||||
| price: 9.9, | |||||
| count: 1, | |||||
| soldCount: 100 | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| name: '酸辣土豆丝', | |||||
| image: '/static/image/红烧肉.png', | |||||
| price: 9.9, | |||||
| count: 1, | |||||
| soldCount: 100 | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| name: '酸辣土豆丝', | |||||
| image: '/static/image/红烧肉.png', | |||||
| price: 9.9, | |||||
| count: 1, | |||||
| soldCount: 100 | |||||
| }, | |||||
| { | |||||
| id: 3, | |||||
| name: '酸辣土豆丝', | |||||
| image: '/static/image/红烧肉.png', | |||||
| price: 9.9, | |||||
| count: 1, | |||||
| soldCount: 100 | |||||
| } | |||||
| ], | |||||
| foodCount: 10, | |||||
| orderTime: '2025-04-09 14:32:46', | |||||
| totalPrice: 88.00, | |||||
| remark: '' | |||||
| } | |||||
| } | |||||
| }, | |||||
| computed: { | |||||
| statusText() { | |||||
| const statusMap = { | |||||
| 'pending': '等待支付', | |||||
| 'processing': '正在出餐', | |||||
| 'shipping': '正在配送中', | |||||
| 'delivered': '已送达,等待取餐', | |||||
| 'completed': '订单已完成', | |||||
| 'canceled': '订单已取消' | |||||
| } | |||||
| return statusMap[this.orderDetail.status] || '等待支付' | |||||
| }, | |||||
| showedFoods() { | |||||
| return this.showAllFoods ? this.orderDetail.foods : this.orderDetail.foods.slice(0, 3) | |||||
| } | |||||
| }, | |||||
| onLoad(options) { | |||||
| // 获取订单ID | |||||
| if (options.id) { | |||||
| this.id = options.id | |||||
| // 这里应该根据ID从服务器获取订单详情 | |||||
| // this.getOrderDetail(this.id) | |||||
| // 这里假设是从订单列表页面跳转过来获取的订单状态 | |||||
| this.orderStatus = options.status | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 返回上一页 | |||||
| navigateBack() { | |||||
| uni.navigateBack() | |||||
| }, | |||||
| // 获取订单详情 | |||||
| getOrderDetail(id) { | |||||
| // 这里应该是API请求 | |||||
| // 目前使用模拟数据 | |||||
| }, | |||||
| // 处理支付 | |||||
| handlePay() { | |||||
| uni.showLoading({ | |||||
| title: '支付处理中...' | |||||
| }) | |||||
| // 模拟支付过程 | |||||
| setTimeout(() => { | |||||
| uni.hideLoading() | |||||
| uni.showToast({ | |||||
| title: '支付成功', | |||||
| icon: 'success', | |||||
| duration: 2000 | |||||
| }) | |||||
| // 支付成功后,跳转回订单列表页面,并刷新 | |||||
| setTimeout(() => { | |||||
| this.navigateBack() | |||||
| // 页面栈中的order页面需要刷新 | |||||
| const pages = getCurrentPages() | |||||
| const prevPage = pages[pages.length - 2] | |||||
| if (prevPage && prevPage.route.includes('order')) { | |||||
| // 更新上一页的数据 | |||||
| prevPage.$vm.loadMockOrders() | |||||
| prevPage.$vm.filterOrdersByStatus(1) // 切换到待出餐Tab | |||||
| prevPage.$vm.current = 1 // 更新Tab索引 | |||||
| } | |||||
| }, 1000) | |||||
| }, 2000) | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .page { | |||||
| background-color: #f5f5f5; | |||||
| min-height: 100vh; | |||||
| padding-bottom: 120rpx; | |||||
| } | |||||
| .status-bar { | |||||
| background-color: #019245; | |||||
| padding: 30rpx; | |||||
| color: #fff; | |||||
| font-size: 32rpx; | |||||
| font-weight: 500; | |||||
| } | |||||
| .shop-info { | |||||
| background-color: #fff; | |||||
| margin: 20rpx; | |||||
| border-radius: 16rpx; | |||||
| padding: 20rpx; | |||||
| .shop-header { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| // background-color: red; | |||||
| .shop-logo { | |||||
| width: 150rpx; | |||||
| height: 150rpx; | |||||
| border-radius: 10rpx; | |||||
| margin-right: 20rpx; | |||||
| } | |||||
| .shop-name-container { | |||||
| flex: 1; | |||||
| .shop-name { | |||||
| font-size: 30rpx; | |||||
| font-weight: 500; | |||||
| margin-bottom: 10rpx; | |||||
| display: block; | |||||
| } | |||||
| .shop-address, .shop-phone { | |||||
| display: flex; | |||||
| align-items: start; | |||||
| font-size: 24rpx; | |||||
| color: $uni-color-third; | |||||
| margin-top: 8rpx; | |||||
| .address-text, .phone-text { | |||||
| margin-left: 8rpx; | |||||
| width: 80%; | |||||
| white-space: wrap; | |||||
| // overflow: hidden; | |||||
| // text-overflow: ellipsis; | |||||
| } | |||||
| } | |||||
| .shop-address-top{ | |||||
| display: flex; | |||||
| align-items: start; | |||||
| background-color: red; | |||||
| // gap: 10rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .order-status{ | |||||
| background-color: #fff; | |||||
| margin: 20rpx; | |||||
| border-radius: 16rpx; | |||||
| padding: 20rpx; | |||||
| .food-list { | |||||
| // gap: 20rpx; | |||||
| // background-color: #019245; | |||||
| .food-item { | |||||
| display: flex; | |||||
| margin-bottom: 20rpx; | |||||
| // background-color: red; | |||||
| .food-image { | |||||
| width: 120rpx; | |||||
| height: 120rpx; | |||||
| border-radius: 10rpx; | |||||
| margin-right: 20rpx; | |||||
| } | |||||
| .food-info { | |||||
| flex: 1; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| justify-content: space-between; | |||||
| position: relative; | |||||
| .food-name { | |||||
| font-size: 28rpx; | |||||
| font-weight: 500; | |||||
| } | |||||
| .food-sold { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| font-size: 24rpx; | |||||
| color: $uni-color-third; | |||||
| } | |||||
| .food-price { | |||||
| font-size: 28rpx; | |||||
| color: #f00; | |||||
| } | |||||
| .food-count { | |||||
| color: black; | |||||
| position: absolute; | |||||
| bottom: 50%; | |||||
| right: 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| .expand-more { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| padding: 20rpx 0 0; | |||||
| font-size: 24rpx; | |||||
| color: $uni-color-third; | |||||
| } | |||||
| } | |||||
| .order-info { | |||||
| padding-top: 20rpx; | |||||
| .info-item { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| margin-bottom: 15rpx; | |||||
| font-size: 26rpx; | |||||
| .info-label { | |||||
| color: black; | |||||
| } | |||||
| .info-value { | |||||
| color: #333; | |||||
| &.price { | |||||
| color: #f00; | |||||
| font-weight: 500; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .discount-info-container { | |||||
| background-color: #fff; | |||||
| margin: 20rpx; | |||||
| border-radius: 16rpx; | |||||
| padding: 20rpx; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| gap: 40rpx; | |||||
| } | |||||
| .discount-info { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: space-between; | |||||
| .discount-header { | |||||
| font-size: 28rpx; | |||||
| } | |||||
| .discount-item { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| align-items: center; | |||||
| gap: 20rpx; | |||||
| .discount-left { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| gap: 10rpx; | |||||
| .coupon-icon { | |||||
| width: 36rpx; | |||||
| height: 36rpx; | |||||
| margin-top: 6rpx; | |||||
| } | |||||
| } | |||||
| .discount-amount { | |||||
| color: #f00; | |||||
| font-weight: 500; | |||||
| } | |||||
| } | |||||
| } | |||||
| .remark-section { | |||||
| display: flex; | |||||
| // flex-direction: column; | |||||
| gap: 40rpx; | |||||
| // background-color: red; | |||||
| align-items: center; | |||||
| .remark-header { | |||||
| font-size: 28rpx; | |||||
| // font-weight: 500; | |||||
| } | |||||
| .remark-content { | |||||
| font-size: 26rpx; | |||||
| color: black; | |||||
| min-height: 60rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| } | |||||
| .payment-methods { | |||||
| background-color: #fff; | |||||
| width: 100%; | |||||
| margin: 20rpx; | |||||
| border-radius: 16rpx; | |||||
| padding: 20rpx; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| gap: 20rpx; | |||||
| .payment-item { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| padding: 20rpx 0; | |||||
| border-bottom: 1rpx solid #f5f5f5; | |||||
| &:last-child { | |||||
| border-bottom: none; | |||||
| } | |||||
| .payment-name { | |||||
| flex: 1; | |||||
| margin-left: 20rpx; | |||||
| font-size: 28rpx; | |||||
| .balance-text { | |||||
| font-size: 24rpx; | |||||
| color: $uni-color-third; | |||||
| margin-left: 10rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .bottom-bar { | |||||
| position: fixed; | |||||
| bottom: 0; | |||||
| left: 0; | |||||
| right: 0; | |||||
| height: 100rpx; | |||||
| background-color: #fff; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| padding: 0 30rpx; | |||||
| box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); | |||||
| .total-section { | |||||
| flex: 1; | |||||
| .total-label { | |||||
| font-size: 26rpx; | |||||
| color: $uni-color-third; | |||||
| } | |||||
| .total-price { | |||||
| font-size: 32rpx; | |||||
| color: #f00; | |||||
| margin-left: 10rpx; | |||||
| } | |||||
| } | |||||
| .pay-button { | |||||
| width: 240rpx; | |||||
| height: 80rpx; | |||||
| background-color: #019245; | |||||
| color: #fff; | |||||
| font-size: 30rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| border-radius: 40rpx; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,123 @@ | |||||
| export default [ | |||||
| { | |||||
| id: '20241223184523001', | |||||
| shopName: '轻奢时代芙蓉兴盛', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| foods: [ | |||||
| { id: 1, name: '红烧肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 2, name: '青椒炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 3, name: '香菇炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 4, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 5, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 6, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 7, name: '豆角炒肉', image: '/static/image/红烧肉.png' } | |||||
| ], | |||||
| foodCount: 10, | |||||
| orderTime: '2024-12-23 18:45:23', | |||||
| totalPrice: 88.00, | |||||
| status: 'pending' | |||||
| }, | |||||
| { | |||||
| id: '20241223184523001', | |||||
| shopName: '轻奢时代芙蓉兴盛', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| foods: [ | |||||
| { id: 1, name: '红烧肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 2, name: '青椒炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 3, name: '香菇炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 4, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 5, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 6, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 7, name: '豆角炒肉', image: '/static/image/红烧肉.png' } | |||||
| ], | |||||
| foodCount: 10, | |||||
| orderTime: '2024-12-23 18:45:23', | |||||
| totalPrice: 88.00, | |||||
| status: 'pending' | |||||
| }, | |||||
| { | |||||
| id: '20241223184523001', | |||||
| shopName: '轻奢时代芙蓉兴盛', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| foods: [ | |||||
| { id: 1, name: '红烧肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 2, name: '青椒炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 3, name: '香菇炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 4, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 5, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 6, name: '豆角炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 7, name: '豆角炒肉', image: '/static/image/红烧肉.png' } | |||||
| ], | |||||
| foodCount: 10, | |||||
| orderTime: '2024-12-23 18:45:23', | |||||
| totalPrice: 88.00, | |||||
| status: 'pending' | |||||
| }, | |||||
| { | |||||
| id: '20241223184523002', | |||||
| shopName: '爷爷不泡茶奶茶店(鲁北路)', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| foods: [ | |||||
| { id: 1, name: '红烧肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 2, name: '青椒炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 3, name: '香菇炒肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 4, name: '豆角炒肉', image: '/static/image/红烧肉.png' } | |||||
| ], | |||||
| foodCount: 10, | |||||
| orderTime: '2024-12-23 18:45:23', | |||||
| totalPrice: 88.00, | |||||
| status: 'pending' | |||||
| }, | |||||
| { | |||||
| id: '20241223184523003', | |||||
| shopName: '芙蓉兴盛小文轩便利店', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| foods: [ | |||||
| { id: 5, name: '回锅肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 6, name: '豆角炒鸡蛋', image: '/static/image/红烧肉.png' } | |||||
| ], | |||||
| foodCount: 4, | |||||
| orderTime: '2024-12-23 17:30:15', | |||||
| totalPrice: 45.50, | |||||
| status: 'processing' | |||||
| }, | |||||
| { | |||||
| id: '20241223184523003', | |||||
| shopName: '晨光文具店', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| foods: [ | |||||
| { id: 5, name: '回锅肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 6, name: '豆角炒鸡蛋', image: '/static/image/红烧肉.png' } | |||||
| ], | |||||
| foodCount: 4, | |||||
| orderTime: '2024-12-23 17:30:15', | |||||
| totalPrice: 45.50, | |||||
| status: 'shipping' | |||||
| }, | |||||
| { | |||||
| id: '20241223184523003', | |||||
| shopName: 'KFC肯德基中山路店', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| foods: [ | |||||
| { id: 5, name: '回锅肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 6, name: '豆角炒鸡蛋', image: '/static/image/红烧肉.png' } | |||||
| ], | |||||
| foodCount: 4, | |||||
| orderTime: '2024-12-23 17:30:15', | |||||
| totalPrice: 45.50, | |||||
| status: 'delivered' | |||||
| }, | |||||
| { | |||||
| id: '20241223184523003', | |||||
| shopName: '轩宇蛋炒饭', | |||||
| shopLogo: '/static/image/古茗店面.webp', | |||||
| foods: [ | |||||
| { id: 5, name: '回锅肉', image: '/static/image/红烧肉.png' }, | |||||
| { id: 6, name: '豆角炒鸡蛋', image: '/static/image/红烧肉.png' } | |||||
| ], | |||||
| foodCount: 4, | |||||
| orderTime: '2024-12-23 17:30:15', | |||||
| totalPrice: 45.50, | |||||
| status: 'completed' | |||||
| }, | |||||
| ]; | |||||