confirmMixin.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. import QueryPos from './QueryPos'
  2. import ReadValueCard from './ReadValueCard'
  3. import Collapse from '@/components/Collapse'
  4. import { payRefresh } from '@/api/pay'
  5. import handlePay, { getPayType } from '../common/handlePay'
  6. import { debounce } from 'throttle-debounce'
  7. import { checkWayList } from '@/assets/staticData'
  8. import { createValueCardOrder } from '@/api/valueCard'
  9. import { createOrder, getSingleOrder } from '@/api/order'
  10. import { EventBus } from '@/utils/eventBus'
  11. export default {
  12. props: {
  13. tickets: {
  14. type: Array,
  15. default: () => []
  16. },
  17. orderItems: {
  18. type: Array,
  19. default: () => []
  20. },
  21. createOrderRemark: {
  22. type: String,
  23. default: ''
  24. },
  25. orderPrice: {
  26. type: Number,
  27. default: 0
  28. },
  29. formData: {
  30. type: Object,
  31. default: () => { }
  32. },
  33. payChannel: {
  34. type: String,
  35. default: ''
  36. },
  37. totalCount: {
  38. type: Number,
  39. default: 0
  40. },
  41. currentTicket: {
  42. type: Object,
  43. default: () => null
  44. }
  45. },
  46. components: {
  47. Collapse,
  48. ReadValueCard,
  49. QueryPos
  50. },
  51. computed: {
  52. payType () {
  53. return getPayType(this.currentPayChannel)
  54. },
  55. showRefresh () {
  56. return this.payType === 'B_SCAN_C_PAY' && this.submitDisable
  57. },
  58. showPosQrcode () {
  59. // 需要手动扫码的景区
  60. const list = ['东方绿舟', '天津之眼', '绿博园']
  61. if (this.scenicName === '绿博园' && (!this.$localStore.get('posName') || this.$localStore.get('posName') === 'jianhang')) {
  62. return false
  63. }
  64. return list.indexOf(this.scenicName) > -1
  65. },
  66. scenicName () {
  67. return this.$localStore.get('scenicName') || this.$store.state.user.scenicName
  68. },
  69. maxNum () {
  70. return this.$store.state.app.systemConfig?.find(i => i.configKey === 'ticket_checkNum_limit').configValue
  71. },
  72. playDate () {
  73. return this.currentTicket ? this.currentTicket.playDate : ''
  74. }
  75. },
  76. data () {
  77. return {
  78. isPrint: false,
  79. isPrintSmallTicket: false,
  80. submitDisable: false,
  81. visible: false,
  82. active: '',
  83. orderInfo: [],
  84. printArray: [],
  85. isRefresh: false,
  86. countNum: 5,
  87. orderTempInfo: {}, // 临时订单信息,防止重复创建订单
  88. timer: null, // 检查订单是否支付成功计时器
  89. currentPrint: null,
  90. currentPayChannel: '',
  91. payStatus: 0, // 支付状态
  92. createOrderStatus: 0, // 创建订单状态
  93. payCode: '',
  94. payCodeDialogVisible: false
  95. }
  96. },
  97. methods: {
  98. show () {
  99. this.visible = true
  100. this.submitDisable = false
  101. this.payStatus = 0
  102. this.createOrderStatus = 0
  103. this.orderInfo = JSON.parse(JSON.stringify(this.orderItems))
  104. this.currentPayChannel = this.payChannel
  105. this.$nextTick(() => {
  106. this.isPrint = this.formData.checkWay === 3 ? false : (this.$localStore.get('autoPrint') || false)
  107. this.isPrintSmallTicket = this.$localStore.get('autoPrintSmallTicket')
  108. })
  109. },
  110. changePayChannel (n) {
  111. let i = this.payChannelOptions.findIndex(channel => channel === this.currentPayChannel)
  112. let l = this.payChannelOptions.length
  113. let j = (i - n + l) % l
  114. this.currentPayChannel = this.payChannelOptions[j]
  115. },
  116. payRefresh () {
  117. // if (!this.orderTempInfo.extraInfo) return
  118. this.countTimer && clearTimeout(this.countTimer)
  119. this.isRefresh = true
  120. this.countNum = 5
  121. this.countdown()
  122. payRefresh({ type: 'TICKET', id: this.orderTempInfo })
  123. },
  124. countdown () {
  125. this.countTimer = setTimeout(() => {
  126. this.countNum--
  127. this.countdown()
  128. if (this.countNum === 0) {
  129. this.isRefresh = false
  130. }
  131. }, 1000)
  132. },
  133. arrowUp () {
  134. this.changePayChannel(1)
  135. },
  136. arrowDown () {
  137. this.changePayChannel(-1)
  138. },
  139. getCheckWayName (val) {
  140. let a = checkWayList.find(i => i.val === val)
  141. return a && a.name
  142. },
  143. handleClose () {
  144. this.timer && clearTimeout(this.timer)
  145. if (this.submitDisable) {
  146. this.$confirm('支付尚未完成,是否强制关闭?', '提示', {
  147. confirmButtonText: '确认',
  148. cancelButtonText: '取消',
  149. type: 'warning'
  150. }).then(() => {
  151. this.$log.info('支付进程被强制关闭')
  152. this.visible = false
  153. // 结束支付进程
  154. this.killAllPosProcess()
  155. }).catch(() => { })
  156. return
  157. }
  158. this.visible = false
  159. // 结束支付进程
  160. this.killAllPosProcess()
  161. },
  162. // 使用现有pos消费信息进行出票
  163. handleQueryPos (posInfo) {
  164. this.setParams()
  165. this.params.bocTradeNo = JSON.stringify(posInfo)
  166. if (this.$NP.divide(posInfo.amount, 100) !== this.params.price) {
  167. this.$message.error('消费金额与当前出票信息不符。')
  168. return
  169. }
  170. this.createOrder(this.params)
  171. },
  172. submit: debounce(1000, true, function (qrcode, cardInfo) {
  173. console.log(this.payType)
  174. // 西宁景区储值卡支付预留
  175. if (this.payType === 'VALUECARD' && this.scenicName === '西宁景区') {
  176. this.setParams()
  177. this.$refs.readValueCard.show(this.params)
  178. return
  179. }
  180. // POS支付是否使用外部扫码
  181. if (this.payType === 'POS' && this.currentPayChannel === '聚合扫码' && !qrcode && this.showPosQrcode) {
  182. this.$refs.posQrCodeReader.show()
  183. return
  184. }
  185. const scanArr = ['瑞通储值卡']
  186. // 是否使用外部扫码
  187. if ((scanArr.indexOf(this.currentPayChannel) > -1 || this.payType === 'B_SCAN_C_PAY') && !qrcode) {
  188. if (this.submitDisable) return
  189. this.setParams()
  190. this.submitDisable = true
  191. createOrder(this.params).then(res => {
  192. this.$log.warn(this.pageName + '下单成功')
  193. this.createOrderStatus = 1
  194. this.orderTempInfo = res.data.order || {}
  195. this.payCodeDialogVisible = true
  196. // this.$refs.XSCQrCodeReader.show(this.tickets, this.currentPayChannel)
  197. this.submitDisable = false
  198. })
  199. .catch(e => {
  200. this.submitDisable = false
  201. })
  202. return
  203. }
  204. // 储值卡支付
  205. if (this.currentPayChannel === '储值卡支付' && !cardInfo) {
  206. this.$refs.ValueCardInput.show(this.tickets, this.currentPayChannel)
  207. return
  208. }
  209. // 防止重复提交
  210. if (this.submitDisable) return
  211. this.submitDisable = true
  212. // 支付已成功只提交订单
  213. if (this.payStatus === 1) {
  214. this.createOrder(this.params)
  215. return
  216. }
  217. // 设置参数
  218. this.setParams()
  219. if (typeof this.params.guestId === 'string') {
  220. this.params.guideName = this.params.guestId
  221. this.params.guestId = null
  222. }
  223. this.params.qrCode = qrcode
  224. this.params.discount = cardInfo ? cardInfo.discount : ''
  225. this.params.password = cardInfo ? cardInfo.password : ''
  226. this.params.memberSystemId = cardInfo ? cardInfo.memberSystemId : ''
  227. this.$log.warn(this.pageName + '支付下单')
  228. this.createOrder(this.params)
  229. }),
  230. handleValueCardPay (cardInfo) {
  231. console.log('储值卡信息', cardInfo)
  232. this.$log.info('储值卡信息', JSON.stringify(cardInfo))
  233. createValueCardOrder({
  234. cardNo: cardInfo.cardCode,
  235. cardVendor: 'CHANGYI',
  236. order: this.params
  237. }).then(res => {
  238. this.handleCreateSuccess(this.params, res)
  239. })
  240. },
  241. submitOnlinePay () {
  242. if (!this.payCode) {
  243. this.$message.error('请输入支付码')
  244. return
  245. }
  246. this.payCodeDialogVisible = false
  247. this.submit(this.payCode)
  248. // this.createOrder(this.params, true)
  249. },
  250. cancelOnlinePay () {
  251. this.payCodeDialogVisible = false
  252. this.payCode = ''
  253. },
  254. createOrder (params, isOnlinePay = false) {
  255. // if (this.payType === 'B_SCAN_C_PAY' && !isOnlinePay) {
  256. // this.payCodeDialogVisible = true
  257. // return
  258. // }
  259. this.submitDisable = true
  260. params.tickets.forEach(ticket => {
  261. if (params.checkWay !== 5) {
  262. ticket.ticketNo = ''
  263. ticket.isStorage = 0
  264. } else {
  265. ticket.isStorage = 1 // 预印票
  266. }
  267. ticket.face = {
  268. faceImg: ticket.face
  269. }
  270. })
  271. params.discountDescription = params.tickets.map((item) => item.discountDescription).filter(i => i).join(',')
  272. params.createOrderRemark = this.createOrderRemark
  273. this.tickets = params.tickets
  274. // debugger;
  275. if (this.createOrderStatus === 1) {
  276. handlePay(this.params, this.orderTempInfo, this, () => { })
  277. if (this.payStatus !== 1) {
  278. this.getSingleOrder(this.orderTempInfo, params)
  279. }
  280. } else {
  281. createOrder(params).then(res => {
  282. const order = res.data.order
  283. this.$log.warn(`下单成功,订单号ID:${order.id}`)
  284. this.createOrderStatus = 1
  285. this.orderTempInfo = order
  286. handlePay(this.params, order, this, () => { })
  287. if (this.payStatus !== 1) {
  288. this.getSingleOrder(order, params)
  289. }
  290. EventBus.$emit('orderCreated', order)
  291. }).catch(e => {
  292. this.submitDisable = false
  293. })
  294. }
  295. },
  296. getSingleOrder (order, params) {
  297. const orderId = order?.id
  298. if (!orderId) return
  299. this.timer && clearTimeout(this.timer)
  300. getSingleOrder(orderId).then(res => {
  301. if (res.data?.payStatus === 'PAYED') {
  302. this.$log.warn(`支付成功,订单号:${res.data.orderNo}`)
  303. this.submitDisable = false
  304. this.handleCreateSuccess(params, res.data)
  305. } else if (res.data?.payStatus === 'CLOSED') {
  306. this.$message.error('交易失败,订单关闭,请重新创建订单')
  307. this.submitDisable = false
  308. this.visible = false
  309. } else {
  310. this.timer = setTimeout(() => {
  311. this.getSingleOrder(order, params)
  312. }, 2000)
  313. }
  314. })
  315. },
  316. handleCreateSuccess (params, order) {
  317. this.$message.success('出票成功')
  318. this.submitDisable = false
  319. // 获取订单详情
  320. // 自动打印
  321. getSingleOrder(order?.id).then(async order => {
  322. this.isPrintSmallTicket && this.$printSmallTicket(order)
  323. const order2 = JSON.parse(JSON.stringify(order))
  324. // 是否判断票种上的打印属性
  325. const projectName = process.env.VUE_APP_PROJECT
  326. // 宏村和demo不判断
  327. if (!['huihuang', 'demo'].includes(projectName)) {
  328. order2.tickets = order2.tickets.filter(v => v.whetherCanPrint)
  329. }
  330. if (!order2.tickets.length) return
  331. if (this.$router.currentRoute.name === 'preOrder' && ['huihuang'].includes(projectName)) {
  332. let price = 0
  333. let checkNum = 0
  334. let personNumber = 0
  335. order2.tickets.forEach(v => {
  336. price = this.$NP.plus(price, v.price)
  337. checkNum = this.$NP.plus(checkNum, v.checkNum)
  338. personNumber = this.$NP.plus(personNumber, v.personNumber)
  339. })
  340. order2.tickets[0].price = price
  341. order2.tickets[0].checkNum = checkNum
  342. order2.tickets[0].personNumber = personNumber
  343. order2.tickets.length = 1
  344. }
  345. let union_invoice_url = this.$localStore.get('union_invoice_url') || ''
  346. if (union_invoice_url) {
  347. order2.tickets.forEach(v => {
  348. v.allInvoiceQrcode = union_invoice_url
  349. })
  350. }
  351. this.isPrint && this.$print(order2)
  352. })
  353. // 关闭弹窗
  354. this.handleClose()
  355. this.$emit('complete')
  356. this.createSuccessCallback && this.createSuccessCallback()
  357. },
  358. beforeDestroy () {
  359. this.killAllPosProcess()
  360. this.payCode = ''
  361. },
  362. handlePayCodeInput (e) {
  363. this.timer && clearTimeout(this.timer)
  364. this.timer = setTimeout(() => {
  365. if (this.payCode.length > 10) {
  366. this.submitOnlinePay()
  367. }
  368. }, 200)
  369. }
  370. },
  371. watch: {
  372. payCode (val) {
  373. if (val) {
  374. this.handlePayCodeInput()
  375. }
  376. },
  377. payCodeDialogVisible (val) {
  378. if (val) {
  379. this.$nextTick(() => {
  380. this.$refs.payCodeInputRef?.focus()
  381. })
  382. }
  383. }
  384. }
  385. }