index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. <template>
  2. <app-layout>
  3. <view>
  4. <view class="scan-head dir-top-nowrap main-center">
  5. <view class="order-name">订单金额</view>
  6. <view class="scan-price dir-left-nowrap cross-bottom" @click="openPriceModel">
  7. <view class="order-key">¥</view>
  8. <view class="order-value">{{list.price}}</view>
  9. </view>
  10. <view class="scan-line"></view>
  11. <!-- 优惠 -->
  12. <view class="dir-left-nowrap cross-center scan-offer">
  13. <view class="box-grow-1">订单优惠</view>
  14. <view class="box-grow-0">
  15. <view v-if="list.preferential_money > 0" class="red">
  16. -¥{{list.preferential_money}}
  17. </view>
  18. <view v-else-if="list.price > 0" class="gray">暂无优惠</view>
  19. </view>
  20. </view>
  21. <!-- 优惠券 -->
  22. <view class="dir-left-nowrap cross-center scan-offer">
  23. <view class="box-grow-1">优惠劵</view>
  24. <view class="box-grow-0 coupon-right">
  25. <view v-if="list.coupon_id" @click="setCoupon" class="red">
  26. -¥{{list.coupon_preferential_money}}
  27. </view>
  28. <view v-else-if="list.price > 0 && list.can_coupon_num > 0" class="gray"
  29. @click="setCoupon">选择优惠券
  30. </view>
  31. <view v-else-if="list.price > 0" class="gray">暂无可用优惠券</view>
  32. </view>
  33. <view class="box-grow-0 cross-center">
  34. <icon class="icon-right"></icon>
  35. </view>
  36. </view>
  37. <!-- 积分抵扣 -->
  38. <view v-if="list.price > 0 && activity && integral.user_integral_num >= integral.member_integral && list.integral_deduction > 0"
  39. class="dir-left-nowrap cross-center scan-offer">
  40. <view class="box-grow-1 cross-center dir-left-nowrap">
  41. <view>
  42. <text>使用{{list.use_integral_num}}积分抵扣</text>
  43. <text class="red">{{list.integral_deduction}}</text>
  44. <text>元</text>
  45. </view>
  46. <view @click="getIntegralInfo" class="main-center cross-center">
  47. <icon class="scan-integral-icon"></icon>
  48. </view>
  49. </view>
  50. <view class="box-grow-0" @click="handleUseIntegral">
  51. <icon v-if="list.use_integral == 1" class="scan-integral-switch check"></icon>
  52. <icon v-else class="scan-integral-switch uncheck"></icon>
  53. </view>
  54. </view>
  55. <!-- 备注 -->
  56. <view class="dir-left-nowrap scan-offer">
  57. <input @input="bindTextBlur" :value="remark" class="scan-input" placeholder="添加备注"/>
  58. </view>
  59. <view class="scan-line"></view>
  60. <view class="scan-remark cross-center dir-left-nowrap main-center">
  61. <view class="key">应付金额</view>
  62. <view class="value">¥{{list.pay_price}}</view>
  63. </view>
  64. </view>
  65. <view class="main-center cross-center scan-btn">
  66. <app-button @click="submit"
  67. color="#ffffff"
  68. font-size="32"
  69. height="88"
  70. width="702"
  71. :background="list.price > 0 ? '#ff4544': '#cdcdcd'"
  72. :disabled="list.price <= 0"
  73. round>已与店员确认,立即买单
  74. </app-button>
  75. </view>
  76. <view class="scan-end" v-if="activity.rules">
  77. <view class="dir-left-nowrap cross-center">
  78. <view class="icon"></view>
  79. <view>规则说明</view>
  80. </view>
  81. <text space="nbsp">{{activity.rules}}</text>
  82. </view>
  83. </view>
  84. <!-- MODEL -->
  85. <view v-if="price_modal" class="scan-modal show bt">
  86. <view class="scan-modal-bg"></view>
  87. <view class="scan-modal-pic main-center">
  88. <view class="info-model cross-center dir-top-nowrap">
  89. <view class="order-title">订单金额</view>
  90. <view class="info-box dir-left-nowrap cross-center">
  91. <input focus class="info-input" @input="setTempInput" :value="tmp_price" type="digit"
  92. placeholder-class="place" placeholder="输入支付金额"/>
  93. <view>元</view>
  94. </view>
  95. <view class="info-end dir-left-nowrap cross-center">
  96. <view @click="closePriceModel" class="box-grow-1 main-center cross-center">取消</view>
  97. <view class="box-grow-0 info-line"></view>
  98. <view @click="calcPrice" class="box-grow-1 red main-center cross-center">确认</view>
  99. </view>
  100. </view>
  101. </view>
  102. </view>
  103. </app-layout>
  104. </template>
  105. <script>
  106. export default {
  107. name: "index",
  108. components: {},
  109. data() {
  110. return {
  111. page_loading: true,
  112. tmp_price: '',
  113. edit_status: true,
  114. price_modal: false,
  115. activity: null,
  116. remark: '',
  117. integral: {
  118. user_integral_num: '0',
  119. },
  120. list: {
  121. price: '',
  122. pay_price: 0.00,
  123. use_integral: 0,
  124. activity_id: 0,
  125. coupon_id: 0,
  126. can_coupon_num: 0,
  127. integral_explain: [],
  128. },
  129. clear: false,
  130. }
  131. },
  132. onShow: function () {
  133. const self = this;
  134. const userCoupon = self.$store.state.scanCode.userCoupon;
  135. if (userCoupon) {
  136. self.list.coupon_id = userCoupon.id;
  137. self.calcPrice();
  138. } else {
  139. self.list.coupon_id = 0
  140. }
  141. if (self.clear) {
  142. console.log('onShow => clear');
  143. [
  144. self.edit_status,
  145. self.clear,
  146. self.remark,
  147. self.tmp_price,
  148. self.list,
  149. ] = [
  150. true,
  151. false,
  152. '',
  153. '',
  154. {
  155. price: '',
  156. pay_price: 0.00,
  157. use_integral: 0,
  158. activity_id: 0,
  159. coupon_id: 0,
  160. can_coupon_num: 0,
  161. integral_explain: [],
  162. }
  163. ]
  164. }
  165. },
  166. onLoad: function (options) {
  167. const self = this;
  168. if (options.price) {
  169. [self.edit_status, self.tmp_price] = [false, options.price];
  170. self.calcPrice();
  171. }
  172. self.$showLoading({text: '加载中'});
  173. self.$request({
  174. url: self.$api.scan_code_pay.index
  175. }).then(info => {
  176. self.$hideLoading();
  177. if (info.code === 0) {
  178. [
  179. self.activity,
  180. self.goods,
  181. self.integral,
  182. self.setting
  183. ] = [
  184. info.data.activity,
  185. info.data.goods,
  186. info.data.integral,
  187. info.data.setting
  188. ];
  189. }
  190. }).catch(info => {
  191. self.$hideLoading();
  192. })
  193. },
  194. methods: {
  195. openPriceModel() {
  196. if (!this.edit_status) return;
  197. this.price_modal = true;
  198. },
  199. closePriceModel() {
  200. this.price_modal = false;
  201. },
  202. setTempInput: function (e) {
  203. this.tmp_price = e.detail.value;
  204. },
  205. //总价
  206. calcPrice: function () {
  207. const self = this;
  208. self.price_modal = false;
  209. self.$showLoading({text: '加载中'});
  210. self.$request({
  211. url: self.$api.scan_code_pay.preview,
  212. data: {
  213. price: self.tmp_price,
  214. coupon_id: self.list.coupon_id,
  215. use_integral: self.list.use_integral,
  216. },
  217. method: 'POST',
  218. }).then(info => {
  219. self.$hideLoading();
  220. if (info.code === 0) {
  221. [self.list, self.tmp_price] = [info.data, info.data.price];
  222. } else {
  223. uni.showToast({icon: 'none', title: info.msg});
  224. }
  225. }).catch(info => {
  226. self.$hideLoading();
  227. })
  228. },
  229. //UseIntegral
  230. handleUseIntegral() {
  231. const self = this;
  232. let list = self.list;
  233. list.use_integral = list.use_integral == 1 ? 0 : 1;
  234. self.calcPrice();
  235. },
  236. //Remark
  237. bindTextBlur: function (e) {
  238. this.remark = e.detail.value;
  239. },
  240. //Integral
  241. getIntegralInfo: function (e) {
  242. let content = '';
  243. this.list.integral_explain.map(v => {
  244. content += '消费满' + v.consume_money + '元,';
  245. content += '积分最多可抵' + v.integral_deduction + '元';
  246. content += '\r\n';
  247. });
  248. uni.showModal({
  249. title: '积分抵扣说明',
  250. content: content.trim(),
  251. showCancel: false
  252. })
  253. },
  254. //navigate
  255. setCoupon: function (e) {
  256. this.clear = false;
  257. uni.navigateTo({
  258. url: '/plugins/scan_code/index/coupon?price=' + this.list.price + '&coupon_id=' + this.list.coupon_id,
  259. });
  260. },
  261. submit: function (e) {
  262. const self = this;
  263. if (!self.list.price) return
  264. self.$showLoading({text: '正在提交'});
  265. self.$request({
  266. url: self.$api.scan_code_pay.submit,
  267. method: 'post',
  268. data: {
  269. price: self.list.price,
  270. coupon_id: self.list.coupon_id,
  271. use_integral: self.list.use_integral,
  272. remark: self.remark,
  273. },
  274. }).then(e => {
  275. self.$hideLoading();
  276. if (e.code === 0) {
  277. self.$payment.pay(e.data.pay_id).then(payMsg => {
  278. // 支付成功
  279. uni.showModal({
  280. title: '提示',
  281. content: "支付成功",
  282. showCancel: false,
  283. success() {
  284. uni.navigateTo({
  285. url: '/pages/order-submit/pay-result?payment_order_union_id=' + e.data.pay_id + '&plugin=scan_code_pay'
  286. })
  287. self.clear = true;
  288. },
  289. });
  290. }).catch(payMsg => {
  291. // 支付失败
  292. self.$showLoading({text: '取消中'});
  293. self.$request({
  294. url: self.$api.scan_code_pay.cancel,
  295. data: {
  296. pay_id: e.data.pay_id,
  297. },
  298. method: 'POST',
  299. }).then(info => {
  300. self.$hideLoading();
  301. }).catch(info => {
  302. self.$hideLoading();
  303. uni.showModal({title: '提示', content: info.msg});
  304. })
  305. });
  306. } else {
  307. uni.showModal({title: '提示', content: info.msg});
  308. }
  309. }).catch(e => {
  310. self.$hideLoading();
  311. });
  312. },
  313. }
  314. }
  315. </script>
  316. <style scoped lang="scss">
  317. .red {
  318. color: #ff4544;
  319. }
  320. .gray {
  321. color: #999999;
  322. }
  323. .scan-head {
  324. margin: #{20rpx} #{24rpx} 0 #{24rpx};
  325. background: #fff;
  326. border-radius: #{16rpx};
  327. padding: #{48rpx} #{40rpx} 0 #{40rpx};
  328. font-size: #{28rpx};
  329. color: #353535;
  330. .scan-line {
  331. height: 1px;
  332. margin-top: #{38rpx};
  333. background: #e2e2e2;
  334. }
  335. .scan-price {
  336. margin-top: #{32rpx};
  337. .order-key {
  338. font-size: #{50rpx};
  339. }
  340. .order-value {
  341. font-size: #{80rpx};
  342. padding-left: #{28rpx};
  343. height: #{98rpx};
  344. }
  345. }
  346. }
  347. .scan-offer {
  348. color: #666666;
  349. font-size: #{28rpx};
  350. margin-top: #{40rpx};
  351. .coupon-right {
  352. padding-right: #{12rpx};
  353. }
  354. .icon-right {
  355. background-size: 100% auto;
  356. background-repeat: no-repeat;
  357. background-image: url("../../../static/image/icon/arrow-right.png");
  358. width: #{12rpx};
  359. height: #{22rpx};
  360. }
  361. }
  362. .scan-integral-icon {
  363. height: #{36rpx};
  364. width: #{36rpx};
  365. background-image: url("../../../static/image/icon/warning.png");
  366. background-repeat: no-repeat;
  367. background-size: 100% auto;
  368. margin-left: #{20rpx};
  369. }
  370. .scan-integral-switch {
  371. width: #{44rpx};
  372. height: #{44rpx};
  373. background-size: 100% auto;
  374. background-repeat: no-repeat;
  375. float: left;
  376. }
  377. .scan-integral-switch.check {
  378. margin-left: #{5rpx};
  379. background-image: url("../../../static/image/icon/icon-checkbox-checked-a.png");
  380. }
  381. .scan-integral-switch.uncheck {
  382. margin-left: #{5rpx};
  383. background-image: url("../../../static/image/icon/icon-uncheck.png");
  384. }
  385. .scan-input {
  386. width: 100%;
  387. font-size: #{28rpx};
  388. color: #666;
  389. }
  390. .scan-remark {
  391. height: #{106rpx};
  392. .key {
  393. margin-left: auto;
  394. color: #353535;
  395. font-size: #{28rpx};
  396. }
  397. .value {
  398. margin-left: #{10rpx};
  399. color: #ff4544;
  400. font-size: #{36rpx};
  401. }
  402. }
  403. .scan-end {
  404. color: #666;
  405. background: #fff;
  406. margin: 0 #{24rpx};
  407. font-size: #{28rpx};
  408. border-radius: #{16rpx};
  409. padding: #{40rpx};
  410. text {
  411. word-break: break-all;
  412. text-align: justify;
  413. }
  414. }
  415. .scan-end > view {
  416. margin-bottom: #{12rpx};
  417. }
  418. .scan-end .icon {
  419. height: #{26rpx};
  420. width: #{8rpx};
  421. border-radius: #{4rpx};
  422. background: #ff4544;
  423. margin-right: #{16rpx};
  424. }
  425. .scan-btn {
  426. margin: #{40rpx} auto;
  427. }
  428. .scan-modal {
  429. position: fixed;
  430. left: 0;
  431. top: 0;
  432. width: 100%;
  433. height: 100%;
  434. z-index: 2001;
  435. transition: 200ms;
  436. }
  437. .scan-modal.show {
  438. visibility: visible;
  439. opacity: 1;
  440. }
  441. .scan-modal.bt {
  442. -webkit-animation-name: fadeIn; /*动画名称*/
  443. -webkit-animation-duration: 0.25s; /*动画持续时间*/
  444. -webkit-animation-iteration-count: 1; /*动画次数*/
  445. -webkit-animation-delay: 0s; /*延迟时间*/
  446. }
  447. .scan-modal .scan-modal-bg {
  448. background: rgba(0, 0, 0, 0.8);
  449. position: fixed;
  450. left: 0;
  451. top: 0;
  452. width: 100%;
  453. height: 100%;
  454. z-index: 1;
  455. }
  456. .scan-modal .scan-modal-pic {
  457. position: fixed;
  458. left: 0;
  459. top: #{188rpx};
  460. width: 100%;
  461. height: 100%;
  462. z-index: 1;
  463. }
  464. .scan-modal .scan-modal-close image {
  465. width: #{50rpx};
  466. height: #{50rpx};
  467. margin-top: #{50rpx};
  468. }
  469. .scan-modal .info-model {
  470. height: #{360rpx};
  471. width: #{620rpx};
  472. background: #fff;
  473. border-radius: #{16rpx};
  474. }
  475. .scan-modal .order-title {
  476. margin: #{48rpx} 0
  477. }
  478. .scan-modal .place {
  479. color: #cdcdcd
  480. }
  481. .scan-modal .info-box {
  482. height: #{88rpx};
  483. width: #{400rpx};
  484. margin-bottom: #{48rpx};
  485. border-radius: #{8rpx};
  486. padding: 0 #{24rpx};
  487. border: 1px solid #e2e2e2;
  488. }
  489. .scan-modal .info-input {
  490. font-size: #{32rpx};
  491. color: #353535;
  492. }
  493. .scan-modal .info-line {
  494. height: #{32rpx} !important;
  495. width: 1px !important;
  496. background: #e2e2e2;
  497. }
  498. .scan-modal .info-end {
  499. color: #666666;
  500. height: #{88rpx};
  501. font-size: #{32rpx};
  502. border-top: #{1rpx} solid #e2e2e2;
  503. width: 100%;
  504. }
  505. .scan-modal .info-end view {
  506. height: 100%;
  507. width: 100%;
  508. }
  509. </style>