campus-errand/miniapp/pages/pickup/pickup.vue
18631081161 c543ebaf8b
All checks were successful
continuous-integration/drone/push Build is passing
聊天
2026-03-28 17:16:01 +08:00

336 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="order-page">
<!-- 自定义导航栏 -->
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="navbar-content">
<view class="nav-back" @click="goBack">
<image class="back-icon" src="/static/ic_back.png" mode="aspectFit"></image>
</view>
<text class="navbar-title">代取</text>
<view class="nav-placeholder"></view>
</view>
</view>
<view :style="{ height: (statusBarHeight + 44) + 'px' }"></view>
<!-- 顶部大图 -->
<view class="top-banner" v-if="bannerUrl">
<image class="banner-img" :src="bannerUrl" mode="aspectFill"></image>
</view>
<!-- 表单区域 -->
<view class="form-section">
<!-- 1.代取物品 -->
<view class="form-group">
<text class="form-label">1.代取物品</text>
<view class="input-box">
<input v-model="form.itemName" placeholder="请输入要代取的物品名" placeholder-class="placeholder" />
</view>
</view>
<!-- 2.取货地点 -->
<view class="form-group">
<text class="form-label">2.取货地点</text>
<view class="input-box">
<input v-model="form.pickupLocation" placeholder="请输入代取地点" placeholder-class="placeholder" />
</view>
</view>
<!-- 3.送达地点 -->
<view class="form-group">
<text class="form-label">3.送达地点</text>
<view class="input-box">
<input v-model="form.deliveryLocation" placeholder="请输入送达地点" placeholder-class="placeholder" />
</view>
</view>
<!-- 4.备注信息 -->
<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" />
</view>
</view>
<!-- 5.如何联系您 -->
<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" />
</view>
</view>
<!-- 6.跑腿佣金 -->
<view class="form-group">
<text class="form-label">6.跑腿佣金</text>
<view class="input-box">
<input v-model="form.commission" type="digit" placeholder="请输入跑腿佣金最低1.0元" placeholder-class="placeholder" />
</view>
<text class="form-tip">佣金先由平台保管,接单方完成订单后才会收到佣金</text>
</view>
</view>
<!-- 提交按钮 -->
<view class="submit-section">
<button class="submit-btn" @click="onSubmit" :loading="submitting" :disabled="submitting">
支付佣金 确定下单
</button>
</view>
</view>
</template>
<script>
import { createOrder, getPageBanner } from '../../utils/api'
export default {
data() {
return {
statusBarHeight: 0,
bannerUrl: '',
form: {
itemName: '',
pickupLocation: '',
deliveryLocation: '',
remark: '',
phone: '',
commission: ''
},
submitting: false
}
},
onLoad() {
const sysInfo = uni.getSystemInfoSync()
this.statusBarHeight = sysInfo.statusBarHeight || 0
this.loadBanner()
this.restoreFormData()
},
methods: {
/** 恢复登录前保存的表单数据 */
restoreFormData() {
const saved = uni.getStorageSync('loginFormData')
if (saved) {
try {
const data = JSON.parse(saved)
Object.assign(this.form, data)
} catch (e) {}
uni.removeStorageSync('loginFormData')
}
},
goBack() { uni.navigateBack() },
async loadBanner() {
try {
const res = await getPageBanner('pickup')
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 (!/^1\d{10}$/.test(this.form.phone.trim())) {
uni.showToast({ title: '请输入正确的11位手机号', icon: 'none' }); return false
}
return this.validateCommission()
},
async onSubmit() {
if (!this.validateForm()) return
// 未登录跳转登录页
const token = uni.getStorageSync('token')
if (!token) {
// 保存表单数据,登录后恢复
uni.setStorageSync('loginFormData', JSON.stringify(this.form))
uni.setStorageSync('loginRedirect', '/pages/pickup/pickup')
uni.navigateTo({ url: '/pages/login/login' })
return
}
this.submitting = true
try {
const commission = parseFloat(this.form.commission)
const result = await createOrder({
orderType: 'Pickup',
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(),
commission,
totalAmount: commission
})
if (result.paymentParams) await this.wxPay(result.paymentParams)
uni.showToast({ title: '下单成功', icon: 'success' })
setTimeout(() => { uni.switchTab({ url: '/pages/index/index' }) }, 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 {
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));
}
.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>