index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. <script setup lang="ts">
  2. import { filterDay, timeFormat } from '../utils'
  3. import { OrderStatus, handleCommonOrderStatusText } from '../utils/order-data'
  4. import { StaticUrl } from '@/config'
  5. definePage({
  6. name: 'film-order-detail',
  7. islogin: false,
  8. style: {
  9. navigationBarTitleText: '订单详情',
  10. backgroundColorBottom: '#fff',
  11. },
  12. })
  13. const orderInfo = ref()
  14. const current = ref(0)
  15. const qrRefs = ref<Record<string, any>>({})
  16. function handleCopy(data: string) {
  17. uni.setClipboardData({
  18. data,
  19. success() {
  20. uni.showToast({
  21. title: '复制成功',
  22. icon: 'none',
  23. })
  24. },
  25. })
  26. }
  27. async function downloadImg() {
  28. await nextTick()
  29. const qrInstance = qrRefs.value[current.value]
  30. console.log(qrInstance, current.value)
  31. qrInstance.downloadQrcode()
  32. }
  33. async function getData(orderNo: string) {
  34. const res = await Apis.xsb.orderInfo({ data: { orderNo } })
  35. // const res = await Apis.film.filmOrderDetail({ data: { id } })
  36. orderInfo.value = res.data
  37. if (orderInfo.value.orderMovieItems[0].ticketCode) {
  38. orderInfo.value.codeList = orderInfo.value.orderMovieItems[0].ticketCode?.split(',')
  39. }
  40. else {
  41. orderInfo.value.codeList = []
  42. }
  43. }
  44. function call() {
  45. uni.makePhoneCall({
  46. phoneNumber: orderInfo.value.phone,
  47. })
  48. }
  49. function handleNav() {
  50. uni.openLocation({
  51. latitude: Number(orderInfo.value?.latitude),
  52. longitude: Number(orderInfo.value?.longitude),
  53. name: orderInfo.value.cinemaName,
  54. address: orderInfo.value.cinemaName,
  55. })
  56. }
  57. function changeSwiper(e: any) {
  58. console.log(e.detail.current)
  59. current.value = e.detail.current
  60. }
  61. onLoad((options) => {
  62. getData(options?.orderNo as string)
  63. })
  64. </script>
  65. <template>
  66. <view class="film-order-detail">
  67. <view class="status">
  68. <!-- 支付成功,待出票 -->
  69. {{ orderInfo.hbOrderStatus == 0 ? "待支付" : handleCommonOrderStatusText(orderInfo) }}
  70. </view>
  71. <view class="status-desc">
  72. 如需改签、退款,请直接联系商家
  73. </view>
  74. <!-- 出票状态 -->
  75. <view v-if="orderInfo.hbOrderStatus === OrderStatus.OrderAccepted" class="status-box block">
  76. <view class="icon-box">
  77. <image class="icon" :src="`${StaticUrl}/film-ing-icon.png`" />
  78. <view class="state">
  79. 正在出票
  80. </view>
  81. </view>
  82. <view class="notice">
  83. 预计1-15分钟内出票,若遇到影院系统导致出票失败,系统
  84. 将自动为您退款
  85. </view>
  86. </view>
  87. <!-- 取票码 -->
  88. <view class="ticket-info block">
  89. <view class="ticket-item">
  90. <view class="seat">
  91. 座位:
  92. <view v-for="(item, index) in orderInfo.orderMovieItems" :key="index">
  93. {{ `${item.name} ` }} &nbsp;
  94. </view>
  95. </view>
  96. <!-- <view class="code-box">
  97. <view class="code">
  98. 取票码:{{ item.ticketCode || '暂无' }}
  99. </view>
  100. <image class="icon" :src="`${StaticUrl}/film-copy.png`" @click="handleCopy(item.ticketCode)" />
  101. </view>
  102. <view class="notice">
  103. (前为取票码,后为验票码)
  104. </view> -->
  105. <template v-if="orderInfo.codeList.length > 0">
  106. <swiper class="swiper w-[100%]" :indicator-dots="true" @change="changeSwiper">
  107. <swiper-item
  108. v-for="(item, index) in orderInfo.codeList" :key="index"
  109. class="flex items-center justify-center"
  110. >
  111. <QCode
  112. :ref="(el) => { if (el) qrRefs[index] = el; }" class="my-20rpx" :text="item" :qwidth="90"
  113. :qr-key="`qr${index}`"
  114. />
  115. </swiper-item>
  116. </swiper>
  117. <view class="qrcode-box">
  118. <!-- <view class="qrcode">
  119. </view> -->
  120. <view class="download-btn" @click="downloadImg">
  121. 下载到手机
  122. </view>
  123. </view>
  124. </template>
  125. </view>
  126. <!-- <view class="open-box">
  127. <view class="text">
  128. 展开(共{{ orderInfo.orderMovieItems.length }}个)
  129. </view>
  130. <image class="arrow" :src="`${StaticUrl}/film-black-arrow.png`" mode="scaleToFill" />
  131. </view> -->
  132. </view>
  133. <!-- 退款信息 -->
  134. <view v-if="false" class="refund-info block">
  135. <!-- 全退 -->
  136. <view class="sub-title">
  137. 退款信息
  138. </view>
  139. <!-- 部分退 -->
  140. <view class="flex items-center">
  141. <image class="mr-16rpx h-30rpx w-30rpx" :src="`${StaticUrl}/film-error.png`" mode="scaleToFill" />
  142. <view class="sub-title">
  143. 出票失败已退款:6排6座、6排7座
  144. </view>
  145. </view>
  146. <view class="item">
  147. <view class="label gray">
  148. 退款金额
  149. </view>
  150. <view class="value">
  151. ¥159.9
  152. </view>
  153. </view>
  154. <view class="desc">
  155. 退还金额:159.9元 退还积分:100(已过期10)
  156. </view>
  157. <view class="item">
  158. <view class="label gray">
  159. 退款方式
  160. </view>
  161. <view class="value">
  162. 原支付方式退回
  163. </view>
  164. </view>
  165. <view class="item">
  166. <view class="label gray">
  167. 退款时间
  168. </view>
  169. <view class="value">
  170. 2024-12-13 11:12:30
  171. </view>
  172. </view>
  173. <view class="item">
  174. <view class="label gray">
  175. 预计到帐
  176. </view>
  177. <view class="value">
  178. 1-3个工作日
  179. </view>
  180. </view>
  181. </view>
  182. <!-- 退款原因 -->
  183. <view v-if="false" class="refund-reason block">
  184. <view class="sub-title">
  185. 退款原因
  186. </view>
  187. <view class="reason">
  188. 影院场次临时调整
  189. </view>
  190. </view>
  191. <!-- 影片信息 -->
  192. <view class="movie-info block">
  193. <image class="img" :src="orderInfo.orderImage" />
  194. <view class="title-box">
  195. <view class="title">
  196. {{ orderInfo.movieName }}
  197. </view>
  198. <view class="time-box">
  199. {{ filterDay(timeFormat(orderInfo.session, 'yyyy-MM-dd')) == '今天' ? (`今天${timeFormat(orderInfo.session, 'HH:mm')}`) : timeFormat(orderInfo.session) }} 英语3D
  200. </view>
  201. </view>
  202. </view>
  203. <!-- 影院信息 -->
  204. <view class="film-info block">
  205. <view class="title">
  206. {{ orderInfo.cinemaName }}
  207. </view>
  208. <view class="icon-box">
  209. <view class="icon-item" @click="handleNav">
  210. <image class="icon" :src="`${StaticUrl}/film-nav-icon.png`" />
  211. <view class="text">
  212. 导航
  213. </view>
  214. </view>
  215. <view class="icon-item" @click="call">
  216. <image class="icon" :src="`${StaticUrl}/film-phone.png`" />
  217. <view class="text">
  218. 电话
  219. </view>
  220. </view>
  221. </view>
  222. </view>
  223. <!-- 座位信息 -->
  224. <view class="seat-info block">
  225. <view class="room-num">
  226. {{ orderInfo.hallName }}
  227. </view>
  228. <!-- <view class="area-price">
  229. 普通区¥29.9
  230. </view> -->
  231. <view class="seat-list">
  232. <view v-for="(item, index) in orderInfo.orderMovieItems" :key="index" class="item">
  233. <view class="label">
  234. {{ item.name }}
  235. </view>
  236. <view class="value">
  237. ¥{{ item.price }}
  238. </view>
  239. </view>
  240. </view>
  241. </view>
  242. <!-- 价格信息 -->
  243. <view class="goods-price-box block">
  244. <view class="item">
  245. <view class="label">
  246. 商品金额
  247. </view>
  248. <view class="value">
  249. ¥{{ orderInfo.orderMoney }}
  250. </view>
  251. </view>
  252. <view class="notice">
  253. 座位跨区,按最高价格计算。订单总价=最高座位价格×座位数
  254. </view>
  255. <view class="item">
  256. <view class="label">
  257. 积分({{ orderInfo.offsetPoints || 0 }})
  258. </view>
  259. <view class="value price">
  260. -¥{{ orderInfo.offsetPoints / 100 }}
  261. </view>
  262. </view>
  263. <!-- <view class="item">
  264. <view class="label">
  265. 平台券
  266. </view>
  267. <view class="value price">
  268. -¥14
  269. </view>
  270. </view> -->
  271. <view class="line" />
  272. <view class="total-box">
  273. <view class="reduce">
  274. 总计¥{{ orderInfo.orderMoney }}共减¥{{ orderInfo.offsetPoints / 100 }}
  275. </view>
  276. <view class="text">
  277. 实际付款
  278. </view>
  279. <view class="total">
  280. ¥{{ orderInfo.total }}
  281. </view>
  282. </view>
  283. </view>
  284. <view class="order-info block">
  285. <view class="sub-title">
  286. 订单信息
  287. </view>
  288. <view class="item">
  289. <view class="label gray">
  290. 订单编号
  291. </view>
  292. <view class="value">
  293. {{ orderInfo.orderNumber }}
  294. <image class="icon" :src="`${StaticUrl}/film-copy.png`" @click="handleCopy(orderInfo.orderNumber)" />
  295. </view>
  296. </view>
  297. <view class="item">
  298. <view class="label gray">
  299. 支付方式
  300. </view>
  301. <view class="value">
  302. 微信支付
  303. </view>
  304. </view>
  305. <view class="item">
  306. <view class="label gray">
  307. 支付时间
  308. </view>
  309. <view class="value">
  310. {{ orderInfo.payTime || '-' }}
  311. </view>
  312. </view>
  313. <view class="item">
  314. <view class="label gray">
  315. 下单时间
  316. </view>
  317. <view class="value">
  318. {{ orderInfo.createTime }}
  319. </view>
  320. </view>
  321. </view>
  322. </view>
  323. </template>
  324. <style lang="scss" scoped>
  325. .film-order-detail{
  326. padding: 20rpx 24rpx 300rpx;
  327. background: #F9F9F9;
  328. .block{
  329. background: #FFFFFF;
  330. border-radius: 16rpx 16rpx 16rpx 16rpx;
  331. padding: 24rpx;
  332. margin-bottom: 20rpx;
  333. }
  334. .sub-title {
  335. font-weight: bold;
  336. font-size: 32rpx;
  337. color: #222222;
  338. }
  339. .item{
  340. display: flex;
  341. justify-content: space-between;
  342. align-items: center;
  343. margin-top: 20rpx;
  344. .label{
  345. font-size: 28rpx;
  346. color: #222222;
  347. }
  348. .label.gray{
  349. color: #AAAAAA;
  350. }
  351. .value{
  352. font-size: 28rpx;
  353. color: #222222;
  354. }
  355. .value.price {
  356. color: #FF4A39;
  357. }
  358. }
  359. .item:first-child {
  360. margin-top: 0 !important;
  361. }
  362. .status{
  363. font-weight: bold;
  364. font-size: 36rpx;
  365. color: #222222;
  366. margin-bottom: 20rpx;
  367. }
  368. .status-desc{
  369. font-size: 28rpx;
  370. color: #AAAAAA;
  371. margin-bottom: 20rpx;
  372. }
  373. .status-box{
  374. .icon-box{
  375. margin-bottom: 20rpx;
  376. display: flex;
  377. flex-direction: column;
  378. align-items: center;
  379. .icon {
  380. width: 80rpx;
  381. height: 80rpx;
  382. margin-bottom: 20rpx;
  383. }
  384. .state{
  385. font-weight: bold;
  386. font-size: 32rpx;
  387. color: #222222;
  388. }
  389. }
  390. .notice{
  391. font-size: 24rpx;
  392. color: #AAAAAA;
  393. line-height: 40rpx;
  394. }
  395. }
  396. .ticket-info{
  397. .seat{
  398. font-weight: bold;
  399. font-size: 28rpx;
  400. color: #222222;
  401. display: flex;
  402. }
  403. .code-box{
  404. display: flex;
  405. align-items: center;
  406. margin-top: 20rpx;
  407. .code{
  408. font-weight: bold;
  409. font-size: 28rpx;
  410. color: #222222;
  411. }
  412. .icon{
  413. width: 30rpx;
  414. height: 30rpx;
  415. margin-left: 20rpx;
  416. }
  417. }
  418. .notice{
  419. font-size: 24rpx;
  420. color: #AAAAAA;
  421. margin-top: 20rpx;
  422. }
  423. .qrcode-box{
  424. display: flex;
  425. flex-direction: column;
  426. align-items: center;
  427. justify-content: center;
  428. margin-top: 24rpx;
  429. .qrcode{
  430. width: 160rpx;
  431. height: 160rpx;
  432. background: #AAAAAA;
  433. border-radius: 16rpx;
  434. }
  435. .download-btn{
  436. width: 180rpx;
  437. height: 44rpx;
  438. line-height: 44rpx;
  439. text-align: center;
  440. background: #9ED605;
  441. border-radius: 26rpx 26rpx 26rpx 26rpx;
  442. font-size: 28rpx;
  443. color: #FFFFFF;
  444. margin-top: 24rpx;
  445. }
  446. }
  447. .open-box{
  448. display: flex;
  449. align-items: center;
  450. .text{
  451. font-size: 24rpx;
  452. color: #222222;
  453. }
  454. .arrow{
  455. width: 32rpx;
  456. height: 32rpx;
  457. transform: rotate(90deg);
  458. }
  459. }
  460. }
  461. .refund-info{
  462. .desc{
  463. font-size: 24rpx;
  464. color: #AAAAAA;
  465. margin-top: 20rpx;
  466. }
  467. }
  468. .refund-reason{
  469. .reason{
  470. font-size: 28rpx;
  471. color: #AAAAAA;
  472. margin-top: 20rpx;
  473. }
  474. }
  475. .movie-info{
  476. display: flex;
  477. align-items: center;
  478. .img{
  479. width: 152rpx;
  480. height: 208rpx;
  481. margin-right: 24rpx;
  482. border-radius: 16rpx;
  483. vertical-align: bottom;
  484. }
  485. .title-box{
  486. display: flex;
  487. flex-direction: column;
  488. justify-content: center;
  489. .title{
  490. font-weight: bold;
  491. font-size: 32rpx;
  492. color: #222222;
  493. margin-bottom: 20rpx;
  494. }
  495. .time-box{
  496. font-size: 24rpx;
  497. color: #AAAAAA;
  498. }
  499. }
  500. }
  501. .film-info{
  502. display: flex;
  503. align-items: center;
  504. justify-content: space-between;
  505. .title{
  506. font-weight: bold;
  507. font-size: 32rpx;
  508. color: #222222;
  509. white-space: nowrap;
  510. overflow: hidden;
  511. text-overflow: ellipsis;
  512. }
  513. .icon-box{
  514. display: flex;
  515. justify-content: space-between;
  516. width: 140rpx;
  517. .icon-item{
  518. display: flex;
  519. flex-direction: column;
  520. align-items: center;
  521. .icon{
  522. width: 40rpx;
  523. height: 40rpx;
  524. margin-bottom: 20rpx;
  525. }
  526. .text{
  527. font-size: 28rpx;
  528. color: #222222;
  529. }
  530. }
  531. }
  532. }
  533. .seat-info{
  534. .room-num{
  535. font-size: 28rpx;
  536. color: #222222;
  537. margin-bottom: 20rpx;
  538. }
  539. .area-price{
  540. font-size: 24rpx;
  541. color: #AAAAAA;
  542. margin: 20rpx 0;
  543. }
  544. .seat-list{
  545. }
  546. }
  547. .goods-price-box{
  548. .notice{
  549. font-size: 24rpx;
  550. color: #AAAAAA;
  551. margin-top: 16rpx;
  552. }
  553. .line{
  554. height: 2rpx;
  555. background: #F0F0F0;
  556. margin-top: 20rpx;
  557. }
  558. .total-box{
  559. display: flex;
  560. justify-content: flex-end;
  561. align-items: center;
  562. margin-top: 30rpx;
  563. .reduce{
  564. font-size: 24rpx;
  565. color: #222222;
  566. }
  567. .text{
  568. font-weight: bold;
  569. font-size: 32rpx;
  570. color: #222222;
  571. margin: 0 12rpx;
  572. }
  573. .total{
  574. font-weight: bold;
  575. font-size: 32rpx;
  576. color: #FF4A39;
  577. }
  578. }
  579. }
  580. .order-info{
  581. .icon{
  582. width: 30rpx;
  583. height: 30rpx;
  584. margin-left: 20rpx;
  585. }
  586. }
  587. }
  588. </style>