You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

694 lines
17 KiB

8 months ago
8 months ago
8 months ago
  1. <template>
  2. <view class="payOrder">
  3. <mNavbar title="确认订单" :leftClick="leftClick" />
  4. <view class="bac"></view>
  5. <view class="box">
  6. <view class="server-item">
  7. <view class="img-box">
  8. <image :src="projectDetail.image" mode="aspectFill"></image>
  9. </view>
  10. <view class="server-info">
  11. <view class="server-title">{{ projectDetail.title }}</view>
  12. <view class="time-coupon">
  13. <image src="@/static/home/time-icon.png"></image>
  14. <view class="time">{{ projectDetail.times }}分钟</view>
  15. </view>
  16. <!-- <view class="price">
  17. <view class="current-price">
  18. <text class="unit"></text>299
  19. </view>
  20. <view class="original-price">
  21. <text class="unit"></text>399
  22. </view>
  23. </view> -->
  24. <!-- <view class="coupon">{{ projectDetail.subTitle }}</view> -->
  25. <view class="sales-volume">
  26. <image src="@/static/icons/icon1.png"></image>
  27. <view class="desc">已售出 {{ projectDetail.payNum }}+ </view>
  28. </view>
  29. </view>
  30. </view>
  31. <van-cell-group>
  32. <van-cell title="请选择地址" is-Link @click="selectAddressPopupShow = true"
  33. :value="(address.name + address.phone + address.addressDetail) || ''">
  34. <template #icon>
  35. <image class="icon" src="../../static/payOrder/7.png" mode="aspectFill"></image>
  36. </template>
  37. </van-cell>
  38. <van-cell title="服务技师">
  39. <text style="color: #4899a6;">{{ technicianDetail.title }}</text>
  40. <template #icon>
  41. <image class="icon" src="../../static/payOrder/1.png" mode="aspectFill"></image>
  42. </template>
  43. </van-cell>
  44. <van-cell title="服务时间" is-Link @click="onServiceTime">
  45. <text style="color: #4899a6;">
  46. {{ time.timeName ? (dateObj.format('MM-DD') + ' ' + time.timeName) : '' }}
  47. </text>
  48. <template #icon>
  49. <image class="icon" src="../../static/payOrder/3.png" mode="aspectFill"></image>
  50. </template>
  51. </van-cell>
  52. <van-cell title="出行方式">
  53. <text style="color: #fff;
  54. background-color: #6fc6ad;
  55. padding: 5px 10px;
  56. border-radius: 5px;
  57. font-size: 12px;">出租车</text>
  58. <template #icon>
  59. <image class="icon" src="../../static/payOrder/2.png" mode=""></image>
  60. </template>
  61. </van-cell>
  62. <!-- <van-cell title="出行费用">
  63. <text>{{ temp }}</text>
  64. <template #icon>
  65. <image class="icon" src="../../static/payOrder/2.png" mode="aspectFill"></image>
  66. </template>
  67. </van-cell> -->
  68. <view class="mileage">
  69. <view class="top">
  70. 全程共
  71. <text style="color: #4899a6;
  72. font-size: 16px;">{{ distance || 0}}</text>
  73. 公里
  74. </view>
  75. <view class="info">
  76. 2公里内免费 超过2公里每公里{{ travelMoney }}
  77. </view>
  78. </view>
  79. <van-cell title="订单备注" is-Link @click="remarkShow = true">
  80. <text>{{ remark || '选填' }}</text>
  81. <template #icon>
  82. <image class="icon" src="../../static/payOrder/4.png" mode=""></image>
  83. </template>
  84. </van-cell>
  85. </van-cell-group>
  86. <van-cell-group style="margin-top: 10px;">
  87. <van-radio-group v-model="payMethod">
  88. <van-cell>
  89. <template #title>
  90. <text>账户余额</text>
  91. <text style="color: #888;">余额{{ userInfo.price }}</text>
  92. </template>
  93. <template #icon>
  94. <image class="icon" src="../../static/payOrder/5.png" mode=""></image>
  95. </template>
  96. <template #right-icon>
  97. <van-radio :name="1"></van-radio>
  98. </template>
  99. </van-cell>
  100. <van-cell title="微信支付">
  101. <template #icon>
  102. <image class="icon" src="../../static/payOrder/9.png" mode=""></image>
  103. </template>
  104. <template #right-icon>
  105. <van-radio :name="0"></van-radio>
  106. </template>
  107. </van-cell>
  108. </van-radio-group>
  109. </van-cell-group>
  110. <van-cell-group style="margin-top: 10px;">
  111. <van-cell title="优惠劵" is-Link @click="selectCouponPopupShow = true">
  112. <text v-if="coupon.money" style="color: #4899a6;">优惠 {{ coupon.money }}</text>
  113. <text v-else style="color: #4899a6;">{{ couponNum == 0 ? '无' : `${couponNum}` }}</text>
  114. <template #icon>
  115. <image class="icon" src="../../static/payOrder/5.png" mode=""></image>
  116. </template>
  117. </van-cell>
  118. </van-cell-group>
  119. <view style="color: #888;font-size: 12px;padding: 10px 0;;">
  120. 温馨提示下单前请仔细查看下单须知
  121. </view>
  122. <view class="agreement">
  123. <van-checkbox v-model="agreement"></van-checkbox>
  124. 本人已同意<text @click="configPopupShow = true" style="color: #6FDFBE;">用户使用协议</text>
  125. </view>
  126. </view>
  127. <view class="submit">
  128. <view class="price">
  129. <view>
  130. <text style="color: #000;">合计</text>
  131. <text style="font-size: 18px;
  132. font-weight: 600;">{{ count }}</text>
  133. </view>
  134. <view style="font-size: 10px;margin-top: 5px;">
  135. 已优惠{{ coupon.money || 0 }}
  136. </view>
  137. </view>
  138. <view class="btn" @click="submit">
  139. 立即支付
  140. </view>
  141. </view>
  142. <selectTime :show="selectTimeShow" @select="selectTime" :dateList="dateList" :timeList="timeList"
  143. :loading="timeLoading" @selectDate="getVipTenOrderList" @close="selectTimeShow = false"
  144. :title="selectTimeTitle" />
  145. <selectTechnician :serviceId="projectDetail.id" @select="selectTechnician" :show="selectTechnicianShow"
  146. @close="selectTechnicianShow = false" />
  147. <selectCouponPopup :show="selectCouponPopupShow" @selectCoupon="selectCoupon" @countCouponNum="countCouponNum"
  148. @close="selectCouponPopupShow = false" />
  149. <selectAddressPopup :show="selectAddressPopupShow" @select="selectAddress"
  150. @close="selectAddressPopupShow = false" />
  151. <van-popup v-model:show="remarkShow" round position="bottom" @close="remarkShow = false"
  152. :style="{ height: '160px' }">
  153. <van-field v-model="remark" rows="4" autosize type="textarea" maxlength="50" placeholder="请输入留言"
  154. show-word-limit />
  155. </van-popup>
  156. <configPopup :keyValue="keyValue" :show="configPopupShow" :list="config" @close="configPopupShow = false" />
  157. </view>
  158. </template>
  159. <script>
  160. import mNavbar from '@/components/base/m-navbar.vue'
  161. import selectTime from '@/components/payOrder/selectTime.vue'
  162. import selectTechnician from '@/components/payOrder/selectTechnicianPopup.vue'
  163. import selectAddressPopup from '@/components/payOrder/selectAddressPopup.vue'
  164. import selectCouponPopup from '@/components/payOrder/selectCouponPopup.vue'
  165. import configPopup from '@/components/configPopup'
  166. import Position from '@/utils/position.js'
  167. import { showDialog } from 'vant';
  168. import { showNotify } from 'vant'
  169. export default {
  170. components: {
  171. mNavbar,
  172. selectTime,
  173. selectTechnician,
  174. selectAddressPopup,
  175. selectCouponPopup,
  176. configPopup
  177. },
  178. data() {
  179. return {
  180. payMethod: 1,
  181. remark: '',
  182. agreement: false,
  183. selectTimeShow: false,
  184. selectTechnicianShow: false,
  185. selectCouponPopupShow: false,
  186. selectAddressPopupShow: false,
  187. remarkShow: false,
  188. selectTimeTitle: '',
  189. technicianDetail: {},
  190. projectDetail: {},
  191. time: {},
  192. address: {},
  193. coupon: {},
  194. userInfo: {},
  195. order: [],
  196. dateList: [],
  197. timeList: [],
  198. timeLoading: false,
  199. dateObj: '',
  200. price: 0, //用于保存商品原价
  201. temp: 0,//路费
  202. count: 0, //计算出的价格
  203. configPopupShow: false,
  204. config: [],
  205. keyValue: 'protocol',
  206. distance : 0,
  207. travelMoney : 0,
  208. selectDay : '', //用户选择的日期
  209. couponNum : 0
  210. }
  211. },
  212. onShow() {
  213. this.getOrderDetail()
  214. this.getUserInfo()
  215. this.getConfig()
  216. let today = this.dayjs()
  217. this.dateList.push(today)
  218. for (let i = 1; i < 7; i++) {
  219. this.dateList.push(today.add(i, 'day'))
  220. }
  221. },
  222. methods: {
  223. //获取订单详情
  224. getOrderDetail() {
  225. this.$api('getOrderVipDetail', {
  226. id: this.$route.query.orderId
  227. }, res => {
  228. if (res.code == 200) {
  229. this.projectDetail = res.result.shop
  230. this.technicianDetail = res.result.technician
  231. this.order = res.result.order
  232. this.getVipTenOrderList(this.dayjs())
  233. this.initPrice()
  234. }
  235. })
  236. },
  237. //获取技师上钟时间
  238. getVipTenOrderList(item) {
  239. this.selectDay = item
  240. this.timeLoading = true
  241. this.$api('getVipTenOrderList', {
  242. tenId: this.technicianDetail.id,
  243. name: item.format('dddd')
  244. }, res => {
  245. if (res.code == 200) {
  246. this.timeList = res.result
  247. }
  248. this.timeLoading = false
  249. })
  250. },
  251. //获取用户信息
  252. getUserInfo() {
  253. this.$api('getUserInfo', {}, res => {
  254. if (res.code == 200) {
  255. this.userInfo = res.result;
  256. }
  257. })
  258. },
  259. //点击返回箭
  260. leftClick() {
  261. let {current,id,distance,orderId} = this.$route.query
  262. if (current == 'technicianDetail') { //返回技师详情
  263. return uni.navigateTo({
  264. url: `/pages/technician/technicianDetail?id=${id}&distance=${distance}`
  265. })
  266. }
  267. if (current == 'orderDetail') { //返回订单详情
  268. return uni.navigateTo({
  269. url: `/pages/order/orderDetail?id=${orderId}`
  270. })
  271. }
  272. uni.navigateTo({ //返回技师选择列表
  273. url: `/pages/technician/selectTechnician?serviceId=${this.projectDetail.id}`
  274. })
  275. },
  276. //支付
  277. submit() {
  278. if (!this.address.id) {
  279. return this.selectAddressPopupShow = true
  280. }
  281. if (!this.time.id) {
  282. return this.selectTimeShow = true
  283. }
  284. if (!this.agreement) {
  285. return uni.showToast({
  286. title: '请勾选用户使用协议协议',
  287. icon: 'none'
  288. })
  289. }
  290. let data = {
  291. addressId: this.address.id, //地址id
  292. orderId: this.order.id, //订单id
  293. payType: this.payMethod, // 支付类型
  294. remark: this.remark, //备注
  295. serviceTime: this.time.id, //服务时间
  296. travelType: 1, //出行方式
  297. travelDistance: this.distance, //技师距离
  298. serviceDate : this.selectDay.format('YYYY-MM-DD')//服务时间
  299. }
  300. if (this.coupon.id) {
  301. data.couponId = this.coupon.id //优惠劵id
  302. }
  303. this.$api('payVipOrder', data, res => {
  304. if (res.code == 200) {
  305. if (this.payMethod == 1) { //余额支付
  306. showDialog({
  307. title: '支付成功',
  308. message: '订单支付成功!请前往订单查看',
  309. }).then(() => {
  310. this.paySusscess()
  311. });
  312. } else if (this.payMethod == 0) { //微信支付
  313. this.$wxPay(res,this.paySusscess,this.paySusscess)
  314. }
  315. }else{ //不管订单是否支付成功,直接跳订单页面
  316. this.paySusscess()
  317. }
  318. })
  319. },
  320. //显示选择技师上钟时间弹框
  321. onServiceTime() {
  322. this.selectTimeShow = true
  323. this.selectTimeTitle = '请选择服务时间'
  324. },
  325. //选择技师上钟时间
  326. selectTime(obj) {
  327. this.selectTimeShow = false
  328. this.time = obj.time
  329. this.dateObj = obj.date
  330. },
  331. //选择技师
  332. selectTechnician(item) {
  333. this.selectTechnicianShow = false
  334. this.technicianDetail = item
  335. },
  336. //选择优惠券
  337. selectCoupon(item) {
  338. if (item.useMoney > this.price) { //判断优惠券使用条件(满多少可用)
  339. this.selectCouponPopupShow = false
  340. return uni.showToast({icon: 'none',title: `此券需满${item.useMoney}可用`});
  341. }
  342. this.count = this.price //先恢复商品价格,防止多次选择优惠券前端多次减金额
  343. this.selectCouponPopupShow = false
  344. this.coupon = item
  345. this.count = this.price - item.money
  346. },
  347. //显示选择地址弹框
  348. selectAddress(item) {
  349. if(!item.latitude && !item.longitude){ //判断地址信息有没有经纬度信息,避免出现距离计算出现问题
  350. this.selectAddressPopupShow = false
  351. return uni.showToast({icon: 'none',title: '选择的地址异常,请选择其他地址或重新添加'});
  352. }
  353. this.selectAddressPopupShow = false
  354. this.address = item
  355. this.calculatedDistance(); //计算两地距离
  356. },
  357. wxPay() {
  358. this.$api('createOrderWXPay', {}, res => {
  359. if (res.code == 200) {
  360. this.$wxPay(res,this.paySusscess,this.paySusscess)
  361. }
  362. })
  363. },
  364. //获取配置信息
  365. getConfig() {
  366. this.$api('getConfig', {}, res => {
  367. if (res.code == 200) {
  368. this.config = res.result
  369. res.result.forEach(item => {
  370. if(item.keyValue == 'travel_money'){
  371. this.travelMoney = item.content
  372. }
  373. })
  374. }
  375. })
  376. },
  377. //计算距离
  378. calculatedDistance(){ //计算距离
  379. // Position.getLocation(result => {
  380. // this.distance = Position.calculateDistance(result.latitude, result.longitude, this.technicianDetail.latitude, this.technicianDetail.longitude)
  381. // //计算路费
  382. // if (this.distance < 2) {
  383. // this.temp = 0
  384. // }else{
  385. // this.temp = Number((this.distance * this.travelMoney).toFixed(2));
  386. // this.initPrice()
  387. // }
  388. // })
  389. if(this.$route.query.setKmOpen=='Y'){ //是否打开了假距离
  390. this.distance = this.$route.query.distance
  391. }else{
  392. this.distance = Position.calculateDistance(this.address.latitude, this.address.longitude, this.technicianDetail.latitude, this.technicianDetail.longitude)
  393. }
  394. //计算路费
  395. if (this.distance < 2) {
  396. this.temp = 0
  397. }else{
  398. this.temp = Number((this.distance * this.travelMoney).toFixed(2));
  399. this.initPrice()
  400. }
  401. },
  402. //初始化金额数据(用于前端计算)
  403. initPrice(){
  404. this.price = Number(this.order.money + this.temp).toFixed(2)
  405. this.count = Number(this.order.money + this.temp).toFixed(2)
  406. },
  407. //支付成功(跳转订单)
  408. paySusscess(){
  409. uni.reLaunch({
  410. url: '/pages/index/order?active=2'
  411. })
  412. },
  413. //获取优惠券数量
  414. countCouponNum(num){
  415. this.couponNum = num
  416. }
  417. }
  418. }
  419. </script>
  420. <style scoped lang="scss">
  421. body {
  422. background-color: #f3f3f3;
  423. }
  424. .payOrder {
  425. .bac {
  426. position: absolute;
  427. width: 100%;
  428. height: 100px;
  429. background: linear-gradient(to right, #4899a6, #6fc6ad);
  430. }
  431. .box {
  432. position: relative;
  433. width: calc(100% - 30px);
  434. margin: 15px;
  435. margin-top: 30rpx;
  436. min-height: 500px;
  437. border-radius: 10px;
  438. padding-bottom: 80px;
  439. .server-item {
  440. display: flex;
  441. flex-wrap: wrap;
  442. justify-content: space-between;
  443. background: white;
  444. border-radius: 15rpx;
  445. box-sizing: border-box;
  446. padding: 25rpx;
  447. margin: 20rpx 0rpx;
  448. .img-box {
  449. width: 150rpx;
  450. height: 150rpx;
  451. background: #ccc;
  452. border-radius: 10rpx;
  453. overflow: hidden;
  454. image {
  455. width: 100%;
  456. height: 100%;
  457. }
  458. }
  459. .server-info {
  460. width: calc(100% - 150rpx);
  461. box-sizing: border-box;
  462. padding: 10rpx 15rpx;
  463. display: flex;
  464. flex-direction: column;
  465. justify-content: space-around;
  466. .server-title {
  467. font-size: 15px;
  468. }
  469. .time-coupon,
  470. .price {
  471. display: flex;
  472. flex-wrap: wrap;
  473. align-items: center;
  474. }
  475. .time-coupon {
  476. margin: 10rpx 0rpx;
  477. font-size: 26rpx;
  478. image {
  479. width: 25rpx;
  480. height: 25rpx;
  481. }
  482. .time {
  483. color: #B8B8B8;
  484. margin-left: 6rpx;
  485. }
  486. }
  487. .coupon {
  488. display: flex;
  489. justify-content: center;
  490. align-items: center;
  491. background: #F29E45;
  492. color: white;
  493. width: 140rpx;
  494. height: 45rpx;
  495. border-radius: 10rpx;
  496. margin-left: 10rpx;
  497. }
  498. // .price {
  499. // font-size: 26rpx;
  500. // color: #B8B8B8;
  501. // .current-price {
  502. // font-size: 30rpx;
  503. // font-weight: 600;
  504. // color: #D34430;
  505. // }
  506. // .unit{
  507. // font-size: 20rpx;
  508. // }
  509. // }
  510. .sales-volume {
  511. display: flex;
  512. align-items: center;
  513. color: #B8B8B8;
  514. font-size: 26rpx;
  515. image {
  516. width: 25rpx;
  517. height: 25rpx;
  518. }
  519. }
  520. }
  521. }
  522. .icon {
  523. width: 14px;
  524. height: 14px;
  525. vertical-align: middle;
  526. padding: 6rpx;
  527. }
  528. .mileage {
  529. display: flex;
  530. flex-direction: column;
  531. padding: 10px;
  532. .top {
  533. padding: 5px 10px;
  534. padding-left: 25px;
  535. background-color: #A1D9CC99;
  536. font-size: 12px;
  537. position: relative;
  538. }
  539. .top::after {
  540. content: '';
  541. position: absolute;
  542. display: block;
  543. width: 8px;
  544. height: 8px;
  545. background-color: #6fc6ad;
  546. top: 50%;
  547. left: 10px;
  548. transform: translate(0, -40%);
  549. border-radius: 4px;
  550. }
  551. .info {
  552. padding: 10px;
  553. background-color: #ECFFFB;
  554. color: #888;
  555. font-size: 11px;
  556. line-height: 20px;
  557. }
  558. }
  559. .agreement {
  560. display: flex;
  561. justify-content: center;
  562. align-items: center;
  563. padding: 10px 0;
  564. .van-checkbox{
  565. margin-right: 5rpx;
  566. }
  567. }
  568. }
  569. .submit {
  570. position: fixed;
  571. bottom: 0;
  572. left: 0;
  573. width: 100%;
  574. height: 60px;
  575. background-color: #fff;
  576. display: flex;
  577. justify-content: space-between;
  578. align-items: center;
  579. .price {
  580. color: #F39637;
  581. padding: 0 20px;
  582. }
  583. .btn {
  584. background: linear-gradient(178deg, #4FD3BC, #60C285);
  585. color: white;
  586. width: 120px;
  587. height: 45px;
  588. border-radius: 23px;
  589. font-size: 16px;
  590. display: flex;
  591. justify-content: center;
  592. align-items: center;
  593. }
  594. }
  595. }
  596. </style>