小吃街
This commit is contained in:
parent
6488aa837d
commit
2d979e821e
|
|
@ -36,11 +36,12 @@
|
|||
<el-input v-model="form.name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="菜品照片" prop="photo">
|
||||
<el-input v-model="form.photo" placeholder="照片地址" />
|
||||
<el-upload action="/api/upload/image" :headers="uploadHeaders" :show-file-list="false"
|
||||
:on-success="(res) => form.photo = res.url" accept="image/*" style="margin-top: 8px;">
|
||||
<el-button size="small">上传照片</el-button>
|
||||
:on-success="(res) => form.photo = res.url" accept="image/*">
|
||||
<el-image v-if="form.photo" :src="form.photo" style="width: 120px; height: 120px; cursor: pointer; border-radius: 8px;" fit="cover" />
|
||||
<el-button v-else size="small">上传照片</el-button>
|
||||
</el-upload>
|
||||
<el-button v-if="form.photo" size="small" text type="danger" style="margin-top: 4px;" @click="form.photo = ''">移除</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="价格" prop="price">
|
||||
<el-input-number v-model="form.price" :min="0" :precision="2" :step="1" />
|
||||
|
|
|
|||
|
|
@ -5,32 +5,33 @@
|
|||
<el-button type="primary" @click="openDialog()">新增门店</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="list" v-loading="loading" border>
|
||||
<el-table-column label="照片" width="100">
|
||||
<el-table :data="list" v-loading="loading" border stripe>
|
||||
<el-table-column label="照片" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-image :src="row.photo" style="width: 60px; height: 60px;" fit="cover" />
|
||||
<el-image :src="row.photo" style="width: 80px; height: 80px; border-radius: 8px;" fit="cover" :preview-src-list="[row.photo]" preview-teleported />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="门店名称" width="140" />
|
||||
<el-table-column prop="location" label="位置" show-overflow-tooltip />
|
||||
<el-table-column prop="packingFeeType" label="打包费类型" width="120">
|
||||
<el-table-column prop="name" label="门店名称" min-width="120" />
|
||||
<el-table-column prop="location" label="位置" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="打包费" width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.packingFeeType === 'Fixed' ? '总打包费' : '单份打包费' }}
|
||||
<span>{{ row.packingFeeType === 'Fixed' ? '总打包费' : '单份' }} ¥{{ row.packingFeeAmount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="packingFeeAmount" label="打包费金额" width="110" />
|
||||
<el-table-column prop="dishCount" label="菜品数" width="80" />
|
||||
<el-table-column label="状态" width="80">
|
||||
<el-table-column prop="dishCount" label="菜品数" width="80" align="center" />
|
||||
<el-table-column label="状态" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.isEnabled ? 'success' : 'info'" size="small">{{ row.isEnabled ? '启用' : '禁用' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="260" fixed="right">
|
||||
<el-table-column label="操作" width="300" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="openDialog(row)">编辑</el-button>
|
||||
<el-button size="small" @click="manageBanners(row)">Banner</el-button>
|
||||
<el-button size="small" type="primary" @click="$router.push(`/shops/${row.id}/dishes`)">菜品</el-button>
|
||||
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
|
||||
<div style="display: flex; gap: 4px; justify-content: center; flex-wrap: nowrap;">
|
||||
<el-button size="small" @click="openDialog(row)">编辑</el-button>
|
||||
<el-button size="small" @click="manageBanners(row)">Banner</el-button>
|
||||
<el-button size="small" type="primary" @click="$router.push(`/shops/${row.id}/dishes`)">菜品</el-button>
|
||||
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
|
@ -42,11 +43,12 @@
|
|||
<el-input v-model="form.name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="门店照片" prop="photo">
|
||||
<el-input v-model="form.photo" placeholder="照片地址" />
|
||||
<el-upload action="/api/upload/image" :headers="uploadHeaders" :show-file-list="false"
|
||||
:on-success="(res) => form.photo = res.url" accept="image/*" style="margin-top: 8px;">
|
||||
<el-button size="small">上传照片</el-button>
|
||||
:on-success="(res) => form.photo = res.url" accept="image/*">
|
||||
<el-image v-if="form.photo" :src="form.photo" style="width: 120px; height: 120px; cursor: pointer; border-radius: 8px;" fit="cover" />
|
||||
<el-button v-else size="small">上传照片</el-button>
|
||||
</el-upload>
|
||||
<el-button v-if="form.photo" size="small" text type="danger" style="margin-top: 4px;" @click="form.photo = ''">移除</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="门店位置" prop="location">
|
||||
<el-input v-model="form.location" />
|
||||
|
|
|
|||
|
|
@ -224,12 +224,11 @@ export default {
|
|||
|
||||
/* 顶部大图 */
|
||||
.top-banner {
|
||||
padding: 20rpx 24rpx 0;
|
||||
width: 100%;
|
||||
}
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
height: 330rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ export default {
|
|||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-end;
|
||||
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
|
|
@ -375,17 +375,19 @@ export default {
|
|||
font-size: 32rpx;
|
||||
color: #e64340;
|
||||
font-weight: bold;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 240rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
background-color: #007AFF;
|
||||
background-color: #FAD146;
|
||||
color: #ffffff;
|
||||
font-size: 30rpx;
|
||||
border-radius: 40rpx;
|
||||
border: none;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.submit-btn[disabled] {
|
||||
|
|
|
|||
|
|
@ -19,17 +19,18 @@
|
|||
|
||||
<!-- 门店列表 -->
|
||||
<view class="shop-list">
|
||||
<view
|
||||
class="shop-card"
|
||||
v-for="shop in shops"
|
||||
:key="shop.id"
|
||||
@click="goShopDetail(shop.id)"
|
||||
>
|
||||
<view class="shop-card" v-for="shop in shops" :key="shop.id" @click="goShopDetail(shop.id)">
|
||||
<image class="shop-photo" :src="shop.photo" mode="aspectFill"></image>
|
||||
<view class="shop-info">
|
||||
<text class="shop-name">{{ shop.name }}</text>
|
||||
<text class="shop-location">{{ shop.location }}</text>
|
||||
<text class="shop-dish-count">{{ shop.dishCount || 0 }} 种美食</text>
|
||||
<view class="info-row">
|
||||
<image class="info-icon" src="/static/ic_address.png" mode="aspectFit"></image>
|
||||
<text class="info-text">{{ shop.location || '暂无位置信息' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<image class="info-icon" src="/static/ic_delicacy.png" mode="aspectFit"></image>
|
||||
<text class="info-text">{{ shop.dishCount || 0 }}种美食</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -67,20 +68,13 @@ export default {
|
|||
if (res?.value) this.bannerUrl = res.value
|
||||
} catch (e) {}
|
||||
},
|
||||
/** 加载门店列表 */
|
||||
async loadShops() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await getShops()
|
||||
this.shops = res || []
|
||||
} catch (e) {
|
||||
// 错误已在 request 中处理
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
} catch (e) {} finally { this.loading = false }
|
||||
},
|
||||
|
||||
/** 跳转门店详情 */
|
||||
goShopDetail(id) {
|
||||
uni.navigateTo({ url: `/pages/food/shop-detail?id=${id}` })
|
||||
}
|
||||
|
|
@ -89,6 +83,11 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
.food-page {
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 自定义导航栏 */
|
||||
.custom-navbar {
|
||||
position: fixed;
|
||||
|
|
@ -127,61 +126,83 @@ export default {
|
|||
|
||||
/* 顶部大图 */
|
||||
.top-banner {
|
||||
padding: 0 24rpx 0;
|
||||
margin-bottom: 20rpx;
|
||||
width: 100%;
|
||||
}
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
height: 280rpx;
|
||||
border-radius: 20rpx;
|
||||
height: 360rpx;
|
||||
}
|
||||
|
||||
.food-page {
|
||||
padding: 24rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
/* 门店列表 */
|
||||
.shop-list {
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.shop-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
overflow: hidden;
|
||||
padding: 24rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.shop-card:first-child {
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.shop-card:last-child {
|
||||
border-radius: 0 0 20rpx 20rpx;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.shop-card:first-child:last-child {
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.shop-photo {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.shop-info {
|
||||
flex: 1;
|
||||
padding: 20rpx 24rpx;
|
||||
padding-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
font-size: 30rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 12rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.shop-location {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.shop-dish-count {
|
||||
font-size: 24rpx;
|
||||
color: #007AFF;
|
||||
.info-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-right: 8rpx;
|
||||
margin-top: 4rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.info-text {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -11,64 +11,63 @@
|
|||
</view>
|
||||
</view>
|
||||
<view :style="{ height: (statusBarHeight + 44) + 'px' }"></view>
|
||||
|
||||
<!-- 门店 Banner -->
|
||||
<swiper
|
||||
v-if="shop.banners && shop.banners.length > 0"
|
||||
class="shop-banner"
|
||||
indicator-dots
|
||||
autoplay
|
||||
circular
|
||||
indicator-color="rgba(255,255,255,0.5)"
|
||||
indicator-active-color="#ffffff"
|
||||
>
|
||||
<swiper v-if="shop.banners && shop.banners.length > 0" class="shop-banner" indicator-dots autoplay circular
|
||||
indicator-color="rgba(255,255,255,0.5)" indicator-active-color="#ffffff">
|
||||
<swiper-item v-for="(banner, index) in shop.banners" :key="index">
|
||||
<image class="banner-image" :src="banner.imageUrl" mode="aspectFill"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<!-- 门店注意事项 -->
|
||||
<!-- 门店信息卡片 -->
|
||||
<view class="shop-info-card">
|
||||
<image class="shop-avatar" :src="shop.photo || '/static/ic_default.png'" mode="aspectFill"></image>
|
||||
<view class="shop-info-text">
|
||||
<text class="shop-name">{{ shop.name }}</text>
|
||||
<view class="shop-location-row">
|
||||
<image class="location-icon" src="/static/ic_address.png" mode="aspectFit"></image>
|
||||
<text class="shop-location">{{ shop.location || '暂无位置信息' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 注意事项 -->
|
||||
<view v-if="shop.notice" class="notice-section">
|
||||
<text class="notice-label">注意事项</text>
|
||||
<text class="notice-text">{{ shop.notice }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 菜品列表 -->
|
||||
<view class="dish-section">
|
||||
<text class="section-title">美食列表</text>
|
||||
<view class="dish-list">
|
||||
<view class="dish-item" v-for="dish in dishes" :key="dish.id">
|
||||
<image class="dish-photo" :src="dish.photo" mode="aspectFill"></image>
|
||||
<view class="dish-info">
|
||||
<text class="dish-name">{{ dish.name }}</text>
|
||||
<text class="dish-price">¥{{ dish.price.toFixed(2) }}</text>
|
||||
</view>
|
||||
<!-- 加减按钮(购物车功能在 18.3 中实现) -->
|
||||
<view class="dish-actions">
|
||||
<view
|
||||
class="action-btn minus-btn"
|
||||
v-if="getQuantity(dish.id) > 0"
|
||||
@click="onMinus(dish)"
|
||||
>
|
||||
<text class="action-text">-</text>
|
||||
</view>
|
||||
<text class="dish-quantity" v-if="getQuantity(dish.id) > 0">
|
||||
{{ getQuantity(dish.id) }}
|
||||
</text>
|
||||
<view class="action-btn plus-btn" @click="onPlus(dish)">
|
||||
<text class="action-text">+</text>
|
||||
<view class="dish-list">
|
||||
<view class="dish-item" v-for="dish in dishes" :key="dish.id">
|
||||
<image class="dish-photo" :src="dish.photo" mode="aspectFill"></image>
|
||||
<view class="dish-info">
|
||||
<text class="dish-name">{{ dish.name }}</text>
|
||||
<view class="dish-bottom">
|
||||
<text class="dish-price">¥{{ dish.price.toFixed(1) }}</text>
|
||||
<view class="dish-actions">
|
||||
<view class="action-btn minus-btn" v-if="getQuantity(dish.id) > 0" @click="onMinus(dish)">
|
||||
<text class="action-text">-</text>
|
||||
</view>
|
||||
<text class="dish-quantity"
|
||||
v-if="getQuantity(dish.id) > 0">{{ getQuantity(dish.id) }}</text>
|
||||
<view class="action-btn plus-btn" @click="onPlus(dish)">
|
||||
<text class="action-text">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部购物车栏(购物车功能在 18.3 中完善) -->
|
||||
<view class="cart-bar" v-if="cartTotalCount > 0">
|
||||
<view class="cart-info" @click="showCartPopup = true">
|
||||
<text class="cart-count">{{ cartTotalCount }} 件</text>
|
||||
<text class="cart-price">¥{{ cartTotalPrice }}</text>
|
||||
<!-- 底部购物车栏 -->
|
||||
<view class="cart-bar">
|
||||
<view class="cart-left" @click="cartTotalCount > 0 && (showCartPopup = true)">
|
||||
<image class="cart-icon" src="/static/ic_courier.png" mode="aspectFit"></image>
|
||||
<text class="cart-price">¥ {{ cartTotalCount > 0 ? cartTotalPrice : '0' }}</text>
|
||||
</view>
|
||||
<button class="cart-checkout-btn" @click="goCheckout">去结算</button>
|
||||
<button class="cart-checkout-btn" :class="{ disabled: cartTotalCount === 0 }"
|
||||
@click="goCheckout">去结算</button>
|
||||
</view>
|
||||
|
||||
<!-- 购物车弹窗 -->
|
||||
|
|
@ -82,9 +81,8 @@
|
|||
<view class="cart-popup-item" v-for="item in cartItems" :key="item.dish.id">
|
||||
<image class="cart-item-photo" :src="item.dish.photo" mode="aspectFill"></image>
|
||||
<view class="cart-item-info">
|
||||
<text class="cart-item-shop">{{ shop.name }}</text>
|
||||
<text class="cart-item-name">{{ item.dish.name }}</text>
|
||||
<text class="cart-item-price">¥{{ item.dish.price.toFixed(2) }}</text>
|
||||
<text class="cart-item-price">¥{{ item.dish.price.toFixed(1) }}</text>
|
||||
</view>
|
||||
<view class="dish-actions">
|
||||
<view class="action-btn minus-btn" @click="onMinus(item.dish)">
|
||||
|
|
@ -97,7 +95,6 @@
|
|||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 额外费用和总价 -->
|
||||
<view class="cart-popup-footer">
|
||||
<view class="cart-fee-row" v-if="packingFee > 0">
|
||||
<text class="cart-fee-label">打包费</text>
|
||||
|
|
@ -114,421 +111,472 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { getShopDetail } from '../../utils/api'
|
||||
import { useCartStore } from '../../stores/cart'
|
||||
import {
|
||||
getShopDetail
|
||||
} from '../../utils/api'
|
||||
import {
|
||||
useCartStore
|
||||
} from '../../stores/cart'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
shop: {},
|
||||
dishes: [],
|
||||
showCartPopup: false,
|
||||
statusBarHeight: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 获取购物车 store */
|
||||
cartStore() {
|
||||
return useCartStore()
|
||||
},
|
||||
/** 购物车中的商品列表 */
|
||||
cartItems() {
|
||||
return this.cartStore.items
|
||||
},
|
||||
/** 购物车总数量 */
|
||||
cartTotalCount() {
|
||||
return this.cartStore.totalCount
|
||||
},
|
||||
/** 购物车商品总价(不含打包费) */
|
||||
cartTotalPrice() {
|
||||
return this.cartStore.totalPrice.toFixed(2)
|
||||
},
|
||||
/** 打包费计算 */
|
||||
packingFee() {
|
||||
if (!this.shop.packingFeeType) return 0
|
||||
if (this.shop.packingFeeType === 'Fixed') {
|
||||
return this.cartTotalCount > 0 ? (this.shop.packingFeeAmount || 0) : 0
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
shop: {},
|
||||
dishes: [],
|
||||
showCartPopup: false,
|
||||
statusBarHeight: 0
|
||||
}
|
||||
// PerItem 模式:份数 × 单价
|
||||
return this.cartTotalCount * (this.shop.packingFeeAmount || 0)
|
||||
},
|
||||
/** 含打包费的总价 */
|
||||
cartTotalPriceWithFee() {
|
||||
return (parseFloat(this.cartTotalPrice) + this.packingFee).toFixed(2)
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 0
|
||||
if (options.id) {
|
||||
this.loadShopDetail(options.id)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() { uni.navigateBack() },
|
||||
/** 加载门店详情 */
|
||||
async loadShopDetail(id) {
|
||||
try {
|
||||
const res = await getShopDetail(id)
|
||||
this.shop = res || {}
|
||||
this.dishes = res.dishes || []
|
||||
// 保存门店信息到购物车 store
|
||||
this.cartStore.setShopInfo({
|
||||
id: this.shop.id,
|
||||
name: this.shop.name,
|
||||
packingFeeType: this.shop.packingFeeType,
|
||||
packingFeeAmount: this.shop.packingFeeAmount
|
||||
computed: {
|
||||
cartStore() {
|
||||
return useCartStore()
|
||||
},
|
||||
cartItems() {
|
||||
return this.cartStore.items
|
||||
},
|
||||
cartTotalCount() {
|
||||
return this.cartStore.totalCount
|
||||
},
|
||||
cartTotalPrice() {
|
||||
return this.cartStore.totalPrice.toFixed(2)
|
||||
},
|
||||
packingFee() {
|
||||
if (!this.shop.packingFeeType) return 0
|
||||
if (this.shop.packingFeeType === 'Fixed')
|
||||
return this.cartTotalCount > 0 ? (this.shop.packingFeeAmount || 0) : 0
|
||||
return this.cartTotalCount * (this.shop.packingFeeAmount || 0)
|
||||
},
|
||||
cartTotalPriceWithFee() {
|
||||
return (parseFloat(this.cartTotalPrice) + this.packingFee).toFixed(2)
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 0
|
||||
if (options.id) this.loadShopDetail(options.id)
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
async loadShopDetail(id) {
|
||||
try {
|
||||
const res = await getShopDetail(id)
|
||||
this.shop = res || {}
|
||||
this.dishes = res.dishes || []
|
||||
this.cartStore.setShopInfo({
|
||||
id: this.shop.id,
|
||||
name: this.shop.name,
|
||||
packingFeeType: this.shop.packingFeeType,
|
||||
packingFeeAmount: this.shop.packingFeeAmount
|
||||
})
|
||||
} catch (e) {}
|
||||
},
|
||||
getQuantity(dishId) {
|
||||
return this.cartStore.getQuantity(dishId)
|
||||
},
|
||||
onPlus(dish) {
|
||||
this.cartStore.addItem(dish)
|
||||
},
|
||||
onMinus(dish) {
|
||||
this.cartStore.removeItem(dish.id)
|
||||
},
|
||||
clearCart() {
|
||||
this.cartStore.clearCart();
|
||||
this.showCartPopup = false
|
||||
},
|
||||
goCheckout() {
|
||||
if (this.cartTotalCount === 0) return
|
||||
uni.navigateTo({
|
||||
url: '/pages/food/food-order'
|
||||
})
|
||||
} catch (e) {
|
||||
// 错误已在 request 中处理
|
||||
}
|
||||
},
|
||||
|
||||
/** 获取菜品在购物车中的数量 */
|
||||
getQuantity(dishId) {
|
||||
return this.cartStore.getQuantity(dishId)
|
||||
},
|
||||
|
||||
/** 添加菜品 */
|
||||
onPlus(dish) {
|
||||
this.cartStore.addItem(dish)
|
||||
},
|
||||
|
||||
/** 减少菜品 */
|
||||
onMinus(dish) {
|
||||
this.cartStore.removeItem(dish.id)
|
||||
},
|
||||
|
||||
/** 清空购物车 */
|
||||
clearCart() {
|
||||
this.cartStore.clearCart()
|
||||
this.showCartPopup = false
|
||||
},
|
||||
|
||||
/** 去结算 */
|
||||
goCheckout() {
|
||||
if (this.cartTotalCount === 0) return
|
||||
uni.navigateTo({ url: '/pages/food/food-order' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 自定义导航栏 */
|
||||
.custom-navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
background: #FFB700;
|
||||
}
|
||||
.navbar-content {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
.nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
.navbar-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #363636;
|
||||
}
|
||||
.nav-placeholder {
|
||||
width: 60rpx;
|
||||
}
|
||||
.shop-detail-page {
|
||||
padding-bottom: 140rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.shop-detail-page {
|
||||
padding-bottom: 140rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.shop-banner {
|
||||
width: 100%;
|
||||
height: 360rpx;
|
||||
}
|
||||
/* 自定义导航栏 */
|
||||
.custom-navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
background: #FFB700;
|
||||
}
|
||||
|
||||
.banner-image {
|
||||
width: 100%;
|
||||
height: 360rpx;
|
||||
}
|
||||
.navbar-content {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.notice-section {
|
||||
margin: 20rpx 24rpx;
|
||||
background-color: #fff8e6;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
}
|
||||
.nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.notice-label {
|
||||
font-size: 26rpx;
|
||||
color: #e6a23c;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8rpx;
|
||||
display: block;
|
||||
}
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.notice-text {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
.navbar-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.dish-section {
|
||||
margin: 0 24rpx;
|
||||
}
|
||||
.nav-placeholder {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
margin-bottom: 20rpx;
|
||||
display: block;
|
||||
}
|
||||
/* Banner */
|
||||
.shop-banner {
|
||||
width: 100%;
|
||||
height: 360rpx;
|
||||
}
|
||||
|
||||
.dish-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #ffffff;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 16rpx;
|
||||
padding: 16rpx;
|
||||
}
|
||||
.banner-image {
|
||||
width: 100%;
|
||||
height: 360rpx;
|
||||
}
|
||||
|
||||
.dish-photo {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 8rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
/* 门店信息卡片 */
|
||||
.shop-info-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.dish-info {
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.shop-avatar {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dish-name {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
.shop-info-text {
|
||||
flex: 1;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.dish-price {
|
||||
font-size: 28rpx;
|
||||
color: #e64340;
|
||||
font-weight: bold;
|
||||
}
|
||||
.shop-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 12rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dish-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.shop-location-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.location-icon {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
margin-right: 6rpx;
|
||||
margin-top: 4rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.minus-btn {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
.shop-location {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.plus-btn {
|
||||
background-color: #007AFF;
|
||||
}
|
||||
/* 注意事项 */
|
||||
.notice-section {
|
||||
padding: 16rpx 24rpx;
|
||||
background: #fff;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 32rpx;
|
||||
line-height: 48rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.notice-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.minus-btn .action-text {
|
||||
color: #666666;
|
||||
}
|
||||
/* 菜品列表 */
|
||||
.dish-list {
|
||||
margin-top: 20rpx;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.plus-btn .action-text {
|
||||
color: #ffffff;
|
||||
}
|
||||
.dish-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
padding: 24rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.dish-quantity {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
min-width: 48rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.dish-item:first-child {
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
}
|
||||
|
||||
/* 底部购物车栏 */
|
||||
.cart-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100rpx;
|
||||
background-color: #333333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 30rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
.dish-item:last-child {
|
||||
border-radius: 0 0 20rpx 20rpx;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cart-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.dish-item:first-child:last-child {
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.cart-count {
|
||||
font-size: 28rpx;
|
||||
color: #ffffff;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.dish-photo {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cart-price {
|
||||
font-size: 32rpx;
|
||||
color: #e64340;
|
||||
font-weight: bold;
|
||||
}
|
||||
.dish-info {
|
||||
flex: 1;
|
||||
padding-left: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
min-height: 140rpx;
|
||||
}
|
||||
|
||||
.cart-checkout-btn {
|
||||
width: 200rpx;
|
||||
height: 72rpx;
|
||||
line-height: 72rpx;
|
||||
background-color: #007AFF;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
border-radius: 36rpx;
|
||||
border: none;
|
||||
text-align: center;
|
||||
}
|
||||
.dish-name {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 购物车弹窗 */
|
||||
.cart-popup-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.dish-bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.cart-popup {
|
||||
width: 100%;
|
||||
max-height: 70vh;
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.dish-price {
|
||||
font-size: 32rpx;
|
||||
color: #FF6B00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.cart-popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
.dish-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cart-popup-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
.action-btn {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cart-popup-clear {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
}
|
||||
.minus-btn {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.cart-popup-list {
|
||||
max-height: 50vh;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
.plus-btn {
|
||||
background: #FF8C00;
|
||||
}
|
||||
|
||||
.cart-popup-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
.action-text {
|
||||
font-size: 36rpx;
|
||||
line-height: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.cart-item-photo {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 8rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.minus-btn .action-text {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.cart-item-info {
|
||||
flex: 1;
|
||||
padding: 0 16rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.plus-btn .action-text {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.cart-item-shop {
|
||||
font-size: 22rpx;
|
||||
color: #999999;
|
||||
}
|
||||
.dish-quantity {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
min-width: 48rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cart-item-name {
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
}
|
||||
/* 底部购物车栏 */
|
||||
.cart-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 110rpx;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 24rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.cart-item-price {
|
||||
font-size: 26rpx;
|
||||
color: #e64340;
|
||||
}
|
||||
.cart-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cart-popup-footer {
|
||||
padding: 16rpx 30rpx;
|
||||
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
.cart-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.cart-fee-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8rpx 0;
|
||||
}
|
||||
.cart-price {
|
||||
font-size: 36rpx;
|
||||
color: #FF6B00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.cart-fee-label {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
}
|
||||
.cart-checkout-btn {
|
||||
width: 220rpx;
|
||||
height: 72rpx;
|
||||
line-height: 72rpx;
|
||||
background: linear-gradient(135deg, #FFB700, #FF9500);
|
||||
color: #fff;
|
||||
font-size: 28rpx;
|
||||
border-radius: 36rpx;
|
||||
border: none;
|
||||
text-align: center;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.cart-fee-value {
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.cart-checkout-btn.disabled {
|
||||
background: #e0e0e0;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.cart-fee-total {
|
||||
font-size: 32rpx;
|
||||
color: #e64340;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
/* 购物车弹窗 */
|
||||
.cart-popup-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.cart-popup {
|
||||
width: 100%;
|
||||
max-height: 60vh;
|
||||
background: #fff;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cart-popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.cart-popup-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.cart-popup-clear {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.cart-popup-list {
|
||||
max-height: 50vh;
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cart-popup-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.cart-item-photo {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 8rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cart-item-info {
|
||||
flex: 1;
|
||||
padding: 0 16rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.cart-item-name {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.cart-item-price {
|
||||
font-size: 26rpx;
|
||||
color: #FF6B00;
|
||||
}
|
||||
|
||||
.cart-popup-footer {
|
||||
padding: 16rpx 30rpx;
|
||||
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.cart-fee-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8rpx 0;
|
||||
}
|
||||
|
||||
.cart-fee-label {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.cart-fee-value {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.cart-fee-total {
|
||||
font-size: 32rpx;
|
||||
color: #FF6B00;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -21,9 +21,10 @@
|
|||
<view class="form-section">
|
||||
<!-- 1.要做的事情 -->
|
||||
<view class="form-group">
|
||||
<text class="form-label">1.要做的事情</text>
|
||||
<text class="form-label">1.万能帮事项</text>
|
||||
<view class="input-box textarea-box">
|
||||
<textarea v-model="form.itemName" placeholder="请描述您需要帮忙做的事情" placeholder-class="placeholder" :maxlength="500" />
|
||||
<textarea v-model="form.itemName" placeholder="请输入需要做什么事,需详细描述" placeholder-class="placeholder"
|
||||
:maxlength="500" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -31,16 +32,17 @@
|
|||
<view class="form-group">
|
||||
<text class="form-label">2.如何联系您?</text>
|
||||
<view class="input-box">
|
||||
<input v-model="form.phone" type="number" placeholder="请输入手机号,对方接单后才能看到" placeholder-class="placeholder" maxlength="11" />
|
||||
<input v-model="form.phone" type="number" placeholder="请输入手机号,对方接单后才能看到"
|
||||
placeholder-class="placeholder" maxlength="11" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 3.商品总金额 -->
|
||||
<view class="form-group">
|
||||
<text class="form-label">3.商品总金额</text>
|
||||
<text class="form-tip">需包含商品总额和包装费等额外费用</text>
|
||||
<view class="input-box">
|
||||
<input v-model="form.goodsAmount" type="digit" placeholder="请输入商品总金额" placeholder-class="placeholder" />
|
||||
<input v-model="form.goodsAmount" type="digit" placeholder="请输入代购商品总金额,包含可能存在的包装费等"
|
||||
placeholder-class="placeholder" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -48,7 +50,8 @@
|
|||
<view class="form-group">
|
||||
<text class="form-label">4.跑腿佣金</text>
|
||||
<view class="input-box">
|
||||
<input v-model="form.commission" type="digit" placeholder="请输入跑腿佣金,最低1.0元" placeholder-class="placeholder" />
|
||||
<input v-model="form.commission" type="digit" placeholder="请输入跑腿佣金,若涉及购买,需包含商品金额"
|
||||
placeholder-class="placeholder" />
|
||||
</view>
|
||||
<text class="form-tip">佣金先由平台保管,接单方完成订单后才会收到佣金</text>
|
||||
</view>
|
||||
|
|
@ -65,263 +68,307 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { createOrder, getPageBanner } from '../../utils/api'
|
||||
import {
|
||||
createOrder,
|
||||
getPageBanner
|
||||
} from '../../utils/api'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
itemName: '',
|
||||
phone: '',
|
||||
goodsAmount: '',
|
||||
commission: ''
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
itemName: '',
|
||||
phone: '',
|
||||
goodsAmount: '',
|
||||
commission: ''
|
||||
},
|
||||
submitting: false,
|
||||
statusBarHeight: 0,
|
||||
bannerUrl: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 支付金额 = 商品总金额 + 跑腿佣金 */
|
||||
payAmount() {
|
||||
const goods = parseFloat(this.form.goodsAmount) || 0
|
||||
const commission = parseFloat(this.form.commission) || 0
|
||||
return (goods + commission).toFixed(1)
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 0
|
||||
this.loadBanner()
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
submitting: false,
|
||||
statusBarHeight: 0,
|
||||
bannerUrl: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 支付金额 = 商品总金额 + 跑腿佣金 */
|
||||
payAmount() {
|
||||
const goods = parseFloat(this.form.goodsAmount) || 0
|
||||
const commission = parseFloat(this.form.commission) || 0
|
||||
return (goods + commission).toFixed(1)
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 0
|
||||
this.loadBanner()
|
||||
},
|
||||
methods: {
|
||||
goBack() { uni.navigateBack() },
|
||||
async loadBanner() {
|
||||
try {
|
||||
const res = await getPageBanner('help')
|
||||
if (res?.value) this.bannerUrl = res.value
|
||||
} catch (e) {}
|
||||
},
|
||||
/** 校验佣金 */
|
||||
validateCommission() {
|
||||
const val = this.form.commission
|
||||
if (!val) {
|
||||
uni.showToast({ title: '请输入跑腿佣金', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
const num = parseFloat(val)
|
||||
if (isNaN(num) || num < 1.0) {
|
||||
uni.showToast({ title: '跑腿佣金不可低于1.0元', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
if (val.includes('.') && val.split('.')[1].length > 1) {
|
||||
uni.showToast({ title: '佣金最多支持小数点后1位', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
/** 校验表单 */
|
||||
validateForm() {
|
||||
if (!this.form.itemName.trim()) {
|
||||
uni.showToast({ title: '请描述需要帮忙做的事情', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
if (!this.form.phone.trim()) {
|
||||
uni.showToast({ title: '请输入手机号', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
if (!this.form.goodsAmount) {
|
||||
uni.showToast({ title: '请输入商品总金额', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
const goodsNum = parseFloat(this.form.goodsAmount)
|
||||
if (isNaN(goodsNum) || goodsNum <= 0) {
|
||||
uni.showToast({ title: '请输入正确的商品总金额', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
return this.validateCommission()
|
||||
},
|
||||
/** 提交订单 */
|
||||
async onSubmit() {
|
||||
if (!this.validateForm()) return
|
||||
async loadBanner() {
|
||||
try {
|
||||
const res = await getPageBanner('help')
|
||||
if (res?.value) this.bannerUrl = res.value
|
||||
} catch (e) {}
|
||||
},
|
||||
/** 校验佣金 */
|
||||
validateCommission() {
|
||||
const val = this.form.commission
|
||||
if (!val) {
|
||||
uni.showToast({
|
||||
title: '请输入跑腿佣金',
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
}
|
||||
const num = parseFloat(val)
|
||||
if (isNaN(num) || num < 1.0) {
|
||||
uni.showToast({
|
||||
title: '跑腿佣金不可低于1.0元',
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
}
|
||||
if (val.includes('.') && val.split('.')[1].length > 1) {
|
||||
uni.showToast({
|
||||
title: '佣金最多支持小数点后1位',
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
/** 校验表单 */
|
||||
validateForm() {
|
||||
if (!this.form.itemName.trim()) {
|
||||
uni.showToast({
|
||||
title: '请描述需要帮忙做的事情',
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
}
|
||||
if (!this.form.phone.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入手机号',
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
}
|
||||
if (!this.form.goodsAmount) {
|
||||
uni.showToast({
|
||||
title: '请输入商品总金额',
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
}
|
||||
const goodsNum = parseFloat(this.form.goodsAmount)
|
||||
if (isNaN(goodsNum) || goodsNum <= 0) {
|
||||
uni.showToast({
|
||||
title: '请输入正确的商品总金额',
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
}
|
||||
return this.validateCommission()
|
||||
},
|
||||
/** 提交订单 */
|
||||
async onSubmit() {
|
||||
if (!this.validateForm()) return
|
||||
|
||||
// 未登录跳转登录页
|
||||
const token = uni.getStorageSync('token')
|
||||
if (!token) {
|
||||
uni.navigateTo({ url: '/pages/login/login' })
|
||||
return
|
||||
}
|
||||
// 未登录跳转登录页
|
||||
const token = uni.getStorageSync('token')
|
||||
if (!token) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.submitting = true
|
||||
try {
|
||||
const commission = parseFloat(this.form.commission)
|
||||
const goodsAmount = parseFloat(this.form.goodsAmount)
|
||||
const result = await createOrder({
|
||||
orderType: 'Help',
|
||||
itemName: this.form.itemName.trim(),
|
||||
phone: this.form.phone.trim(),
|
||||
goodsAmount,
|
||||
commission,
|
||||
totalAmount: goodsAmount + commission
|
||||
this.submitting = true
|
||||
try {
|
||||
const commission = parseFloat(this.form.commission)
|
||||
const goodsAmount = parseFloat(this.form.goodsAmount)
|
||||
const result = await createOrder({
|
||||
orderType: 'Help',
|
||||
itemName: this.form.itemName.trim(),
|
||||
phone: this.form.phone.trim(),
|
||||
goodsAmount,
|
||||
commission,
|
||||
totalAmount: goodsAmount + commission
|
||||
})
|
||||
if (result.paymentParams) await this.wxPay(result.paymentParams)
|
||||
uni.showToast({
|
||||
title: '下单成功',
|
||||
icon: 'success'
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
} catch (e) {} finally {
|
||||
this.submitting = false
|
||||
}
|
||||
},
|
||||
/** 调用微信支付 */
|
||||
wxPay(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.requestPayment({
|
||||
...params,
|
||||
success: resolve,
|
||||
fail: (err) => {
|
||||
if (err.errMsg !== 'requestPayment:fail cancel')
|
||||
uni.showToast({
|
||||
title: '支付失败',
|
||||
icon: 'none'
|
||||
})
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
if (result.paymentParams) await this.wxPay(result.paymentParams)
|
||||
uni.showToast({ title: '下单成功', icon: 'success' })
|
||||
setTimeout(() => { uni.navigateBack() }, 1500)
|
||||
} catch (e) {} finally { this.submitting = false }
|
||||
},
|
||||
/** 调用微信支付 */
|
||||
wxPay(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.requestPayment({
|
||||
...params, success: resolve,
|
||||
fail: (err) => {
|
||||
if (err.errMsg !== 'requestPayment:fail cancel')
|
||||
uni.showToast({ title: '支付失败', icon: 'none' })
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.order-page {
|
||||
padding-bottom: 40rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.order-page {
|
||||
padding-bottom: 40rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 自定义导航栏 */
|
||||
.custom-navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
background: #FFB700;
|
||||
}
|
||||
.navbar-content {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
.nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
.navbar-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #363636;
|
||||
}
|
||||
.nav-placeholder {
|
||||
width: 60rpx;
|
||||
}
|
||||
/* 自定义导航栏 */
|
||||
.custom-navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
background: #FFB700;
|
||||
}
|
||||
|
||||
/* 顶部大图 */
|
||||
.top-banner {
|
||||
padding: 20rpx 24rpx 0;
|
||||
}
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
height: 280rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
.navbar-content {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
.form-section {
|
||||
padding: 10rpx 24rpx 0;
|
||||
}
|
||||
.nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.navbar-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 24rpx;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.nav-placeholder {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.input-box input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
/* 顶部大图 */
|
||||
.top-banner {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.textarea-box {
|
||||
height: 240rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
height: 330rpx;
|
||||
}
|
||||
|
||||
.textarea-box textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
/* 表单区域 */
|
||||
.form-section {
|
||||
padding: 10rpx 24rpx 0;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 12rpx;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
/* 支付金额 + 提交按钮 */
|
||||
.submit-section {
|
||||
padding: 20rpx 24rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
.form-label {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.pay-amount {
|
||||
font-size: 32rpx;
|
||||
color: #e64340;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.input-box {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 24rpx;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 96rpx;
|
||||
line-height: 96rpx;
|
||||
background: #FAD146;
|
||||
color: #ffffff;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
border-radius: 10rpx;
|
||||
border: none;
|
||||
text-align: center;
|
||||
}
|
||||
.input-box input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.submit-btn[disabled] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
</style>
|
||||
.textarea-box {
|
||||
height: 240rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.textarea-box textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 12rpx;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 支付金额 + 提交按钮 */
|
||||
.submit-section {
|
||||
padding: 20rpx 24rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.pay-amount {
|
||||
font-size: 32rpx;
|
||||
color: #e64340;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 96rpx;
|
||||
line-height: 96rpx;
|
||||
background: #FAD146;
|
||||
color: #ffffff;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
border-radius: 10rpx;
|
||||
border: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.submit-btn[disabled] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -37,38 +37,63 @@
|
|||
<view v-else-if="orders.length === 0" class="empty-tip">暂无订单</view>
|
||||
|
||||
<view v-for="order in orders" :key="order.id" class="order-card">
|
||||
<!-- 标题行:物品名 + 跑腿费 -->
|
||||
<view class="card-title-row">
|
||||
<text class="card-item-name">{{ getItemTitle(order) }}</text>
|
||||
<view class="card-commission">
|
||||
<text class="commission-label">跑腿费:</text>
|
||||
<text class="commission-value">{{ order.commission }}元</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 信息行 -->
|
||||
<view class="card-body">
|
||||
<view class="info-row" v-if="order.pickupLocation">
|
||||
<view class="dot green"></view>
|
||||
<text class="info-text">取货地址:{{ order.pickupLocation }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="order.deliveryLocation">
|
||||
<view class="dot orange"></view>
|
||||
<text class="info-text">送达地址:{{ order.deliveryLocation }}</text>
|
||||
</view>
|
||||
<!-- 万能帮:特殊卡片布局 -->
|
||||
<template v-if="order.orderType === 'Help'">
|
||||
<view class="info-row remark-row">
|
||||
<image class="remark-icon" src="/static/ic_modify.png" mode="aspectFit"></image>
|
||||
<text class="info-text">备注信息:{{ order.remark || '无' }}</text>
|
||||
<text class="info-text">备注信息:{{ order.itemName || '无' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card-footer" style="margin-top: 20rpx;">
|
||||
<view class="help-commission">
|
||||
<text class="help-commission-label">跑腿费(含其他费用):</text>
|
||||
<text class="commission-value">{{ getHelpTotalAmount(order) }}元</text>
|
||||
</view>
|
||||
<view class="footer-spacer"></view>
|
||||
<button class="accept-btn" size="mini" @click="onAcceptClick(order)">接单</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 接单按钮 -->
|
||||
<view class="card-footer">
|
||||
<view class="footer-spacer"></view>
|
||||
<button v-if="order.orderType === 'Food'" class="accept-btn" size="mini"
|
||||
@click="viewFoodDetail(order)">查看详情</button>
|
||||
<button v-else class="accept-btn" size="mini" @click="onAcceptClick(order)">接单</button>
|
||||
</view>
|
||||
<!-- 其他类型:默认卡片布局 -->
|
||||
<template v-else>
|
||||
<!-- 标题行:物品名 + 跑腿费 -->
|
||||
<view class="card-title-row">
|
||||
<text class="card-item-name">{{ getItemTitle(order) }}</text>
|
||||
<view class="card-commission">
|
||||
<text class="commission-label">跑腿费:</text>
|
||||
<text class="commission-value">{{ order.commission }}元</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 代购:垫付商品金额 -->
|
||||
<view class="goods-amount-row" v-if="order.orderType === 'Purchase' && order.goodsAmount">
|
||||
<text class="goods-amount-label">垫付商品金额:</text>
|
||||
<text class="goods-amount-value">¥{{ order.goodsAmount }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 信息行 -->
|
||||
<view class="card-body">
|
||||
<view class="info-row" v-if="order.pickupLocation">
|
||||
<view class="dot green"></view>
|
||||
<text class="info-text">取货地址:{{ order.pickupLocation }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="order.deliveryLocation">
|
||||
<view class="dot orange"></view>
|
||||
<text class="info-text">送达地址:{{ order.deliveryLocation }}</text>
|
||||
</view>
|
||||
<view class="info-row remark-row">
|
||||
<image class="remark-icon" src="/static/ic_modify.png" mode="aspectFit"></image>
|
||||
<text class="info-text">备注信息:{{ order.remark || '无' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 接单按钮 -->
|
||||
<view class="card-footer">
|
||||
<view class="footer-spacer"></view>
|
||||
<button v-if="order.orderType === 'Food'" class="accept-btn" size="mini"
|
||||
@click="viewFoodDetail(order)">查看详情</button>
|
||||
<button v-else class="accept-btn" size="mini" @click="onAcceptClick(order)">接单</button>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
|
|
@ -235,6 +260,12 @@
|
|||
this.loadOrders()
|
||||
},
|
||||
loadMore() {},
|
||||
/** 获取万能帮总费用(佣金+商品金额) */
|
||||
getHelpTotalAmount(order) {
|
||||
const commission = parseFloat(order.commission) || 0
|
||||
const goodsAmount = parseFloat(order.goodsAmount) || 0
|
||||
return (commission + goodsAmount).toFixed(1)
|
||||
},
|
||||
/** 获取卡片标题 */
|
||||
getItemTitle(order) {
|
||||
const typeMap = {
|
||||
|
|
@ -246,7 +277,7 @@
|
|||
}
|
||||
const prefix = typeMap[order.orderType] || ''
|
||||
if (order.orderType === 'Food') return `美食街订单(${order.shopCount || 0}家)`
|
||||
if (order.orderType === 'Help') return `万能帮:${order.remark || ''}`
|
||||
if (order.orderType === 'Help') return `万能帮:${order.itemName || ''}`
|
||||
return `${prefix}:${order.itemName || ''}`
|
||||
},
|
||||
viewFoodDetail(order) {
|
||||
|
|
@ -477,9 +508,28 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
/* 代购垫付金额 */
|
||||
.goods-amount-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.goods-amount-label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.goods-amount-value {
|
||||
font-size: 30rpx;
|
||||
color: #FF6B00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card-item-name {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
|
|
@ -490,7 +540,7 @@
|
|||
|
||||
.card-commission {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
|
@ -505,6 +555,17 @@
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 万能帮跑腿费 */
|
||||
.help-commission {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.help-commission-label {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 信息行 */
|
||||
.card-body {
|
||||
margin-bottom: 20rpx;
|
||||
|
|
@ -544,8 +605,8 @@
|
|||
}
|
||||
|
||||
.info-text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
/* 卡片底部 */
|
||||
|
|
|
|||
|
|
@ -231,12 +231,11 @@ export default {
|
|||
|
||||
/* 顶部大图 */
|
||||
.top-banner {
|
||||
padding: 20rpx 24rpx 0;
|
||||
width: 100%;
|
||||
}
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
height: 330rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
/* 表单区域 */
|
||||
|
|
|
|||
|
|
@ -40,26 +40,30 @@
|
|||
<view class="form-group">
|
||||
<text class="form-label">4.备注信息</text>
|
||||
<view class="input-box textarea-box">
|
||||
<textarea v-model="form.remark" placeholder="请输入备注信息,如规格、数量、品牌等" placeholder-class="placeholder" :maxlength="200" />
|
||||
<textarea v-model="form.remark" placeholder="请输入备注信息,如规格、数量、品牌等" placeholder-class="placeholder"
|
||||
:maxlength="200" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="form-label">5.如何联系您?</text>
|
||||
<view class="input-box">
|
||||
<input v-model="form.phone" type="number" placeholder="请输入手机号,对方接单后才能看到" placeholder-class="placeholder" maxlength="11" />
|
||||
<input v-model="form.phone" type="number" placeholder="请输入手机号,对方接单后才能看到"
|
||||
placeholder-class="placeholder" maxlength="11" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="form-label">6.商品总金额</text>
|
||||
<view class="input-box">
|
||||
<input v-model="form.goodsAmount" type="digit" placeholder="请输入商品总金额" placeholder-class="placeholder" />
|
||||
<input v-model="form.goodsAmount" type="digit" placeholder="请输入商品总金额"
|
||||
placeholder-class="placeholder" />
|
||||
</view>
|
||||
<text class="form-tip">需包含商品总额和包装费等额外费用</text>
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="form-label">7.跑腿佣金</text>
|
||||
<view class="input-box">
|
||||
<input v-model="form.commission" type="digit" placeholder="请输入跑腿佣金,最低1.0元" placeholder-class="placeholder" />
|
||||
<input v-model="form.commission" type="digit" placeholder="请输入跑腿佣金,最低1.0元"
|
||||
placeholder-class="placeholder" />
|
||||
</view>
|
||||
<text class="form-tip">佣金先由平台保管,接单方完成订单后才会收到佣金</text>
|
||||
</view>
|
||||
|
|
@ -76,136 +80,316 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { createOrder, getPageBanner } from '../../utils/api'
|
||||
import {
|
||||
createOrder,
|
||||
getPageBanner
|
||||
} from '../../utils/api'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
itemName: '',
|
||||
pickupLocation: '',
|
||||
deliveryLocation: '',
|
||||
remark: '',
|
||||
phone: '',
|
||||
goodsAmount: '',
|
||||
commission: ''
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
itemName: '',
|
||||
pickupLocation: '',
|
||||
deliveryLocation: '',
|
||||
remark: '',
|
||||
phone: '',
|
||||
goodsAmount: '',
|
||||
commission: ''
|
||||
},
|
||||
submitting: false,
|
||||
statusBarHeight: 0,
|
||||
bannerUrl: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 支付金额 = 商品总金额 + 跑腿佣金 */
|
||||
payAmount() {
|
||||
const goods = parseFloat(this.form.goodsAmount) || 0
|
||||
const commission = parseFloat(this.form.commission) || 0
|
||||
return (goods + commission).toFixed(1)
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 0
|
||||
this.loadBanner()
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
submitting: false,
|
||||
statusBarHeight: 0,
|
||||
bannerUrl: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/** 支付金额 = 商品总金额 + 跑腿佣金 */
|
||||
payAmount() {
|
||||
const goods = parseFloat(this.form.goodsAmount) || 0
|
||||
const commission = parseFloat(this.form.commission) || 0
|
||||
return (goods + commission).toFixed(1)
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const sysInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = sysInfo.statusBarHeight || 0
|
||||
this.loadBanner()
|
||||
},
|
||||
methods: {
|
||||
goBack() { uni.navigateBack() },
|
||||
async loadBanner() {
|
||||
try {
|
||||
const res = await getPageBanner('purchase')
|
||||
if (res?.value) this.bannerUrl = res.value
|
||||
} catch (e) {}
|
||||
},
|
||||
validateCommission() {
|
||||
const val = this.form.commission
|
||||
if (!val) { uni.showToast({ title: '请输入跑腿佣金', icon: 'none' }); return false }
|
||||
const num = parseFloat(val)
|
||||
if (isNaN(num) || num < 1.0) { uni.showToast({ title: '跑腿佣金不可低于1.0元', icon: 'none' }); return false }
|
||||
if (val.includes('.') && val.split('.')[1].length > 1) { uni.showToast({ title: '佣金最多支持小数点后1位', icon: 'none' }); return false }
|
||||
return true
|
||||
},
|
||||
validateForm() {
|
||||
if (!this.form.itemName.trim()) { uni.showToast({ title: '请输入代购物品', icon: 'none' }); return false }
|
||||
if (!this.form.pickupLocation.trim()) { uni.showToast({ title: '请输入买货地点', icon: 'none' }); return false }
|
||||
if (!this.form.deliveryLocation.trim()) { uni.showToast({ title: '请输入送达地点', icon: 'none' }); return false }
|
||||
if (!this.form.phone.trim()) { uni.showToast({ title: '请输入手机号', icon: 'none' }); return false }
|
||||
if (!this.form.goodsAmount) { uni.showToast({ title: '请输入商品总金额', icon: 'none' }); return false }
|
||||
const goodsNum = parseFloat(this.form.goodsAmount)
|
||||
if (isNaN(goodsNum) || goodsNum <= 0) { uni.showToast({ title: '请输入正确的商品总金额', icon: 'none' }); return false }
|
||||
return this.validateCommission()
|
||||
},
|
||||
async onSubmit() {
|
||||
if (!this.validateForm()) return
|
||||
const token = uni.getStorageSync('token')
|
||||
if (!token) { uni.navigateTo({ url: '/pages/login/login' }); return }
|
||||
this.submitting = true
|
||||
try {
|
||||
const commission = parseFloat(this.form.commission)
|
||||
const goodsAmount = parseFloat(this.form.goodsAmount)
|
||||
const result = await createOrder({
|
||||
orderType: 'Purchase',
|
||||
itemName: this.form.itemName.trim(),
|
||||
pickupLocation: this.form.pickupLocation.trim(),
|
||||
deliveryLocation: this.form.deliveryLocation.trim(),
|
||||
remark: this.form.remark.trim(),
|
||||
phone: this.form.phone.trim(),
|
||||
goodsAmount, commission,
|
||||
totalAmount: goodsAmount + commission
|
||||
async loadBanner() {
|
||||
try {
|
||||
const res = await getPageBanner('purchase')
|
||||
if (res?.value) this.bannerUrl = res.value
|
||||
} catch (e) {}
|
||||
},
|
||||
validateCommission() {
|
||||
const val = this.form.commission
|
||||
if (!val) {
|
||||
uni.showToast({
|
||||
title: '请输入跑腿佣金',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
const num = parseFloat(val)
|
||||
if (isNaN(num) || num < 1.0) {
|
||||
uni.showToast({
|
||||
title: '跑腿佣金不可低于1.0元',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
if (val.includes('.') && val.split('.')[1].length > 1) {
|
||||
uni.showToast({
|
||||
title: '佣金最多支持小数点后1位',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
validateForm() {
|
||||
if (!this.form.itemName.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入代购物品',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
if (!this.form.pickupLocation.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入买货地点',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
if (!this.form.deliveryLocation.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入送达地点',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
if (!this.form.phone.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入手机号',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
if (!this.form.goodsAmount) {
|
||||
uni.showToast({
|
||||
title: '请输入商品总金额',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
const goodsNum = parseFloat(this.form.goodsAmount)
|
||||
if (isNaN(goodsNum) || goodsNum <= 0) {
|
||||
uni.showToast({
|
||||
title: '请输入正确的商品总金额',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
return this.validateCommission()
|
||||
},
|
||||
async onSubmit() {
|
||||
if (!this.validateForm()) return
|
||||
const token = uni.getStorageSync('token')
|
||||
if (!token) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/login/login'
|
||||
});
|
||||
return
|
||||
}
|
||||
this.submitting = true
|
||||
try {
|
||||
const commission = parseFloat(this.form.commission)
|
||||
const goodsAmount = parseFloat(this.form.goodsAmount)
|
||||
const result = await createOrder({
|
||||
orderType: 'Purchase',
|
||||
itemName: this.form.itemName.trim(),
|
||||
pickupLocation: this.form.pickupLocation.trim(),
|
||||
deliveryLocation: this.form.deliveryLocation.trim(),
|
||||
remark: this.form.remark.trim(),
|
||||
phone: this.form.phone.trim(),
|
||||
goodsAmount,
|
||||
commission,
|
||||
totalAmount: goodsAmount + commission
|
||||
})
|
||||
if (result.paymentParams) await this.wxPay(result.paymentParams)
|
||||
uni.showToast({
|
||||
title: '下单成功',
|
||||
icon: 'success'
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
} catch (e) {} finally {
|
||||
this.submitting = false
|
||||
}
|
||||
},
|
||||
wxPay(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.requestPayment({
|
||||
...params,
|
||||
success: resolve,
|
||||
fail: (err) => {
|
||||
if (err.errMsg !== 'requestPayment:fail cancel')
|
||||
uni.showToast({
|
||||
title: '支付失败',
|
||||
icon: 'none'
|
||||
})
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
if (result.paymentParams) await this.wxPay(result.paymentParams)
|
||||
uni.showToast({ title: '下单成功', icon: 'success' })
|
||||
setTimeout(() => { uni.navigateBack() }, 1500)
|
||||
} catch (e) {} finally { this.submitting = false }
|
||||
},
|
||||
wxPay(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.requestPayment({
|
||||
...params, success: resolve,
|
||||
fail: (err) => {
|
||||
if (err.errMsg !== 'requestPayment:fail cancel')
|
||||
uni.showToast({ title: '支付失败', icon: 'none' })
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.order-page {
|
||||
padding-bottom: 40rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.custom-navbar {
|
||||
position: fixed; top: 0; left: 0; width: 100%; z-index: 999; background: #FFB700;
|
||||
}
|
||||
.navbar-content {
|
||||
height: 44px; display: flex; align-items: center; justify-content: space-between; padding: 0 20rpx;
|
||||
}
|
||||
.nav-back { width: 60rpx; height: 60rpx; display: flex; align-items: center; justify-content: center; }
|
||||
.back-icon { width: 40rpx; height: 40rpx; }
|
||||
.navbar-title { font-size: 34rpx; font-weight: bold; color: #363636; }
|
||||
.nav-placeholder { width: 60rpx; }
|
||||
.top-banner { padding: 20rpx 24rpx 0; }
|
||||
.banner-img { width: 100%; height: 280rpx; border-radius: 20rpx; }
|
||||
.form-section { padding: 10rpx 24rpx 0; }
|
||||
.form-group { margin-bottom: 24rpx; }
|
||||
.form-label { font-size: 30rpx; color: #333333; font-weight: bold; display: block; margin-bottom: 16rpx; }
|
||||
.input-box {
|
||||
background-color: #ffffff; border-radius: 16rpx; padding: 0 24rpx; height: 88rpx; display: flex; align-items: center;
|
||||
}
|
||||
.input-box input { width: 100%; height: 100%; font-size: 28rpx; color: #333; }
|
||||
.textarea-box { height: 240rpx; padding: 20rpx 24rpx; align-items: flex-start; }
|
||||
.textarea-box textarea { width: 100%; height: 100%; font-size: 28rpx; color: #333; }
|
||||
.form-tip { font-size: 24rpx; color: #999999; margin-top: 12rpx; display: block; text-align: center; }
|
||||
.submit-section { padding: 20rpx 24rpx; padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); }
|
||||
.pay-amount { font-size: 32rpx; color: #e64340; font-weight: bold; display: block; text-align: center; margin-bottom: 20rpx; }
|
||||
.submit-btn {
|
||||
width: 100%; height: 96rpx; line-height: 96rpx; background: #FAD146; color: #ffffff;
|
||||
font-size: 32rpx; font-weight: bold; border-radius: 10rpx; border: none; text-align: center;
|
||||
}
|
||||
.submit-btn[disabled] { opacity: 0.6; }
|
||||
</style>
|
||||
.order-page {
|
||||
padding-bottom: 40rpx;
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.custom-navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
background: #FFB700;
|
||||
}
|
||||
|
||||
.navbar-content {
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.navbar-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.nav-placeholder {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.top-banner {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
height: 330rpx;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
padding: 10rpx 24rpx 0;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.input-box {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 24rpx;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.input-box input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.textarea-box {
|
||||
height: 240rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.textarea-box textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 12rpx;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
padding: 20rpx 24rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.pay-amount {
|
||||
font-size: 32rpx;
|
||||
color: #e64340;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 96rpx;
|
||||
line-height: 96rpx;
|
||||
background: #FAD146;
|
||||
color: #ffffff;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
border-radius: 10rpx;
|
||||
border: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.submit-btn[disabled] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
</style>
|
||||
BIN
miniapp/static/ic_address.png
Normal file
BIN
miniapp/static/ic_address.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 655 B |
BIN
miniapp/static/ic_courier.png
Normal file
BIN
miniapp/static/ic_courier.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
BIN
miniapp/static/ic_delicacy.png
Normal file
BIN
miniapp/static/ic_delicacy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 765 B |
Loading…
Reference in New Issue
Block a user