getOrder.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. <template>
  2. <view class="order-content">
  3. <view class="step">
  4. <uni-steps :options="[{title: '停车'}, {title: '检查'}, {title: '下单'}]" :active="stepIndex" active-color="rgb(255,0,0)"></uni-steps>
  5. </view>
  6. <view class="step-content">
  7. <!-- 停车 -->
  8. <view v-if="stepIndex===0" class="step-item step-one">
  9. <text>请确认车辆是否停到指定位置</text>
  10. <image src="/static/img/step-one.png" mode="aspectFit"></image>
  11. </view>
  12. <!-- 检查 -->
  13. <view v-if="stepIndex===1" class="step-item step-two">
  14. <view class="item top">
  15. <text class="item-text">-请完成以下操作-</text>
  16. <image src="/static/img/cztis.png" mode="aspectFit"></image>
  17. <view class="care">
  18. 注意:洗车过程中禁止移动车辆和上下车
  19. </view>
  20. </view>
  21. <view class="item bottom" @click="lookMore">
  22. <view class="item-text">
  23. <text >超高加装件不能清洗</text>
  24. <view class="right">
  25. <text>查看更多</text>
  26. <u-icon name="arrow-right" size="28"></u-icon>
  27. </view>
  28. </view>
  29. <image src="/static/img/zyts.png" mode="aspectFit"></image>
  30. </view>
  31. </view>
  32. <!-- 下单 -->
  33. <view v-if="stepIndex===2" class="step-item step-three">
  34. <view class="choose">
  35. <view class="title">
  36. 请选择服务模式
  37. </view>
  38. <view class="list">
  39. <view :class="['item', serverIndex==index ?'avtive':'']" @click="chooseItem(index)" v-for="(item,index) in itemList" :key="index">
  40. <text>{{item.itemName}}</text>
  41. <text class="price">¥{{item.currentPrice}}</text>
  42. </view>
  43. <u-empty text="暂无服务项目" img-width="120" v-if="itemList.length==0 && status!='loading'" mode="list"></u-empty>
  44. </view>
  45. </view>
  46. <view class="choose-content">
  47. <view class="choose-item">
  48. <view class="item" @click="intoChooseCoupon">
  49. <text>优惠卷</text>
  50. <view v-if="checkedCoupon" class="right">
  51. <u-icon name="gift" color="rgb(255,0,0)" size="32"></u-icon>
  52. <text class="coopon">9.8元洗车券(¥-9.8)</text>
  53. <u-icon name="arrow-right" color="rgb(255,0,0)" size="32"></u-icon>
  54. </view>
  55. <view v-else class="right">
  56. <text >暂无可用优惠券</text>
  57. </view>
  58. </view>
  59. <view class="item phone">
  60. <text>手机号码</text>
  61. <view class="right">
  62. <text >{{userPhone}}</text>
  63. </view>
  64. </view>
  65. </view>
  66. <view class="read" @click="intoAgreement">
  67. <u-radio-group v-model="isRead">
  68. <u-radio shape="square" :disabled="isRead!='read'" name="read" active-color="red" icon-size="28" label-size="28">
  69. 点击阅读并同意
  70. <text>无人洗车</text>
  71. <text>《注意事项及服务协议》</text>
  72. </u-radio>
  73. </u-radio-group>
  74. </view>
  75. </view>
  76. </view>
  77. </view>
  78. <view class="step-footer">
  79. <button class="next-button" @click="nextStep" v-if="stepIndex!=2" type="warn">下一步</button>
  80. <view v-else class="pay">
  81. <text>合计:</text>
  82. <text class="amount">¥{{finalAmount}}</text>
  83. <view class="">
  84. <button @click="handleSubmit" type="warn">去付款</button>
  85. </view>
  86. </view>
  87. </view>
  88. </view>
  89. </template>
  90. <script>
  91. import uniSteps from '@/components/uni-steps/uni-steps.vue'
  92. import {getUserInfo} from '@/api/login.js'
  93. import {getStoreItems, saveOrder, signPay} from '@/api/order.js'
  94. export default {
  95. components: {
  96. uniSteps
  97. },
  98. data() {
  99. return {
  100. status: 'loadmore',
  101. userPhone: '',
  102. stepIndex: 0, // 当前步奏下标
  103. serverIndex: 0, // 选择服务下标
  104. itemList: [], // 服务类型
  105. isRead: '', // 是否同意协议
  106. couponList: [
  107. {
  108. id: 23432445,
  109. name: "满100减50",
  110. price: 100,
  111. yxTime: "2020-05-16",
  112. remarks: '优惠卷使用说明优惠卷使用说明优惠卷使用说明',
  113. checked: false
  114. },
  115. {
  116. id: 3544355,
  117. name: "满100减50",
  118. price: 100,
  119. yxTime: "2020-05-16",
  120. remarks: '优惠卷使用说明优惠卷使用说明优惠卷使用说明',
  121. checked: false
  122. },
  123. {
  124. id: 234234234,
  125. name: "满100减50",
  126. price: 100,
  127. yxTime: "2020-05-16",
  128. remarks: '优惠卷使用说明优惠卷使用说明优惠卷使用说明',
  129. checked: false
  130. },
  131. {
  132. id: 66264646,
  133. name: "满100减50",
  134. price: 100,
  135. yxTime: "2020-05-16",
  136. remarks: '优惠卷使用说明优惠卷使用说明优惠卷使用说明',
  137. checked: false
  138. },
  139. {
  140. id: 9794694698,
  141. name: "满100减50",
  142. price: 100,
  143. yxTime: "2020-05-16",
  144. remarks: '优惠卷使用说明优惠卷使用说明优惠卷使用说明',
  145. checked: false
  146. }
  147. ], // 用户可用优惠券
  148. checkedCoupon: null, // 用户当前所选优惠券
  149. amount: 0, // 所选服务项目总金额
  150. couponAmount: 0, // 优惠券优惠金额
  151. finalAmount: 0, // 用户最终所需支付金额
  152. }
  153. },
  154. onLoad(option) {
  155. // 存储当前扫码的设备及网点id
  156. // if(options.scene){
  157. // let scene=decodeURIComponent(options.scene);
  158. // //&是我们定义的参数链接方式
  159. // let userId=scene.split("&")[0];
  160. // let recommendId=scene.split('&')[1];
  161. // //其他逻辑处理。。。。。
  162. // }
  163. this.$store.state.vuex_orderInfo.bizId = option.bizId || '9898'
  164. this.$store.state.vuex_orderInfo.storeId = option.storeId || '100000'
  165. uni.removeStorageSync('stepIndex')
  166. // 注册全局监听事件
  167. uni.$once('read', this.read)
  168. this.getUserPhone()
  169. this.getServerList()
  170. },
  171. onUnload() {
  172. uni.removeStorageSync('stepIndex')
  173. },
  174. onShow() {
  175. const index = uni.getStorageSync('stepIndex')
  176. this.stepIndex = index ? index : 0
  177. console.log(this.stepIndex)
  178. },
  179. methods: {
  180. // 获取用户信息
  181. getUserPhone () {
  182. getUserInfo().then(res =>{
  183. console.log(res,'rrrrrrr')
  184. if(res.status == 200) {
  185. this.userPhone = res.data.mobile
  186. } else {
  187. uni.showToast({
  188. title: res.message,
  189. icon: 'none'
  190. })
  191. }
  192. })
  193. },
  194. // 查看更多注意事项
  195. lookMore () {
  196. uni.navigateTo({
  197. url: '/pages/careMore/careMore'
  198. })
  199. },
  200. // 获取服务列表
  201. getServerList () {
  202. this.status = 'loading'
  203. let storeId = this.$store.state.vuex_orderInfo.storeId
  204. getStoreItems({storeId:storeId}).then(res =>{
  205. this.status = 'loadmore'
  206. if (res.status == 200) {
  207. this.itemList = res.data
  208. this.serverIndex = 0
  209. this.getFinalAmount()
  210. } else {
  211. this.itemList = []
  212. this.toashMsg(res.message)
  213. }
  214. })
  215. },
  216. // 选择服务项目
  217. chooseItem(index) {
  218. this.serverIndex = index
  219. this.getFinalAmount()
  220. },
  221. // 下一步
  222. nextStep() {
  223. this.stepIndex = this.stepIndex===0 ? 1 : 2
  224. uni.setStorageSync('stepIndex', this.stepIndex)
  225. },
  226. // 已阅读
  227. read (e) {
  228. this.isRead = e.msg
  229. },
  230. // 获取用户可用优惠券
  231. getCouponList () {
  232. },
  233. // 格式化优惠券数据 获取优惠金额最大的优惠券 couponType 优惠券类型:FULLSUB满减/DISCOUNT折扣券/VOUCHER代金券
  234. formatCouponData (){
  235. let arr = []
  236. let _this = this
  237. this.couponList.map(item => {
  238. let data = {}
  239. data.id = item.couponReceivesId
  240. if (item.couponType == 'DISCOUNT') {
  241. console.log(_this.amount, '_this.amount')
  242. data.subAmount = Number((_this.amount * (1 - item.subAmount)).toFixed(2))
  243. } else {
  244. data.subAmount = item.couponType == 'FULLSUB' ? item.subAmount : item.price
  245. }
  246. arr.push(data)
  247. })
  248. console.log(arr, 'arr')
  249. // 比较数据中优惠金额最大的值 并返回该对象
  250. let obj = arr.reduce((p, v) => p.subAmount < v.subAmount ? v : p)
  251. console.log(obj)
  252. let p = this.couponList.find(item => item.couponReceivesId == obj.id)
  253. // 订单金额为0时,默认不使用优惠卷
  254. if (this.amount != 0){
  255. this.checkedCoupon = p
  256. this.couponAmount = obj.subAmount > this.amount ? this.amount : obj.subAmount
  257. } else {
  258. this.checkedCoupon = null
  259. this.couponAmount = 0
  260. }
  261. // 计算合计
  262. this.getFinalAmount()
  263. },
  264. // 计算合计
  265. getFinalAmount () {
  266. this.amount = this.itemList[this.serverIndex].currentPrice
  267. let ret = this.amount - this.couponAmount
  268. this.finalAmount = ret.toFixed(2)
  269. },
  270. // 选择优惠券
  271. intoChooseCoupon () {
  272. uni.navigateTo({
  273. url: `/pages/coupon/chooseCoupon/chooseCoupon?list=${encodeURIComponent(JSON.stringify(this.couponList))}`
  274. })
  275. },
  276. // 打开服务协议
  277. intoAgreement () {
  278. uni.navigateTo({
  279. url: '/pages/agreement/agreement'
  280. })
  281. },
  282. // 去付款 保存订单
  283. handleSubmit (){
  284. if(this.itemList.length==0){
  285. this.toashMsg('请先选择服务')
  286. return
  287. }
  288. if (this.isRead !='read') {
  289. this.toashMsg('请先阅读并同意无人洗车《注意事项及服务协议》!')
  290. return
  291. } else if (this.itemList.length==0) {
  292. this.toashMsg('暂无服务项目')
  293. return
  294. }
  295. uni.showLoading({
  296. title: '请求中...',
  297. mask: true
  298. })
  299. let item = this.itemList[this.serverIndex]
  300. let params = {
  301. "itemId": item.itemId, // 服务id
  302. "itemCode": item.itemCode,
  303. "storeId": 100000, // 门店id
  304. "deviceId": 100000, // 设备id
  305. "orderTime": this.$u.timeFormat(Date.now(), 'yyyy-mm-dd hh:MM:ss'),
  306. "payableAmount": this.amount, // 应付金额 即优惠前金额
  307. "paymentAmount": this.finalAmount // 实收金额 即优惠后金额
  308. }
  309. saveOrder(params).then(res =>{
  310. if (res.status==200) {
  311. let data = res.data
  312. // 保存成功后 请求预支付返回吊起微信支付所需参数
  313. this.getPayData(data)
  314. this.$store.state.vuex_orderInfo.itemCode = data.itemCode
  315. this.$store.state.vuex_orderInfo.orderNo = data.orderNo
  316. this.$store.state.vuex_orderInfo.duration = item.duration
  317. } else {
  318. uni.hideLoading()
  319. // 刷新服务项
  320. this.getServerList()
  321. this.toashMsg(res.message)
  322. }
  323. })
  324. },
  325. // 预支付 返回微信支付所需参数
  326. getPayData (orderData) {
  327. signPay({orderId:orderData.id}).then(res =>{
  328. console.log(res,'预支付')
  329. uni.hideLoading()
  330. if (res.status == 200) {
  331. let data = res.data
  332. // 0元订单直接支付成功,不用吊微信支付
  333. if (data.tradeStatus && data.tradeStatus=="PAID") {
  334. // 付款成功后开始洗车
  335. uni.redirectTo({
  336. url:`/pages/work/index/index`
  337. })
  338. } else {
  339. uni.requestPayment({
  340. provider: 'wxpay',
  341. timeStamp: data.timeStamp,
  342. nonceStr: data.nonceStr,
  343. package: data.package,
  344. signType: data.signType,
  345. paySign: data.paySign,
  346. success: function (res) {
  347. console.log('success:' + JSON.stringify(res));
  348. // 付款成功后开始洗车
  349. uni.redirectTo({
  350. url:`/pages/work/index/index`
  351. })
  352. },
  353. fail: function (err) {
  354. console.log('fail:' + JSON.stringify(err));
  355. }
  356. });
  357. }
  358. } else {
  359. this.toashMsg(res.message)
  360. }
  361. })
  362. }
  363. }
  364. }
  365. </script>
  366. <style lang="scss">
  367. page{
  368. height: 100%;
  369. }
  370. .order-content{
  371. width: 100%;
  372. height: 100%;
  373. display: flex;
  374. flex-direction: column;
  375. .step{
  376. padding: 40rpx 0;
  377. }
  378. .step-content{
  379. flex: 1;
  380. width: 100%;
  381. display: flex;
  382. flex-direction: column;
  383. .step-item{
  384. width: 100%;
  385. display: flex;
  386. flex-direction: column;
  387. align-items: center;
  388. flex: 1;
  389. }
  390. // 第一步
  391. .step-one{
  392. text{
  393. color: #999;
  394. margin: 40rpx 0;
  395. }
  396. }
  397. // 第二步
  398. .step-two{
  399. background-color: #F8F8F8;
  400. justify-content: space-around;
  401. .item{
  402. background-color: #fff;
  403. width: 80%;
  404. height: 45%;
  405. display: flex;
  406. flex-direction: column;
  407. align-items: center;
  408. image{
  409. width: 80%;
  410. flex: 1;
  411. }
  412. }
  413. .top{
  414. text{
  415. color: #df928e;
  416. font-size: 24rpx;
  417. }
  418. .item-text{
  419. padding-top: 20rpx;
  420. }
  421. .care{
  422. padding: 10rpx 20rpx;
  423. background-color: #ff805b;
  424. border-radius: 30rpx;
  425. color: #fff;
  426. font-size: 24rpx;
  427. margin-bottom: 20rpx;
  428. }
  429. }
  430. .bottom{
  431. text{
  432. font-size: 24rpx;
  433. color: #333;
  434. }
  435. .item-text{
  436. width: 100%;
  437. padding:0 20rpx;
  438. display: flex;
  439. justify-content: space-between;
  440. padding-top: 20rpx;
  441. }
  442. }
  443. }
  444. // 第三步 下单
  445. .step-three{
  446. .choose{
  447. width: 100%;
  448. height: auto;
  449. padding-bottom: 60rpx;
  450. display: flex;
  451. flex-direction: column;
  452. align-items: center;
  453. border-bottom: 1px solid #eee;
  454. .title{
  455. color: #666;
  456. }
  457. .list{
  458. width: 100%;
  459. display: flex;
  460. justify-content: space-around;
  461. padding: 0 20rpx;
  462. .item{
  463. width: 30%;
  464. height: 140rpx;
  465. display: flex;
  466. flex-direction: column;
  467. align-items: center;
  468. justify-content: center;
  469. border: 1px solid #eee;
  470. border-radius: 15rpx;
  471. margin-top: 30rpx;
  472. color: #999;
  473. .price{
  474. font-size: 34rpx;
  475. margin-top: 10rpx;
  476. }
  477. }
  478. .avtive{
  479. color: #333;
  480. border-color: rgb(255,0,0);
  481. .price{
  482. color: rgb(255,0,0);
  483. }
  484. }
  485. }
  486. }
  487. .choose-content{
  488. flex: 1;
  489. width: 100%;
  490. .choose-item{
  491. width: 100%;
  492. .item{
  493. padding: 0 30rpx;
  494. }
  495. }
  496. .item{
  497. width: 100%;
  498. height: 100rpx;
  499. display: flex;
  500. align-items: center;
  501. justify-content: space-between;
  502. border-bottom: 1px solid #eee;
  503. .coopon{
  504. color: rgb(255,0,0);
  505. }
  506. }
  507. .phone{
  508. border-bottom: none;
  509. }
  510. .read{
  511. width: 100%;
  512. border-top: 1px solid #eee;
  513. padding-top: 40rpx;
  514. display: flex;
  515. justify-content: center;
  516. text{
  517. color: #999;
  518. }
  519. text:last-child{
  520. color: #ff9ba5;
  521. }
  522. }
  523. }
  524. }
  525. }
  526. .step-footer{
  527. width: 100%;
  528. background-color: #fff;
  529. .next-button{
  530. margin: 0;
  531. border-radius: 0;
  532. padding: 10rpx 0;
  533. }
  534. .pay{
  535. width: 100%;
  536. height: 100%;
  537. padding: 10rpx;
  538. border-top: 1px solid #eee;
  539. display: flex;
  540. align-items: center;
  541. justify-content: flex-end;
  542. .amount{
  543. color: rgb(255,0,0);
  544. font-size: 36rpx;
  545. margin-right: 40rpx;
  546. }
  547. button{
  548. width: 200rpx;
  549. }
  550. }
  551. }
  552. }
  553. </style>