order.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. <template>
  2. <view class="item">
  3. <view class="between mb10">
  4. <view class="meal-no">{{ item.takeupCode }}</view>
  5. <view class="type-name">{{ formatOrderType(item) }}</view>
  6. <view class="status-name">{{ item.statusName }}</view>
  7. </view>
  8. <view class="time pd24 fs14 between">
  9. <view class="left-time">
  10. {{ formatOrderTime(item) }}
  11. </view>
  12. <view class="order-status">
  13. </view>
  14. </view>
  15. <view class="pd24 fs14">
  16. 备注: {{ item.customerMes || '无' }}
  17. </view>
  18. <view class="between around mlr24">
  19. <view class="col">
  20. <view class="label desc">订单号:</view>
  21. <view class="text">{{ item.orderCode }}</view>
  22. </view>
  23. <view class="col">
  24. <view class="label desc">下单时间:</view>
  25. <view class="text">{{ item.createDateStr }}</view>
  26. </view>
  27. </view>
  28. <view class="desc mlr24 borbtm mt20">
  29. <view class="row">
  30. <view class="label">{{ item.orderName }} {{ item.orderTel }}</view>
  31. <view class="phone-btn" @click="takePhone(item)">
  32. <u-icon name="phone-fill" color="#fff"></u-icon>
  33. </view>
  34. </view>
  35. <view class="row" v-if="item.orderType == 1 || item.orderType == 2">
  36. <view class="label">{{ item.orderAddress }}</view>
  37. </view>
  38. </view>
  39. <view class="goods borbtm mlr24 fs14">
  40. <view class="between w100">
  41. <view class="label">商品</view>
  42. <view class="btn" @click="handItemOrderDetail(item)">{{ !isShowGoods ? '查看' : '收起' }}</view>
  43. </view>
  44. <view class="goods-info" v-if="isShowGoods">
  45. <view class="goods-row" v-for="detail in item.detailList">
  46. <view class="goods-name">{{ detail.goodsName }} {{detail.propertys == '' ? '' : '(' + detail.propertys + ')'}}</view>
  47. <view class="goods-count">×{{ detail.buyCount }}</view>
  48. <view class="price">¥{{ moneyConverter(detail.salesPrice) }}</view>
  49. </view>
  50. <view class="params" >
  51. <view class="name">餐盒费</view>
  52. <view class="price">¥{{ moneyConverter(item.packingFee) }}</view>
  53. </view>
  54. <view class="params" v-if="(item.deliveryFee + item.sortingFee + item.climbingFee) > 0">
  55. <view class="name">配送费</view>
  56. <view class="price" :style="item.deliveryDiscountsFlag == 1 ? 'text-decoration: line-through' : ''">¥{{ moneyConverter(item.deliveryFee + item.sortingFee + item.climbingFee) }}</view>
  57. </view>
  58. <view class="params" v-if="item.newcusDiscounts > 0">
  59. <view class="name">新客立减</view>
  60. <view class="price">-¥{{ moneyConverter(item.newcusDiscounts) }}</view>
  61. </view>
  62. <view class="params" v-if="item.fullDiscounts > 0">
  63. <view class="name">满减</view>
  64. <view class="price">-¥{{ moneyConverter(item.fullDiscounts) }}</view>
  65. </view>
  66. <view class="params" v-if="item.couponCost > 0">
  67. <view class="name">优惠券</view>
  68. <view class="price">-¥{{ moneyConverter(item.couponCost) }}</view>
  69. </view>
  70. </view>
  71. </view>
  72. <view class="settle borbtm mlr24 fs14">
  73. <view class="between w100">
  74. <view class="label">结算信息</view>
  75. <view class="btn" @click="handItemOrderSettle(item)">{{ !isShowSettle ? '查看' : '收起' }}</view>
  76. </view>
  77. <view class="settle-row" v-if="isShowSettle">
  78. <view class="settle-item">
  79. <view class="name">顾客实付</view>
  80. <view class="price">¥<text>{{ moneyConverter(item.orderFee) }}</text></view>
  81. </view>
  82. <view class="settle-item">
  83. <view class="name">扣除配送费</view>
  84. <view class="price">-¥<text>{{ moneyConverter(item.deliveryFee + item.sortingFee + item.climbingFee) }}</text></view>
  85. </view>
  86. <view class="settle-item">
  87. <view class="name">微信扣点</view>
  88. <view class="price">-¥<text>{{ moneyConverter(calcPoints(item.wxPoint / 1000, item.orderFee)) }}</text></view>
  89. </view>
  90. <view class="settle-item">
  91. <view class="name">平台扣点</view>
  92. <view class="price">
  93. -¥<text>
  94. {{ moneyConverter(calcPoints(Number(item.commissionRate) / Number(1000) ,
  95. item.orderFee - item.deliveryFee - item.sortingFee - item.climbingFee)) > 0 ? moneyConverter(calcPoints(Number(item.commissionRate) / Number(1000) ,
  96. item.orderFee - item.deliveryFee - item.sortingFee - item.climbingFee)) : 0 }}
  97. </text>
  98. </view>
  99. </view>
  100. <view class="settle-item">
  101. <view class="name">本单预计收入</view>
  102. <view class="price">
  103. {{
  104. incomeFormatter(item)
  105. }}
  106. </view>
  107. </view>
  108. </view>
  109. </view>
  110. <view class="tools-btn mlr24 mt20" v-if="showBtn != 0">
  111. <view class="taking" v-if="item.status == 10" @click="handItemTaking(item)">接单</view>
  112. <view class="item-btn" v-if="item.status == 10" @click="handTurnDownOut(item)">拒绝接单</view>
  113. <view class="item-btn" v-if="item.status == 30 && (item.orderType == 3 || item.orderType == 4)" @click="handComfirmPickOut(item)">确认自提</view>
  114. <view class="item-btn" v-if="item.status > 10 && item.status < 60" @click="handAllPriceRefund(item)">全额退款</view>
  115. <view class="item-btn" v-if="item.status == 8 || (item.status > 10 && item.status < 60)" @click="handPrintDenomination(item)">小票打印</view>
  116. </view>
  117. </view>
  118. </template>
  119. <script>
  120. import {mapState} from 'vuex';
  121. export default {
  122. name: 'order',
  123. props: ['item', 'showBtn'],
  124. data () {
  125. return {
  126. isShowGoods: false,
  127. isShowSettle: false,
  128. takeUrl: '/storeOrderApi/receiveOrder',
  129. refuseUrl: '/storeOrderApi/refuseOrder',
  130. pickUrl: '/storeOrderApi/selfPickUp',
  131. refundUrl: '/storeOrderApi/orderRefund',
  132. printUrl: '/storeOrderApi/printOrder',
  133. handle: false,
  134. }
  135. },
  136. computed: {
  137. ...mapState(['storeInfo'])
  138. },
  139. methods: {
  140. // 堂食 / 外卖 渲染
  141. formatOrderTime (item) {
  142. let str = item.requireDateStr.slice(item.requireDateStr.length - 8, item.requireDateStr.length - 3);
  143. let desc = "";
  144. if (item.orderType == 4) {
  145. desc = "堂食时间 "
  146. } else if (item.orderType == 3) {
  147. desc = "取餐时间 "
  148. } else {
  149. desc = "送达时间 "
  150. }
  151. return desc + str;
  152. },
  153. formatOrderType (item) {
  154. if (item.orderType == 1 || item.orderType == 2) {
  155. return '外卖订单'
  156. } else if (item.orderType == 3) {
  157. return '自提订单'
  158. } else if (item.orderType == 4) {
  159. return '堂食订单'
  160. }
  161. },
  162. incomeFormatter(item) {
  163. const orderFee = this.moneyConverter(item.orderFee);
  164. const deliveryFee = this.moneyConverter(item.deliveryFee + item.sortingFee + item.climbingFee);
  165. const wxPoints = this.moneyConverter(this.calcPoints(item.wxPoint / 1000, item.orderFee));
  166. const commissionPoints = this.moneyConverter(this.calcPoints(Number(item.commissionRate) / Number(1000) ,
  167. item.orderFee - item.deliveryFee - item.sortingFee - item.climbingFee)) > 0 ? this.moneyConverter(this.calcPoints(Number(item.commissionRate) / Number(1000) ,
  168. item.orderFee - item.deliveryFee - item.sortingFee - item.climbingFee)) : 0
  169. const income = this.toFixed2(orderFee - deliveryFee - wxPoints - commissionPoints);
  170. if (income > 0) {
  171. return '¥' + income;
  172. } else {
  173. return '-¥' + Math.abs(income)
  174. }
  175. },
  176. // 查看商品
  177. handItemOrderDetail (item) {
  178. this.isShowGoods = !this.isShowGoods
  179. },
  180. // 查看结算信息
  181. handItemOrderSettle (item) {
  182. this.isShowSettle = !this.isShowSettle
  183. },
  184. // taking 接单
  185. handItemTaking (item) {
  186. if (this.handle) {
  187. return;
  188. }
  189. this.handle = true;
  190. uni.showLoading({
  191. title: '加载中'
  192. })
  193. var dateStr = (new Date()).getTime();
  194. var sign = this.getSign(dateStr);
  195. this.requst({
  196. url: this.takeUrl,
  197. data: {
  198. timestamp: dateStr,
  199. sign: sign,
  200. orderId: this.item.orderId
  201. },
  202. success: res => {
  203. this.handle = false;
  204. if (res.data.rtnBean.rtnCode == 0) {
  205. if (res.data.obj == 0) {
  206. this.$emit('loadOrder', res.data.rtnBean.rtnMsg)
  207. } else {
  208. this.$emit('loadOrder', '接单成功')
  209. }
  210. } else {
  211. if (res.data.rtnBean.rtnMsg != '') {
  212. this.$api.msg(res.data.rtnBean.rtnMsg);
  213. }
  214. }
  215. uni.hideLoading()
  216. },
  217. fail: (e) => {
  218. console.log("接口调用失败:" + JSON.stringify(e));
  219. this.handle = false;
  220. uni.hideLoading()
  221. },
  222. });
  223. },
  224. handTurnDownOut (item) {
  225. let that = this
  226. uni.showModal({
  227. title: '提示',
  228. content: '是否拒绝该订单?',
  229. success: function (r) {
  230. if (r.confirm) {
  231. that.handTurnDown(item);
  232. } else if (r.cancel) {
  233. }
  234. }
  235. })
  236. },
  237. // 拒单
  238. handTurnDown (item) {
  239. if (this.handle) {
  240. return;
  241. }
  242. this.handle = true;
  243. uni.showLoading({
  244. title: '加载中'
  245. })
  246. var dateStr = (new Date()).getTime();
  247. var sign = this.getSign(dateStr);
  248. this.requst({
  249. url: this.refuseUrl,
  250. data: {
  251. timestamp: dateStr,
  252. sign: sign,
  253. orderId: this.item.orderId,
  254. storeUserId: this.storeInfo.storeUserId
  255. },
  256. success: res => {
  257. this.handle = false;
  258. if (res.data.rtnBean.rtnCode == 0) {
  259. this.$emit('loadOrder', '拒单成功')
  260. } else {
  261. if (res.data.rtnBean.rtnMsg != '') {
  262. this.$api.msg(res.data.rtnBean.rtnMsg);
  263. }
  264. }
  265. uni.hideLoading()
  266. },
  267. fail: (e) => {
  268. console.log("接口调用失败:" + JSON.stringify(e));
  269. this.handle = false;
  270. uni.hideLoading()
  271. },
  272. });
  273. },
  274. calcPoints(rate, orderFee) {
  275. return (Number(orderFee) * Number(rate));
  276. },
  277. handComfirmPickOut (e) {
  278. let that = this
  279. uni.showModal({
  280. title: '提示',
  281. content: '是否将该订单标记为自取?',
  282. success: function (r) {
  283. if (r.confirm) {
  284. that.handComfirmPick(e);
  285. } else if (r.cancel) {
  286. }
  287. }
  288. })
  289. },
  290. handComfirmPick (e) {
  291. if (this.handle) {
  292. return;
  293. }
  294. this.handle = true;
  295. uni.showLoading({
  296. title: '加载中'
  297. })
  298. var dateStr = (new Date()).getTime();
  299. var sign = this.getSign(dateStr);
  300. this.requst({
  301. url: this.pickUrl,
  302. data: {
  303. timestamp: dateStr,
  304. sign: sign,
  305. orderId: e.orderId,
  306. },
  307. success: res => {
  308. this.handle = false;
  309. if (res.data.rtnBean.rtnCode == 0) {
  310. this.$emit('loadOrder', '自取成功')
  311. } else {
  312. if (res.data.rtnBean.rtnMsg != '') {
  313. this.$api.msg(res.data.rtnBean.rtnMsg);
  314. }
  315. }
  316. uni.hideLoading()
  317. },
  318. fail: (e) => {
  319. console.log("接口调用失败:" + JSON.stringify(e));
  320. this.handle = false;
  321. uni.hideLoading()
  322. },
  323. });
  324. },
  325. // 全额退款
  326. handAllPriceRefund (item) {
  327. let that = this
  328. uni.showModal({
  329. title: '提示',
  330. content: '是否将本单全额退款?',
  331. success: function (r) {
  332. if (r.confirm) {
  333. that.doRefund(item);
  334. } else if (r.cancel) {
  335. }
  336. }
  337. });
  338. },
  339. doRefund (item) {
  340. if (this.handle) {
  341. return;
  342. }
  343. this.handle = true;
  344. uni.showLoading({
  345. title: '加载中'
  346. })
  347. var dateStr = (new Date()).getTime();
  348. var sign = this.getSign(dateStr);
  349. this.requst({
  350. url: this.refundUrl,
  351. data: {
  352. timestamp: dateStr,
  353. sign: sign,
  354. orderId: item.orderId,
  355. storeUserId: this.storeInfo.storeUserId
  356. },
  357. success: res => {
  358. this.handle = false;
  359. if (res.data.rtnBean.rtnCode == 0) {
  360. this.$emit('loadOrder', '退款成功')
  361. } else {
  362. if (res.data.rtnBean.rtnMsg != '') {
  363. this.$api.msg(res.data.rtnBean.rtnMsg);
  364. }
  365. }
  366. uni.hideLoading()
  367. },
  368. fail: (e) => {
  369. console.log("接口调用失败:" + JSON.stringify(e));
  370. this.handle = false;
  371. uni.hideLoading()
  372. },
  373. });
  374. },
  375. // 小票打印
  376. handPrintDenomination (item) {
  377. if (this.handle) {
  378. return;
  379. }
  380. this.handle = true;
  381. uni.showLoading({
  382. title: '加载中'
  383. })
  384. var dateStr = (new Date()).getTime();
  385. var sign = this.getSign(dateStr);
  386. this.requst({
  387. url: this.printUrl,
  388. data: {
  389. timestamp: dateStr,
  390. sign: sign,
  391. orderId: item.orderId,
  392. },
  393. success: res => {
  394. if (res.data.rtnBean.rtnCode == 0) {
  395. uni.showToast({
  396. title: '正在打印',
  397. icon: 'none'
  398. })
  399. } else {
  400. if (res.data.rtnBean.rtnMsg != '') {
  401. this.$api.msg(res.data.rtnBean.rtnMsg);
  402. }
  403. }
  404. this.handle = false;
  405. uni.hideLoading()
  406. },
  407. fail: (e) => {
  408. console.log("接口调用失败:" + JSON.stringify(e));
  409. this.handle = false;
  410. uni.hideLoading()
  411. },
  412. });
  413. },
  414. toFixed2(money) {
  415. return Math.round(money * 100) / 100
  416. },
  417. // 商家客服
  418. takePhone(item){
  419. uni.makePhoneCall({
  420. phoneNumber: item.orderTel,
  421. success:function(e){
  422. },
  423. fail:function(e){
  424. }
  425. })
  426. },
  427. },
  428. onLoad () {}
  429. }
  430. </script>
  431. <style lang="scss" scoped>
  432. .fs14 {
  433. font-size: $font-base;
  434. }
  435. .pd24 {
  436. padding: 0 24rpx;
  437. box-sizing: border-box;
  438. }
  439. .mlr24 {
  440. margin: 0 24rpx;
  441. }
  442. .ptb10 {
  443. padding: 10rpx 0;
  444. box-sizing: border-box;
  445. }
  446. .mt10 {
  447. margin-top: 10rpx;
  448. }
  449. .mt20 {
  450. margin-top: 20rpx;
  451. }
  452. .mb10 {
  453. margin-bottom: 10rpx;
  454. }
  455. .w100 {
  456. width: 100%;
  457. }
  458. .borbtm {
  459. border-bottom: 2rpx solid #ececec;
  460. }
  461. .text {
  462. color: $text-color;
  463. }
  464. .desc {
  465. color: $desc-color;
  466. }
  467. .item {
  468. background-color: #fff;
  469. border-radius: 20rpx;
  470. margin-bottom: 20rpx;
  471. padding-bottom: 20rpx;
  472. box-sizing: border-box;
  473. }
  474. .between {
  475. height: 56rpx;
  476. @include between;
  477. }
  478. .meal-no {
  479. width: 156rpx;
  480. height: 56rpx;
  481. border-radius: 56rpx;
  482. border-radius: 20rpx 28rpx 28rpx 0;
  483. background-color: #000;
  484. color: #fff;
  485. @include flexCenter;
  486. font-size: $font-base;
  487. }
  488. .type-name, .status-name {
  489. height: 56rpx;
  490. line-height: 56rpx;
  491. }
  492. .type-name {
  493. flex: 1;
  494. margin-left: 20rpx;
  495. }
  496. .status-name {
  497. font-size: $font-base;
  498. color: #101010;
  499. margin-right: 24rpx;
  500. }
  501. .time {
  502. color: $theme-color;
  503. }
  504. .order-status {
  505. color: $icon-color;
  506. }
  507. .around {
  508. width: calc(100% - 48rpx);
  509. height: 80rpx;
  510. font-size: $font-sm;
  511. border-bottom: 2rpx solid #ececec;
  512. .col {
  513. flex: 1;
  514. }
  515. }
  516. .phone-btn {
  517. width: 40rpx;
  518. height: 40rpx;
  519. border-radius: 40rpx;
  520. background-color: $theme-color;
  521. @include flexCenter;
  522. }
  523. .row {
  524. width: 100%;
  525. @include between;
  526. font-size: $font-sm;
  527. margin-bottom: 10rpx;
  528. }
  529. .goods, .settle {
  530. .between {
  531. height: 80rpx;
  532. }
  533. .btn {
  534. font-size: $font-sm;
  535. color: $icon-color;
  536. width: 80rpx;
  537. height: 40rpx;
  538. border-radius: 40rpx;
  539. @include flexCenter;
  540. border: 2rpx solid $icon-color;
  541. }
  542. }
  543. .tools-btn {
  544. @include flexStart;
  545. .taking, .item-btn {
  546. height: 52rpx;
  547. @include flexCenter;
  548. border-radius: 52rpx;
  549. font-size: $font-sm;
  550. }
  551. .taking {
  552. width: 140rpx;
  553. background-color: $theme-color;
  554. color: #fff;
  555. margin-right: 20rpx;
  556. }
  557. .item-btn {
  558. width: 200rpx;
  559. color: $icon-color;
  560. border: 2rpx solid $icon-color;
  561. margin-right: 20rpx;
  562. }
  563. }
  564. .goods-row {
  565. @include between(flex-start);
  566. font-size: $font-sm;
  567. margin-bottom: 20rpx;
  568. .goods-name {
  569. flex: 2;
  570. }
  571. .goods-count, .price {
  572. flex: 1;
  573. text-align: right;
  574. }
  575. }
  576. .params {
  577. @include between;
  578. margin-bottom: 10rpx;
  579. }
  580. .settle-item {
  581. @include between;
  582. margin-bottom: 10rpx;
  583. }
  584. </style>