pay.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <template>
  2. <view>
  3. <Loading :type="3" :loadStatus="loadStatus" :showText="errorText" />
  4. <zj-page-layout :hasFooter="true" v-if="detail">
  5. <view style="padding: 1rpx 30rpx">
  6. <view class="materials-container card mt30">
  7. <view class="title">
  8. <view class="t1">支付金额</view>
  9. <view class="t2"
  10. >¥<text>{{ detail.totalAmount | priceFilter }}</text></view
  11. >
  12. </view>
  13. <view class="id"><text>订单号:</text>{{ detail.orderId }}</view>
  14. <view class="product">
  15. <view class="it" v-for="(item, index) in detail.workerOrderItems" :key="index">
  16. <view class="name"
  17. >{{ item.goodsName }}<text>×{{ item.num }}{{ item.unit }}</text></view
  18. >
  19. <view class="price">¥{{ item.totalAmount | priceFilter }}</view>
  20. </view>
  21. <view class="total">
  22. <view class="text">合计:</view>
  23. <view class="price">¥{{ detail.totalAmount | priceFilter }}</view>
  24. </view>
  25. </view>
  26. <view class="row"><text>备注:</text>{{ detail.remark }}</view>
  27. <view class="row"><text>操作人:</text>{{ detail.workerName }}</view>
  28. </view>
  29. </view>
  30. <template slot="footer">
  31. <view class="footer-btn-group">
  32. <u-button v-if="detail.ifCancel" text="取消订单" @click="cancelOrder"></u-button>
  33. <!-- <u-button text="扫码支付" type="primary" @click="scanCode"></u-button> -->
  34. <u-button text="线下支付" type="primary" @click="scanCodeXX"></u-button>
  35. </view>
  36. </template>
  37. </zj-page-layout>
  38. <zhifutanchuan
  39. v-if="state > 0"
  40. :detail="detail"
  41. :orderId="orderId"
  42. :state="state"
  43. @scan="scan"
  44. @back="back"
  45. @offTiming="offTiming"
  46. />
  47. </view>
  48. </template>
  49. <script>
  50. import { wxScanCode } from '@/common/utils/util.js'
  51. import zhifutanchuan from '@/components/zhifutanchuan.vue'
  52. export default {
  53. data() {
  54. return {
  55. orderId: null,
  56. refresherTriggered: false,
  57. loadStatus: 0,
  58. errorText: '',
  59. detail: null,
  60. canScanCode: 0,
  61. timeout: null,
  62. timeoutNum: 0,
  63. payType: 1,
  64. state: 0
  65. }
  66. },
  67. components: {
  68. zhifutanchuan
  69. },
  70. onLoad({ handleOrderId }) {
  71. this.orderId = handleOrderId
  72. this.getDetail()
  73. this.crossPage.$on('reScanCode', () => {
  74. this.scanCode()
  75. })
  76. },
  77. onUnload() {
  78. if (this.timeout) {
  79. clearTimeout(this.timeout)
  80. }
  81. },
  82. methods: {
  83. scan() {
  84. this.state = 0
  85. if (this.timeout) {
  86. clearTimeout(this.timeout)
  87. }
  88. this.scanCode()
  89. },
  90. back() {
  91. this.state = 0
  92. if (this.timeout) {
  93. clearTimeout(this.timeout)
  94. }
  95. this.$navToPage(
  96. {
  97. url: `/packageMaterial/pages/index?type=P`
  98. },
  99. 'reLaunch'
  100. )
  101. },
  102. getDetail(cb) {
  103. let url = '/pay/getOrder'
  104. let params = {}
  105. params.orderId = this.orderId
  106. this.$api
  107. .post(url, params)
  108. .then(res => {
  109. this.detail = res.data
  110. this.loadStatus = 0
  111. cb?.()
  112. })
  113. .catch(res => {
  114. this.errorText = res.message
  115. this.loadStatus = 2
  116. })
  117. .finally(res => {
  118. this.refresherTriggered = false
  119. })
  120. },
  121. // 取消订单
  122. cancelOrder() {
  123. this.$modal({
  124. content: '确认取消订单吗?'
  125. })
  126. .then(() => {
  127. this.$api
  128. .post('/pay/cancel', {
  129. orderId: this.orderId
  130. })
  131. .then(res => {
  132. this.$successToast()
  133. this.$navToPage(
  134. {
  135. delta: 1
  136. },
  137. 'navigateBack'
  138. )
  139. })
  140. })
  141. .catch(() => {})
  142. },
  143. // 扫码
  144. async scanCode() {
  145. if (this.canScanCode > 0) return this.$toast(`请等待${this.canScanCode}秒后重试`)
  146. var codeVal = await wxScanCode(['qrCode'])
  147. this.submitData(codeVal)
  148. },
  149. // 下单
  150. submitData(code) {
  151. let url = '/pay/paid'
  152. this.$api
  153. .post(url, {
  154. authCode: code,
  155. orderId: this.orderId,
  156. payType: 'WECHAT'
  157. })
  158. .then(res => {
  159. this.orderId = res.data.orderId
  160. if (res.data.payStatus == 'PAID') {
  161. // 支付成功
  162. this.getDetail(() => {
  163. this.state = 2
  164. })
  165. } else {
  166. // 支付失败
  167. this.getDetail(() => {
  168. this.state = 4
  169. })
  170. }
  171. })
  172. .catch(res => {
  173. // 等待支付
  174. var [USERPAYING, orderId] = res.message.split('|')
  175. if (~USERPAYING.indexOf('USERPAYING') && !!orderId) {
  176. this.orderId = orderId
  177. if (this.state == 0) {
  178. this.state = 1
  179. }
  180. this.getDetail__()
  181. } else {
  182. this.$tips(res.message)
  183. }
  184. })
  185. },
  186. scanCodeXX() {
  187. this.$api
  188. .post('/pay/paid', {
  189. orderId: this.orderId,
  190. payType: 'LINE'
  191. })
  192. .then(res => {
  193. this.orderId = res.data.orderId
  194. if (res.data.payStatus == 'PAID') {
  195. // 支付成功
  196. this.state = 2
  197. } else {
  198. // 支付失败
  199. this.state = 4
  200. }
  201. })
  202. .catch(res => {})
  203. },
  204. offTiming() {
  205. if (this.timeout) {
  206. clearTimeout(this.timeout)
  207. }
  208. },
  209. getDetail__(cb) {
  210. this.$api
  211. .post('/pay/getOrder', {
  212. orderId: this.orderId
  213. })
  214. .then(res => {
  215. this.detail = res.data
  216. if (res.data.payStatus == 'PAID') {
  217. this.state = 2
  218. } else {
  219. this.timeout = setTimeout(() => {
  220. this.getDetail__(cb)
  221. }, 1000)
  222. }
  223. cb?.()
  224. })
  225. .catch(res => {})
  226. .finally(res => {})
  227. },
  228. confirmPay() {
  229. let url = '/pay/paid'
  230. this.$api
  231. .post(url, {
  232. authCode: '',
  233. orderId: this.orderId,
  234. payType: 'LINE'
  235. })
  236. .then(res => {
  237. if (res.data) {
  238. this.$navToPage({
  239. url: `/packageMaterial/pages/newSale/result?handleOrderId=${this.orderId}&result=1`
  240. })
  241. } else {
  242. this.$navToPage({
  243. url: `/packageMaterial/pages/newSale/result?handleOrderId=${this.orderId}&result=0`
  244. })
  245. }
  246. })
  247. }
  248. }
  249. }
  250. </script>
  251. <style lang="scss" scoped>
  252. .card {
  253. @include zj-card;
  254. }
  255. .materials-container {
  256. padding: 30rpx;
  257. .title {
  258. text-align: center;
  259. margin-top: 30rpx;
  260. .t1 {
  261. font-size: 32rpx;
  262. font-weight: 500;
  263. }
  264. .t2 {
  265. font-size: 40rpx;
  266. color: $minor-color;
  267. margin-top: 20rpx;
  268. text {
  269. font-size: 56rpx;
  270. font-weight: 500;
  271. }
  272. }
  273. }
  274. .id {
  275. margin-top: 50rpx;
  276. text {
  277. color: $sec-font;
  278. }
  279. }
  280. .product {
  281. background: #f5f5f5;
  282. border-radius: 12rpx;
  283. padding: 20rpx;
  284. margin-top: 20rpx;
  285. .it {
  286. display: flex;
  287. align-items: flex-end;
  288. margin-bottom: 20rpx;
  289. .name {
  290. flex: 1;
  291. font-size: 28rpx;
  292. font-weight: 500;
  293. text {
  294. color: $sec-font;
  295. margin-left: 12rpx;
  296. font-weight: normal;
  297. }
  298. }
  299. .price {
  300. margin-left: 30rpx;
  301. font-size: 28rpx;
  302. font-weight: 500;
  303. }
  304. }
  305. .total {
  306. display: flex;
  307. align-items: center;
  308. justify-content: flex-end;
  309. margin-top: 30rpx;
  310. .text {
  311. font-size: 28rpx;
  312. color: $sec-font;
  313. }
  314. .price {
  315. font-size: 28rpx;
  316. color: $minor-color;
  317. font-weight: 500;
  318. }
  319. }
  320. }
  321. .row {
  322. margin-top: 20rpx;
  323. line-height: 40rpx;
  324. display: flex;
  325. font-size: 28rpx;
  326. text {
  327. color: $sec-font;
  328. flex-shrink: 0;
  329. line-height: 40rpx;
  330. }
  331. }
  332. }
  333. .pay-container {
  334. padding: 30rpx;
  335. .top {
  336. margin-bottom: 40rpx;
  337. }
  338. .item {
  339. display: flex;
  340. align-items: center;
  341. justify-content: space-between;
  342. margin: 30rpx 0;
  343. .left {
  344. display: flex;
  345. align-items: center;
  346. .iconfont {
  347. font-size: 44rpx;
  348. color: #43c93e;
  349. }
  350. .text {
  351. margin-left: 18rpx;
  352. font-size: 32rpx;
  353. }
  354. }
  355. .right {
  356. .iconfont {
  357. font-size: 40rpx;
  358. color: $sec-font;
  359. &.active {
  360. color: $theme-color;
  361. }
  362. }
  363. }
  364. }
  365. }
  366. </style>