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.

730 lines
18 KiB

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