trade-detail.tsx 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. import ColHeader from '@/components/col-header'
  2. import { Button, Cell, CellGroup, Col, Image, Popup, Row } from 'vant'
  3. import { defineComponent } from 'vue'
  4. import styles from './trade-detail.module.less'
  5. import { goodsType } from '@/constant'
  6. import iconTeacher from '@common/images/icon_teacher.png'
  7. import request from '@/helpers/request'
  8. import Payment from '../order-detail/payment'
  9. import { orderStatus } from '../order-detail/orderStatus'
  10. import { state } from '@/state'
  11. export const getAssetsHomeFile = (fileName: string) => {
  12. const path = `./images/${fileName}`
  13. const modules = import.meta.globEager('./images/*')
  14. return modules[path].default
  15. }
  16. // WAIT_PAY 待支付 PAYING 支付中 PAID 已付款 CLOSE 已关闭 FAIL 支付失败
  17. type orderType = 'WAIT_PAY' | 'PAYING' | 'PAID' | 'CLOSE' | 'FAIL'
  18. export default defineComponent({
  19. name: 'tradeDetail',
  20. data() {
  21. const query = this.$route.query
  22. return {
  23. type: (query.type as string) || 'ING',
  24. path: query.path, // 来源
  25. orderNo: query.orderNo || '',
  26. paymentStatus: false,
  27. order: {
  28. ING: {
  29. img: getAssetsHomeFile('icon_paying.png'),
  30. background: '#FF802C',
  31. title: '支付中'
  32. },
  33. SUCCESS: {
  34. img: getAssetsHomeFile('icon_success.png'),
  35. background:
  36. state.projectType === 'tenant' ? '#FF5461' : 'var(--van-primary)',
  37. title: '支付成功'
  38. },
  39. FAILED: {
  40. img: getAssetsHomeFile('icon_close.png'),
  41. background: '#BDBDBD',
  42. title: '支付失败'
  43. },
  44. CLOSE: {
  45. img: getAssetsHomeFile('icon_close.png'),
  46. background: '#BDBDBD',
  47. title: '订单关闭'
  48. }
  49. },
  50. result: {} as any,
  51. loading: true,
  52. timerOut: null as any,
  53. timer: 3
  54. }
  55. },
  56. computed: {
  57. orderDetailList() {
  58. const result: any = this.result
  59. const orderDetailList = result.orderDetailList || []
  60. orderDetailList.forEach((item: any) => {
  61. let tempPrice = item?.expectPrice || item.actualPrice
  62. if (item?.couponAmount) {
  63. tempPrice = Number((tempPrice / item.goodNum).toFixed(2))
  64. } else {
  65. tempPrice = Number(tempPrice / item.goodNum).toFixed(2)
  66. }
  67. item.showPrice = tempPrice || 0
  68. })
  69. return orderDetailList || []
  70. }
  71. },
  72. async mounted() {
  73. setTimeout(async () => {
  74. this.loading = true
  75. this.orderNo && (await this.getOrder())
  76. this.loading = false
  77. this.type === 'ING' && this.path !== 'tradeRecord' && this.interval()
  78. }, 0)
  79. },
  80. unmounted() {
  81. clearInterval(this.timerOut)
  82. },
  83. methods: {
  84. onRePay() {
  85. orderStatus.orderInfo = {
  86. orderNo: this.result.orderNo,
  87. actualPrice: this.result.actualPrice,
  88. payStatus: true
  89. }
  90. this.paymentStatus = true
  91. this.interval()
  92. },
  93. interval() {
  94. let countTime = 0
  95. this.timerOut = setInterval(async () => {
  96. countTime === 25 && clearInterval(this.timerOut)
  97. await this.getOrder(true)
  98. countTime++
  99. }, 5000)
  100. },
  101. async getOrder(status?: true) {
  102. try {
  103. const urlFix =
  104. state.platformType === 'TEACHER' ? '/api-teacher' : '/api-student'
  105. const res = await request.get(
  106. `${urlFix}/open/userOrder/detailByOrderNo/${this.orderNo}`,
  107. {
  108. hideLoading: status
  109. }
  110. )
  111. this.result = res.data
  112. // WAIT_PAY 待支付 PAYING 支付中 PAID 已付款 CLOSE 已关闭 FAIL 支付失败
  113. this.type = this.formatType(this.result.status)
  114. this.type !== 'ING' && clearInterval(this.timerOut)
  115. } catch {}
  116. },
  117. formatType(type: orderType) {
  118. let str = 'PAYING'
  119. switch (type) {
  120. case 'WAIT_PAY':
  121. case 'PAYING':
  122. str = 'ING'
  123. break
  124. case 'PAID':
  125. str = 'SUCCESS'
  126. break
  127. case 'CLOSE':
  128. str = 'CLOSE'
  129. break
  130. case 'FAIL':
  131. str = 'FAILED'
  132. break
  133. default:
  134. str = 'ING'
  135. break
  136. }
  137. return str
  138. }
  139. },
  140. render() {
  141. return (
  142. <div class={[styles.tradeDetail, styles[this.type]]}>
  143. {!this.loading && (
  144. <>
  145. <ColHeader
  146. background={this.order[this.type].background}
  147. color="#fff"
  148. title="交易详情"
  149. backIconColor="white"
  150. border={false}
  151. />
  152. <div
  153. class={[
  154. styles.orderType,
  155. state.projectType === 'tenant' && styles.orderTypeTenant
  156. ]}
  157. >
  158. <p>
  159. <Image
  160. class={styles.orderImg}
  161. src={this.order[this.type].img}
  162. fit="cover"
  163. />
  164. <span>{this.order[this.type].title}</span>
  165. </p>
  166. </div>
  167. <CellGroup
  168. border={false}
  169. class={[
  170. styles.orderContent,
  171. state.projectType === 'tenant' && styles.orderContentTenant,
  172. 'mb12'
  173. ]}
  174. >
  175. <Cell
  176. v-slots={{
  177. title: () => (
  178. <div class={styles.payPrice}>
  179. <span>¥</span>
  180. {(this as any).$filters.moneyFormat(
  181. this.result.actualPrice
  182. )}
  183. </div>
  184. )
  185. }}
  186. />
  187. {this.orderDetailList.map((item: any) => (
  188. <Cell
  189. border={false}
  190. style={{ paddingBottom: '15px' }}
  191. class={styles.goodsItem}
  192. v-slots={{
  193. icon: () => (
  194. <Image
  195. class={styles.tradeLogo}
  196. src={item.goodUrl || iconTeacher}
  197. fit="contain"
  198. />
  199. ),
  200. title: () => (
  201. <div class={styles.title}>
  202. <span>{item.goodName}</span>
  203. <span class={styles.desc}>
  204. {goodsType[item.goodType]}
  205. </span>
  206. </div>
  207. ),
  208. default: () => (
  209. <div class={styles.content}>
  210. {item.giftFlag ? (
  211. <span class={styles.price}>赠送</span>
  212. ) : (
  213. <span class={styles.price}>
  214. {(this as any).$filters.moneyFormat(item.showPrice)}
  215. </span>
  216. )}
  217. <span class={styles.num}>x{item.goodNum}</span>
  218. </div>
  219. )
  220. }}
  221. />
  222. ))}
  223. {this.result.couponAmount > 0 && (
  224. <Row class={styles.optionRow}>
  225. <Col span="8" offset={1}>
  226. 优惠金额:
  227. </Col>
  228. <Col span="14">
  229. {(this as any).$filters.moneyFormat(
  230. this.result.couponAmount
  231. )}
  232. </Col>
  233. <Col span="1"> </Col>
  234. </Row>
  235. )}
  236. <Row class={styles.optionRow}>
  237. <Col span="8" offset={1}>
  238. 订单号:
  239. </Col>
  240. <Col span="14">{this.result.orderNo}</Col>
  241. <Col span="1"> </Col>
  242. </Row>
  243. <Row class={styles.optionRow}>
  244. <Col span="8" offset={1}>
  245. 交易流水号:
  246. </Col>
  247. <Col span="14">{this.result.transNo}</Col>
  248. <Col span="1"> </Col>
  249. </Row>
  250. <Row class={styles.optionRow}>
  251. <Col span="8" offset={1}>
  252. 创建时间:
  253. </Col>
  254. <Col span="14">{this.result.createTime}</Col>
  255. <Col span="1"> </Col>
  256. </Row>
  257. <Row class={styles.optionRow}>
  258. <Col span="8" offset={1}>
  259. 付款时间:
  260. </Col>
  261. <Col span="14">{this.result.payTime}</Col>
  262. <Col span="1"> </Col>
  263. </Row>
  264. </CellGroup>
  265. {/* {this.type === 'ING' && this.path === 'tradeRecord' && (
  266. <div class="btnGroup">
  267. <Button type="primary" round block onClick={this.onRePay}>
  268. 重新支付
  269. </Button>
  270. </div>
  271. )}
  272. <Popup
  273. show={this.paymentStatus}
  274. closeOnClickOverlay={false}
  275. position="bottom"
  276. round
  277. closeOnPopstate
  278. safeAreaInsetBottom
  279. style={{ minHeight: '30%' }}
  280. >
  281. <Payment
  282. v-model={this.paymentStatus}
  283. orderInfo={orderStatus.orderInfo}
  284. />
  285. </Popup> */}
  286. </>
  287. )}
  288. </div>
  289. )
  290. }
  291. })