439 lines
15 KiB
Vue
439 lines
15 KiB
Vue
<template>
|
|
<view>
|
|
<!-- 顶部操作条 -->
|
|
<cu-custom :bgColor="'bg-main-color'" :isBack="true">
|
|
<block slot="backText">返回</block>
|
|
<block slot="content">订单确认</block>
|
|
</cu-custom>
|
|
<!-- 服务地址 -->
|
|
<view v-if="formInfo.defaultAddress" class="bg-white">
|
|
<view class="padding flex justify-between align-center" @click="showAddress2Choose">
|
|
<view>
|
|
<view class="flex justify-start align-center">
|
|
<view class="text-gray margin-right-xs">{{formInfo.defaultAddress.countryName}}</view>
|
|
<view class="text-gray margin-right-xs">{{formInfo.defaultAddress.provinceName}}</view>
|
|
<view class="text-gray margin-right-xs">{{formInfo.defaultAddress.cityName}}</view>
|
|
</view>
|
|
<view class="text-lg margin-tb-sm">{{formInfo.defaultAddress.address}}</view>
|
|
<view class="text-gray">
|
|
<text class="margin-right">{{formInfo.defaultAddress.name}}</text>
|
|
<text>{{formInfo.defaultAddress.phone}}</text>
|
|
</view>
|
|
</view>
|
|
<view class="text-lg"><text class="text-bold text-gray cuIcon-right"></text></view>
|
|
</view>
|
|
<view class="cu-progress sm striped">
|
|
<view class="bg-orange" style="width: 100%;"></view>
|
|
</view>
|
|
</view>
|
|
<view v-else class="bg-white" @click="showAddress2Choose">
|
|
<view class="flex justify-between align-center padding-lg">
|
|
<view class="text-lg text-black">
|
|
<text class="cuIcon-locationfill text-blue light"></text>
|
|
选择服务地址
|
|
</view>
|
|
<view>选择<text class="text-sm text-bold text-gray cuIcon-right"></text></view>
|
|
</view>
|
|
<view class="cu-progress sm striped">
|
|
<view class="bg-orange" style="width: 100%;"></view>
|
|
</view>
|
|
</view>
|
|
<!-- 预约时间 -->
|
|
<view class="margin-lr-sm margin-top-sm bg-white padding">
|
|
<view class="flex justify-between">
|
|
<text class="text-black">预约时间</text>
|
|
<view class="flex justify-end align-center">
|
|
<uni-datetime-picker @change="changeDoorTime" type="date">
|
|
<view v-if="formInfo.doorTime">
|
|
<text>{{formInfo.doorTime}}</text>
|
|
</view>
|
|
<view v-else class="text-red text-sm">请选择上门时间<text class="text-bold cuIcon-right"></text></view>
|
|
</uni-datetime-picker>
|
|
<picker class="margin-left-xs" v-if="formInfo.doorTime" mode="selector" :value="timeRangeIndex" :range="timeRangeList"
|
|
@change="timeRangeChange">
|
|
<input class="radius-input time-picker" v-model="timeRange" disabled></input>
|
|
</picker>
|
|
</view>
|
|
</view>
|
|
<view class="text-sm text-gray margin-top-sm"><text
|
|
class="cuIcon-question">选择的为期望上门时间,稍后工程师将与你确认具体上门时间</text></view>
|
|
</view>
|
|
<!-- 选购的商品列表 -->
|
|
<view class="margin-lr-sm margin-top-sm bg-white">
|
|
<view class="solid-top" v-for="(item, index0) in pickedProductList" :key="index0">
|
|
<view class="cu-bar">
|
|
<view class="action bar-first-action">
|
|
<text class="cuIcon-shopfill text-main-color"></text>
|
|
{{item.name}}
|
|
<view>
|
|
<view class="cuIcon-right"></view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="margin-top-sm padding-lr">
|
|
<product-picked :columnTitleArr="columnTitleArr" v-for="(product, index1) in item.product"
|
|
:key="product.id"
|
|
:product="product" :pickedList="product.pickedList">
|
|
</product-picked>
|
|
</view>
|
|
</view>
|
|
<!-- <view class="solid-bottom" v-for="(item, index) in pickedProductList">
|
|
<product-picked :columnTitleArr="columnTitleArr" :product="item.product" :pickedList="item.pickedList">
|
|
</product-picked>
|
|
</view> -->
|
|
</view>
|
|
<!-- 支付方式 -->
|
|
<view class="margin-lr-sm margin-top-sm bg-white padding">
|
|
<view class="flex justify-between align-center">
|
|
<text class="text-black">支付方式</text>
|
|
<radio-group @change="changePayWay">
|
|
<label class="radio">
|
|
<radio class="main-color" value="0" :checked="formInfo.payWay=='0'" />
|
|
<text class="margin-left-xs">在线支付</text>
|
|
</label>
|
|
<label class="radio margin-left">
|
|
<radio class="main-color" value="1" :checked="formInfo.payWay=='1'" />
|
|
<text class="margin-left-xs">上门到付</text>
|
|
</label>
|
|
</radio-group>
|
|
</view>
|
|
</view>
|
|
<template v-if="InsuranceList.length">
|
|
<view class="margin-lr-sm margin-top-sm bg-white padding">
|
|
<view class="text-black">
|
|
<!-- insuranceAmount -->
|
|
<text style="font-size: 40rpx;">保险</text> <text style="font-size: 26rpx;margin-left: 10upx;" v-if="chooseInsurance.insuranceAmount">核对服务费¥{{chooseInsurance.insuranceAmount}}(预付),未出发上门可退!</text>
|
|
</view>
|
|
<view class="text-black" style="font-size: 26rpx;padding-top: 10upx;">本订单勾选全程保险,请平台核对本单家政公司的雇主雇员与订单关联者按下方保险购买并生效:</view>
|
|
<radio-group @change="changeInsurance" style="width: 100%;">
|
|
<label v-for="item in InsuranceList" :key="item.id" class="radio" style="width: 100%;display: flex;justify-content: space-between;align-items: center;padding: 20upx 0;">
|
|
<view>
|
|
<radio class="main-color" :value="item.id" :checked="chooseInsurance.id == item.id" />
|
|
<text class="margin-left-xs text-red">{{item.insuranceName}}</text>
|
|
</view>
|
|
<text class="text-main-color">条款查看</text>
|
|
</label>
|
|
</radio-group>
|
|
<view style="text-align: right;padding: 10upx 0;">
|
|
<view class="cu-tag light bg-blue radius" @click="chooseInsurance.id = null; chooseInsurance.insuranceAmount = 0;">清除保险</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<!-- 发票信息 -->
|
|
<view class="margin-lr-sm margin-top-sm bg-white padding">
|
|
<view class="flex justify-between align-center">
|
|
<!-- <text class="text-black">发票信息</text>
|
|
<text class="text-sm text-bold cuIcon-right"></text> -->
|
|
<view class="basis-df">
|
|
<view class="text-black">是否需要发票</view>
|
|
<view class="text-red text-sm">需开具发票请在下面备注发票信息</view>
|
|
</view>
|
|
<radio-group @change="changeIsNeedBill">
|
|
<label class="radio">
|
|
<radio class="main-color" value="0" :checked="formInfo.isNeedBill=='0'" />
|
|
<text class="margin-left-xs">不需要</text>
|
|
</label>
|
|
<label class="radio margin-left">
|
|
<radio class="main-color" value="1" :checked="formInfo.isNeedBill=='1'" />
|
|
<text class="margin-left-xs">需要</text>
|
|
</label>
|
|
</radio-group>
|
|
</view>
|
|
</view>
|
|
<!-- 备注留言 -->
|
|
<view class="margin-lr-sm margin-top-sm bg-white padding">
|
|
<text class="text-black">备注留言</text>
|
|
<view class="margin-top uni-textarea">
|
|
<textarea class="solid" maxlength="-1" @input="inputComments" placeholder="请填写备注" />
|
|
</view>
|
|
</view>
|
|
<!-- 平台提醒 -->
|
|
<view class="margin-lr-sm margin-top-sm bg-white padding margin-bottom-with-bar">
|
|
<view class="text-sm text-orange"><text
|
|
class="cuIcon-roundcheck">为保障您的权益,请在平台内交易,师傅服务离开后发生损坏或退款以及售后质保,平台可为您追责!</text></view>
|
|
</view>
|
|
<!-- 底部操作栏 -->
|
|
<view class="cu-bar bg-white tabbar border shop fixed-bottom-bar">
|
|
<view class="action text-df left-grid">
|
|
<text class="margin-left-lg">共计</text>
|
|
<text class="margin-left-xs text-red text-price text-xl">{{totalPrice}}</text>
|
|
</view>
|
|
<view class="bg-main-color submit" @click="submit">确定</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import productPicked from '@/components/goods-card/product-picked.vue';
|
|
|
|
export default {
|
|
components: {
|
|
productPicked
|
|
},
|
|
data() {
|
|
return {
|
|
columnTitleArr: ['购买型号', '购买数量'],
|
|
pickedProductList: [],
|
|
formInfo: {
|
|
payWay: '0',
|
|
isNeedBill: '0',
|
|
comments: '',
|
|
doorTime: null,
|
|
defaultAddress: null,
|
|
expectTimeStart: '',
|
|
expectTimeEnd: '',
|
|
},
|
|
totalPrice: 0,
|
|
timeRangeIndex: 0,
|
|
timeRange: '',
|
|
timeRangeList: [],
|
|
InsuranceList: [],
|
|
chooseInsurance: {id: null, insuranceAmount: 0}
|
|
}
|
|
},
|
|
onLoad(options) {
|
|
let params = JSON.parse(decodeURIComponent(options.params));
|
|
this.loadData(params);
|
|
this.bindEvent();
|
|
},
|
|
onUnload() {
|
|
this.offBindEvent();
|
|
},
|
|
methods: {
|
|
async loadData(params) {
|
|
this.loadDefaultAddress();
|
|
// this.pickedProductList = await this.$api.data('pickedProductList');
|
|
this.pickedProductList = params.pickedProductList;
|
|
console.log(params);
|
|
this.InsuranceList = params.pickedProductList[0].insuranceManagers || []
|
|
if(this.InsuranceList.length) {
|
|
this.chooseInsurance.id = this.InsuranceList[0].id;
|
|
this.chooseInsurance.insuranceAmount = this.InsuranceList[0].insuranceAmount;
|
|
}
|
|
|
|
this.loadTotalPrice();
|
|
this.timeRangeList = this.$globalData.timeRangeList;
|
|
this.timeRange = this.timeRangeList[0];
|
|
},
|
|
async loadDefaultAddress() {
|
|
let res = await this.$request.getAddressList({
|
|
customerId: this.$request.getCurUserInfo().customerId,
|
|
isDefault: 1
|
|
});
|
|
// if (res && res.data &&res.data.length) {
|
|
// this.formInfo.defaultAddress = res.data[0];
|
|
// }
|
|
if (res && res.data &&res.data.length) {
|
|
const defaultAdd = res.data.filter(i => i.isDefault === 1)
|
|
this.formInfo.defaultAddress = defaultAdd.length ? defaultAdd[0] : res.data[0];
|
|
}
|
|
},
|
|
loadTotalPrice() {
|
|
// 计算totalprice
|
|
this.pickedProductList.forEach((obj) => {
|
|
this.totalPrice = Math.round((this.totalPrice + Number(obj.totalMoney)) * 100) / 100;
|
|
})
|
|
},
|
|
bindEvent() {
|
|
uni.$on(this.$globalFun.CHOOSE_ADDRESS, this.chooseAddress);
|
|
},
|
|
offBindEvent() {
|
|
uni.$off(this.$globalFun.CHOOSE_ADDRESS);
|
|
},
|
|
changePayWay(e) {
|
|
this.formInfo.payWay = e.detail.value;
|
|
},
|
|
changeIsNeedBill(e) {
|
|
this.formInfo.isNeedBill = e.detail.value;
|
|
},
|
|
changeInsurance(e) {
|
|
if(e.detail.value) {
|
|
const current = this.InsuranceList.find(i => i.id == e.detail.value)
|
|
this.chooseInsurance.id = current.id;
|
|
this.chooseInsurance.insuranceAmount = current.insuranceAmount;
|
|
} else {
|
|
this.chooseInsurance.id = null;
|
|
this.chooseInsurance.insuranceAmount = 0;
|
|
}
|
|
},
|
|
inputComments(e) {
|
|
this.formInfo.comments = e.detail.value
|
|
},
|
|
showAddress2Choose() {
|
|
uni.navigateTo({
|
|
url: '/pages/my/my-address?chooseMode=true'
|
|
})
|
|
},
|
|
chooseAddress(addressInfo) {
|
|
this.formInfo.defaultAddress = addressInfo;
|
|
},
|
|
changeDoorTime(value) {
|
|
this.formInfo.doorTime = value;
|
|
this.changeExpectTime();
|
|
},
|
|
timeRangeChange(e) {
|
|
this.timeRangeIndex = e.detail.value;
|
|
this.timeRange = this.timeRangeList[this.timeRangeIndex];
|
|
this.changeExpectTime();
|
|
},
|
|
changeExpectTime() {
|
|
let timeRangeSplit = this.$globalData.timeRangeSplit;
|
|
let timeArr = this.timeRange.split(timeRangeSplit);
|
|
this.formInfo.expectTimeStart = this.formInfo.doorTime + ' ' + timeArr[0] + ':00';
|
|
this.formInfo.expectTimeEnd = this.formInfo.doorTime + ' ' + timeArr[1] + ':00';
|
|
},
|
|
parseGoodsList() {
|
|
let goodsList = [];
|
|
this.pickedProductList.forEach((shopInfo) => {
|
|
shopInfo.product.forEach((productInfo) => {
|
|
productInfo.pickedList.forEach((pickedSpecs) => {
|
|
goodsList.push({
|
|
goodsStandardId: pickedSpecs.id,
|
|
num: pickedSpecs.pickedNum,
|
|
})
|
|
})
|
|
})
|
|
})
|
|
return goodsList;
|
|
},
|
|
validForm() {
|
|
if (!this.formInfo.defaultAddress) {
|
|
uni.showToast({
|
|
title: '请选择服务地址',
|
|
icon: 'none'
|
|
})
|
|
return false;
|
|
}
|
|
if (!this.formInfo.doorTime || !this.formInfo.expectTimeEnd || !this.formInfo.expectTimeStart) {
|
|
uni.showToast({
|
|
title: '请选择上门时间',
|
|
icon: 'none'
|
|
})
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
// 检测当前默认地址是否在服务区域之间
|
|
checkDefaultAddressIfInclude() {
|
|
if(!this.formInfo.defaultAddress) return true
|
|
const allAreaId = []
|
|
this.pickedProductList.forEach(item => {
|
|
item.product.forEach(pro => {
|
|
allAreaId.push(...pro.goodsAreaList.map(i => i.countryAreaId))
|
|
})
|
|
})
|
|
// console.log(allAreaId, this.formInfo.defaultAddress);
|
|
// const allAreaId = this.shopInfo.workerAreas.map(i => i.districtId)
|
|
return allAreaId.includes(this.formInfo.defaultAddress.countryId)
|
|
},
|
|
submit() {
|
|
let valid = this.validForm();
|
|
if (!valid) {
|
|
return;
|
|
}
|
|
if(!this.checkDefaultAddressIfInclude()) {
|
|
uni.showModal({
|
|
title: '提示',
|
|
content: '所选服务的区域与您所填地址的区域不匹配!可能会无法服务,请核对!',
|
|
cancelText: '查看',
|
|
confirmText: '仍然下单',
|
|
success: res => {
|
|
if (res.confirm) {
|
|
this.makeOrderOpration()
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
this.makeOrderOpration()
|
|
}
|
|
},
|
|
async makeOrderOpration() {
|
|
|
|
let curUserInfo = this.$request.getCurUserInfo();
|
|
let params = {
|
|
customerId: curUserInfo.customerId,
|
|
expectTimeStart: this.formInfo.expectTimeStart,
|
|
expectTimeEnd: this.formInfo.expectTimeEnd,
|
|
addressId: this.formInfo.defaultAddress.customerAddressId,
|
|
payType: this.formInfo.payWay,
|
|
remark: this.formInfo.comments,
|
|
isNeedBill: this.formInfo.isNeedBill,
|
|
goodsList: this.parseGoodsList(),
|
|
goodsId: this.pickedProductList[0].product[0].goodsId,
|
|
// 保险id
|
|
insuranceId: this.chooseInsurance.id
|
|
// goodsList: [{
|
|
// goodsId: 2,
|
|
// num: 1
|
|
// }]
|
|
}
|
|
// 调用下单接口
|
|
let res = await this.$request.placeOrder(params);
|
|
if (res.code != 0) {
|
|
return;
|
|
} else if (this.formInfo.payWay == '1') {
|
|
// 上门支付则不拉起微信支付窗口,直接跳转至提示导航页面
|
|
uni.navigateTo({
|
|
url: '/pages/order/pay-result?customTip=您选择上门到付款,师傅/服务人员上门后会让您付款,请配合!可从对方出示的系统二维码或你订单中的“付款”键支付!'
|
|
})
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// 获取微信支付所需参数
|
|
let exPayParams = {
|
|
code: this.$request.getCurUserInfo().openId,
|
|
orderMasterCode: res.data.code
|
|
}
|
|
let wxPayParamRes = await this.$request.getWxPayParams(exPayParams);
|
|
// 拉起微信支付窗口,支付成功跳转到支付成功页面
|
|
let payInfo = JSON.parse(wxPayParamRes.data.expend.pay_info);
|
|
let wxPayRes = await wx.requestPayment(payInfo);
|
|
if (wxPayRes.errMsg === "requestPayment:ok") {
|
|
uni.navigateTo({
|
|
url: '/pages/order/pay-result?payResult=0'
|
|
})
|
|
} else {
|
|
throw 'err';
|
|
}
|
|
} catch(e) {
|
|
// 支付失败弹出提示并跳转到我的订单待支付页
|
|
uni.navigateTo({
|
|
url: '/pages/order/pay-result?payResult=1'
|
|
})
|
|
}
|
|
}
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.fixed-bottom-bar .text-df {
|
|
font-size: 28rpx !important;
|
|
}
|
|
|
|
.fixed-bottom-bar .left-grid {
|
|
width: 55% !important;
|
|
text-align: left;
|
|
}
|
|
|
|
.bar-first-action {
|
|
margin-left: unset !important;
|
|
padding-left: 40rpx;
|
|
font-size: 30rpx !important;
|
|
}
|
|
|
|
.cu-progress {
|
|
display: inherit;
|
|
}
|
|
|
|
.cu-progress.sm {
|
|
height: 12rpx;
|
|
}
|
|
|
|
.time-picker {
|
|
width: 180rpx;
|
|
}
|
|
</style>
|