Files
Smart-Farm/uniapp/uni-app/claim/pages/order.vue
2026-01-07 10:16:49 +08:00

654 lines
19 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="claim-order" v-if="orderInfo.claim_info.id">
<uni-nav-bar :fixed="true" :shadow="false" title="确认订单" leftIcon="icon-left"></uni-nav-bar>
<view :style="{ height: `${configInfo.navBarHeight}px` }"></view>
<image mode="aspectFill" lazy-load class="common-bg abs" src="https://lbqny.migugu.com/admin/farm/bg-cash.png"></image>
<view class="space-lg"></view>
<view class="fill-base mt-md ml-md mr-md pd-lg box-shadow radius-24">
<view class="f-title c-title pb-lg b-1px-b">{{ orderInfo.farmer_info.title }}</view>
<view class="flex-warp pt-lg pb-lg">
<image mode="aspectFill" lazy-load class="avatar lg radius-10" :src="orderInfo.claim_info.cover"></image>
<view class="flex-1 ml-lg">
<view class="f-paragraph max-520 ellipsis">{{ orderInfo.claim_info.title }}</view>
<block v-if="options.type">
<view class="flex-y-center f-desc c-warning mt-sm">
众筹价
<view class="flex-y-baseline f-caption ml-sm">
¥
<view class="f-sm-title text-bold">
{{ orderInfo.claim_info[orderType[options.type]].price }}
</view>
</view>
<view class="f-icontext c-caption text-delete ml-sm">原价 ¥{{ orderInfo.claim_info.price }}</view>
</view>
<view class="flex-center mt-md">
<view class="collage-tag flex-center f-caption c-base" :style="{ background: primaryColor }">
{{ orderInfo.claim_info[orderType[options.type]].success_num }}人团
</view>
<view class="flex-1"></view>
</view>
</block>
<view class="flex-y-baseline f-paragraph c-warning mt-sm" v-else>
¥{{ orderInfo.claim_info.price }}
<view class="f-caption c-caption ml-sm">/{{ orderInfo.claim_info.unit }}</view>
</view>
</view>
</view>
<view class="flex-between pt-lg pb-lg b-1px-tb">
<view class="f-paragraph c-black">认养数量</view>
<view v-if="options.type">{{ subForm.num }}</view>
<view class="add-remove-item flex-center" v-else>
<i @tap.stop="changeNum(-1, index)" class="iconfont icon-remove-square c-caption"></i>
<view class="number flex-center f-desc pl-sm pr-sm">{{ subForm.num }}</view>
<i @tap.stop="changeNum(1, index)" class="iconfont icon-add-square" :style="{ color: primaryColor }"></i>
</view>
</view>
<view class="pt-lg pb-lg f-paragraph c-black">认养收获</view>
<view class="flex-center">
<image mode="aspectFill" lazy-load class="avatar sm radius-10" :src="orderInfo.claim_info.harvest_cover"></image>
<view class="flex-1 ml-lg ellipsis">{{ orderInfo.claim_info.harvest_text }}</view>
</view>
</view>
<view class="fill-base mt-md ml-md mr-md f-paragraph box-shadow radius-24">
<view class="flex-between pd-lg">
<view class="flex-y-center f-sm-title c-black">
<i class="iconfont icon-peisong mr-sm" :style="{ color: primaryColor }"></i>
配送周期
</view>
<view class="f-paragraph">{{ orderInfo.claim_info.send_cycle }}</view>
</view>
</view>
<view class="fill-base mt-md ml-md mr-md f-paragraph box-shadow radius-24">
<view class="flex-between pd-lg f-sm-title c-title b-1px-b">
<view class="text-bold">配送方式</view>
<view class="send-list flex-center radius" :style="{ width: sendList.length == 1 ? '90rpx' : '' }">
<view
@tap.stop="toChangeItem('sendInd', index)"
class="send-item flex-center f-paragraph radius"
:class="[{ 'c-base': sendInd == index }]"
:style="{ background: sendInd == index ? primaryColor : '' }"
v-for="(item, index) in sendList"
:key="index"
>
{{ item.title }}
</view>
</view>
</view>
<view @tap.stop="toChooseAddr" class="pd-lg flex-center" v-if="sendList[sendInd].id == 1 || orderInfo.address.id">
<view class="flex-1">
<view class="flex-warp">
<i class="iconfont icon-dingwei mr-sm" style="font-size: 28rpx; margin-top: 6rpx"></i>
<view class="f-paragraph c-title flex-1" :class="[{ 'max-520': sendList[sendInd].id == 2 }]">
{{
sendList[sendInd].id == 1
? `${orderInfo.farmer_info.address}`
: orderInfo.address.id
? `${orderInfo.address.address} ${orderInfo.address.address_info}`
: ''
}}
</view>
</view>
<view class="flex-y-baseline f-paragraph c-caption" style="margin: 5rpx 0 0 38rpx">
{{ sendList[sendInd].id == 1 ? orderInfo.farmer_info.user_name : orderInfo.address.id ? orderInfo.address.user_name : '' }}
<view class="ml-lg">
{{ sendList[sendInd].id == 1 ? orderInfo.farmer_info.mobile : orderInfo.address.id ? orderInfo.address.mobile : '' }}
</view>
</view>
</view>
<i class="iconfont" :class="[{ 'icon-dingwei': sendList[sendInd].id == 1 }, { 'icon-right': sendList[sendInd].id == 2 }]"></i>
</view>
<block v-else>
<view class="space-lg"></view>
<view class="space-lg"></view>
<view @tap.stop="toChooseAddr" class="add-btn flex-center f-paragraph c-desc">
<i class="iconfont icon-add-circle-fill mr-sm"></i>
添加地址
</view>
<view class="space-lg"></view>
<view class="space-lg"></view>
</block>
</view>
<view class="fill-base mt-md ml-md mr-md f-paragraph box-shadow radius-24" v-if="sendList[sendInd].id == 1">
<view class="flex-between ml-md mr-md pl-sm pt-lg pb-lg b-1px-b">
<view class="flex-y-center">
<i class="iconfont icon-required c-warning"></i>
<view class="item-text">姓名</view>
</view>
<input v-model="subForm.user_name" type="text" class="flex-1 f-paragraph" placeholder-class="c-placeholder" :placeholder="rule[0].errorMsg" />
</view>
<view class="flex-between ml-md mr-md pl-sm pt-lg pb-lg">
<view class="flex-y-center">
<i class="iconfont icon-required c-warning"></i>
<view class="item-text">手机号</view>
</view>
<input v-model="subForm.mobile" type="text" class="flex-1 f-paragraph" placeholder-class="c-placeholder" :placeholder="rule[1].errorMsg" />
<button open-type="getPhoneNumber" @getphonenumber="toAuthPhone" class="clear-btn auth-phone-btn flex-center" :style="{ color: primaryColor }">立即授权</button>
</view>
</view>
<view class="fill-base mt-md ml-md mr-md f-paragraph box-shadow radius-24">
<view class="flex-between ml-md mr-md pl-sm pt-lg pb-lg b-1px-b">
<view class="flex-y-center">
<i class="iconfont icon-required c-warning"></i>
<view class="item-text">认养取名</view>
</view>
<input v-model="subForm.claim_name" type="text" class="flex-1 f-paragraph" placeholder-class="c-placeholder" :placeholder="rule[2].errorMsg" />
</view>
<view class="flex-between ml-md mr-md pl-sm pt-lg pb-lg">
<view class="flex-y-center">
<i class="iconfont icon-required c-base"></i>
<view class="item-text">订单备注</view>
</view>
<input v-model="subForm.text" type="text" class="flex-1 f-paragraph" maxlength="100" placeholder-class="c-placeholder" placeholder="请输入订单备注" />
</view>
</view>
<view class="fill-base mt-md ml-md mr-md f-paragraph box-shadow radius-24" v-if="!options.type">
<view class="flex-between ml-md mr-md pl-sm pt-lg pb-lg">
<view class="item-text">卡券优惠</view>
<view @tap.stop="$util.goUrl({ url: `/mine/pages/coupon/use?claim_id=${options.id}&num=${subForm.num}&type=2` })" class="flex-y-center">
<view class="flex-1 text-right">
{{ orderInfo.coupon_id ? `${orderInfo.coupon_discount}` : `${orderInfo.canUseCoupon}张可用` }}
</view>
<i class="iconfont icon-right"></i>
</view>
</view>
</view>
<view class="fill-base mt-md ml-md mr-md f-sm-title box-shadow radius-24">
<view @tap.stop="toChangeItem('payInd', index)" class="flex-between ml-md mr-md pl-sm pr-sm pt-lg pb-lg b-1px-b" v-for="(item, index) in payList" :key="index">
<view class="pay-item flex-y-center">
<i class="iconfont mr-md" :class="[item.icon]" :style="{ color: item.id == 1 ? primaryColor : item.id == 2 ? subColor : '#01AAF2' }"></i>
<view class="flex-y-baseline">
{{ item.title }}
<view class="f-paragraph c-caption ml-sm" v-if="item.id == 2">余额{{ userInfo.balance || 0 }}</view>
</view>
</view>
<i
class="pay-icon iconfont c-caption"
:class="[{ 'icon-xuanze': payInd != index }, { 'icon-radio-fill': item.is_disabled || payInd == index }]"
:style="{ color: payInd == index ? primaryColor : '' }"
></i>
</view>
</view>
<view @tap.stop="toAgree" class="flex-warp f-paragraph mt-md pd-md">
<i
class="agree-icon iconfont c-caption mr-sm"
:class="[{ 'icon-xuanze': !agree }, { 'icon-xuanze-fill': agree }]"
style="margin-top: 3rpx"
:style="{ color: agree ? primaryColor : '' }"
></i>
<view class="flex-y-center">
购买代表您已同意
<view @tap.stop="$util.goUrl({ url: `/mine/pages/agreement?type=1` })" :style="{ color: primaryColor }">{{ agreement }}</view>
</view>
</view>
<view class="space-max-footer"></view>
<view class="footer-btn fill-base fix">
<view class="footer-item flex-between pl-lg pr-lg">
<view class="flex-y-baseline f-paragraph c-title">
合计
<view class="f-sm-title c-warning text-bold">¥{{ orderInfo.pay_price }}</view>
</view>
<!-- #ifdef APP-PLUS -->
<view @tap="toOrder" class="order-btn flex-center f-sm-title c-base text-bold radius-20" :style="{ background: primaryColor }">立即支付</view>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<auth :needAuth="userInfo && !userInfo.nickName" :must="true" type="userInfo" @go="toOrder">
<view class="order-btn flex-center f-sm-title c-base text-bold radius-20" :style="{ background: primaryColor }">立即支付</view>
</auth>
<!-- #endif -->
</view>
<view class="space-safe"></view>
</view>
</view>
</template>
<script>
import { mapState, mapActions, mapMutations } from 'vuex';
export default {
components: {},
data() {
return {
options: {},
scrollTop: 0,
orderType: {
1: 'collage_start_data',
2: 'collage_join_data'
},
// 1微信支付2余额支付3支付宝支付
payList: [
{
id: 1,
title: '微信支付',
icon: 'icon-wechat-pay',
is_disabled: false
},
// #ifdef APP-PLUS
{
id: 3,
title: '支付宝支付',
icon: 'icon-alipay',
is_disabled: false
},
// #endif
{
id: 2,
title: '余额支付',
icon: 'icon-qianbao',
is_disabled: false
}
],
payInd: 0,
// #ifdef APP-PLUS
balanceInd: 2,
// #endif
// #ifndef APP-PLUS
balanceInd: 1,
// #endif
sendList: [],
sendInd: 0,
agreement: '',
agree: false,
orderInfo: {
address: {},
farmer_info: {},
claim_info: {}
},
subForm: {
num: 1,
send_type: 1,
address_id: '',
user_name: '',
mobile: '',
claim_name: '',
text: ''
},
rule: [
{
name: 'user_name',
checkType: 'isNotNull',
errorMsg: '请输入姓名',
regType: 2
},
{
name: 'mobile',
checkType: 'isMobile',
errorMsg: '请输入手机号'
},
{
name: 'claim_name',
checkType: 'isNotNull',
errorMsg: '快给你认养的小动物取个名吧'
}
]
};
},
computed: mapState({
primaryColor: (state) => state.config.configInfo.primaryColor,
subColor: (state) => state.config.configInfo.subColor,
configInfo: (state) => state.config.configInfo,
userInfo: (state) => state.user.userInfo
}),
onLoad(options) {
let { type = 0 } = options;
options.type = type * 1;
this.options = options;
this.initIndex();
},
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
methods: {
...mapActions(['getUserInfo', 'getAuthPhone']),
...mapMutations(['updateOrderItem']),
async initIndex(refresh = false) {
if (!refresh) {
let [, info] = await Promise.all([
this.getUserInfo(),
this.$api.home.aboutUsInfoType({
type: 1
})
]);
this.agreement = info.title;
}
let { id: claim_id, type: order_type, cid: collage_id } = this.options;
let { phone } = this.userInfo;
let { mobile = '', num = 1 } = this.subForm;
this.subForm.mobile = mobile || phone;
let { address = {}, coupon_id = 0 } = this.orderInfo;
let { id: address_id = 0 } = address;
let param = {
claim_id,
coupon_id,
address_id,
num
};
// order_type 1发起众筹2参与众筹
if (order_type == 1) {
param.collage_start_id = collage_id;
}
if (order_type == 2) {
param.collage_join_id = collage_id;
}
let orderInfo = await this.$api.claim.claimPayOrderInfo(param);
if (!refresh) {
let { is_self, is_send } = orderInfo.claim_info;
let sendList = [];
if (is_self) {
sendList.push({
id: 1,
title: '自提'
});
}
if (is_send) {
sendList.push({
id: 2,
title: '快递'
});
}
this.sendList = sendList;
}
let { balance } = this.userInfo;
let { pay_price } = orderInfo;
let is_disabled = balance * 1 < pay_price * 1;
let { balanceInd } = this;
this.payList[balanceInd].is_disabled = is_disabled;
if (pay_price * 1 == 0) {
this.payList[0].is_disabled = true;
// #ifdef APP-PLUS
this.payList[1].is_disabled = true;
// #endif
this.payInd = balanceInd;
}
this.orderInfo = orderInfo;
},
initRefresh() {
this.initIndex(true);
},
async changeNum(mod, index) {
let { num: goods_num } = this.subForm;
let { unit } = this.orderInfo.claim_info;
let num = goods_num + mod;
if (num < 1) {
this.$util.showToast({
title: `此动物最少购买1${unit}`
});
return;
}
this.subForm.num = num;
this.initRefresh();
},
toChangeItem(key, index) {
if (key == 'payInd' && index === 2 && this.payList[index].is_disabled) return;
this[key] = index;
},
async toMap() {
let { lat, lng, address } = this.orderInfo.farmer_info;
await this.$util.checkAuth({
type: 'userLocation'
});
await uni.getLocation({
type: 'gcj02'
});
await uni.openLocation({
latitude: lat * 1,
longitude: lng * 1,
name: address,
scale: 28
});
},
toChooseAddr() {
if (this.sendList[this.sendInd].id == 1) {
this.toMap();
return;
}
this.$util.goUrl({
url: `/mine/pages/address/list?check=1`
});
},
// 授权手机号
async toAuthPhone(e) {
let phone = await this.getAuthPhone({
e
});
if (!phone) return;
this.$nextTick(() => {
this.subForm.mobile = phone;
});
},
toAgree() {
this.agree = !this.agree;
},
//表单验证
validate(param) {
let validate = new this.$util.Validate();
let arr = param.send_type == 1 ? ['user_name', 'mobile', 'claim_name'] : ['claim_name'];
this.rule.map((item) => {
let { name } = item;
if (!arr.includes(name)) return;
validate.add(param[name], item);
});
let message = validate.start();
return message;
},
toOrder() {
let { payList, payInd, sendList, sendInd, subForm, agreement } = this;
let { id: claim_id, cid: collage_id, type: order_type } = this.options;
let { id: pay_model } = payList[payInd];
let { id: send_type } = sendList[sendInd];
let { address = {}, coupon_id = 0 } = this.orderInfo;
let { id: address_id = 0 } = address;
if (!address_id && send_type == 2) {
this.$util.showToast({
title: `请选择收货地址`
});
return;
}
let param = Object.assign({}, subForm, {
claim_id,
address_id,
coupon_id,
pay_model,
send_type
});
// order_type 1发起众筹2参与众筹
if (order_type == 1) {
param.collage_start_id = collage_id;
}
if (order_type == 2) {
param.collage_join_id = collage_id;
}
let msg = this.validate(param);
if (msg) {
this.$util.showToast({
title: msg
});
return;
}
if (!this.agree) {
this.$util.showToast({
title: `请勾选${agreement}`
});
return;
}
this.toPay(param);
},
async toPay(param) {
// #ifdef MP-WEIXIN
let that = this;
let { tmp_list = [] } = that.orderInfo;
let tmplIds = [];
tmp_list.map((item) => {
tmplIds.push(item.tmpl_id);
});
if (tmplIds && tmplIds.length > 0) {
uni.requestSubscribeMessage({
tmplIds,
complete(res) {
that.toConfirmPay(param);
console.log(res, 'complete requestSubscribeMessage');
}
});
} else {
that.toConfirmPay(param);
}
// #endif
// #ifndef MP-WEIXIN
this.toConfirmPay(param);
// #endif
},
async toConfirmPay(param) {
if (this.lockTap) return;
this.lockTap = true;
this.$util.showLoading();
try {
let { pay_list } = await this.$api.claim.claimPayOrder(param);
this.$util.hideAll();
if (pay_list) {
if (param.pay_model == 3) {
pay_list = {
orderInfo: pay_list,
provider: 'alipay'
};
}
try {
await this.$util.pay(pay_list);
this.$util.showToast({
title: `支付成功`
});
this.updateOrderItem({
key: 'haveOperItem',
val: true
});
setTimeout(() => {
this.$util.back();
this.$util.goUrl({
url: '/mine/pages/pay-result?type=claim',
openType: 'redirectTo'
});
}, 1000);
this.lockTap = false;
return;
} catch (e) {
this.$util.showToast({
title: `支付失败`
});
setTimeout(() => {
this.$util.back();
this.$util.goUrl({
url: `/claim/pages/order/list`,
openType: 'redirectTo'
});
}, 1000);
this.lockTap = false;
return;
}
}
this.$util.showToast({
title: `支付成功`
});
this.updateOrderItem({
key: 'haveOperItem',
val: true
});
setTimeout(() => {
this.$util.back();
this.$util.goUrl({
url: '/mine/pages/pay-result?type=claim',
openType: 'redirectTo'
});
}, 1000);
} catch (e) {
setTimeout(() => {
this.lockTap = false;
this.$util.hideAll();
}, 2000);
}
}
}
};
</script>
<style lang="scss">
.claim-order {
.collage-tag {
height: 36rpx;
padding: 0 10rpx;
}
.send-list {
width: 180rpx;
height: 52rpx;
border: 1rpx solid #cccccc;
transform: rotateZ(360deg);
overflow: hidden;
.send-item {
width: 90rpx;
height: 50rpx;
}
}
.add-btn {
width: 296rpx;
height: 72rpx;
background: #f6f6f6;
border-radius: 36rpx;
margin: 0 auto;
}
.pay-item {
.iconfont {
font-size: 50rpx;
}
}
.pay-icon {
font-size: 40rpx;
}
.icon-right {
font-size: 28rpx;
}
.icon-peisong,
.agree-icon {
font-size: 36rpx;
}
.item-text {
width: 150rpx;
}
.auth-phone-btn {
width: 106rpx;
height: 36rpx;
line-height: 36rpx;
margin-left: 15rpx;
font-size: 20rpx;
background: #f0f4ec;
border-radius: 10rpx;
}
.footer-btn {
bottom: 0;
.footer-item {
height: 114rpx;
.order-btn {
width: 332rpx;
height: 88rpx;
}
}
}
}
</style>