affirmOrder.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. <template>
  2. <view class="container">
  3. <!-- 导航栏图片区域 -->
  4. <view class="header">
  5. <img src="https://chtech.ncjti.edu.cn/hotelReservation/image/18.png" />
  6. <!-- 标题区域 -->
  7. <view class="header_title" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }">{{ hotelName }}</view>
  8. <!-- 返回图标区域 -->
  9. <view class="header_icon" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }" @click="handleBack">
  10. <img src="../../static/index/left.png" />
  11. </view>
  12. </view>
  13. <view class="body">
  14. <!-- 房间信息区域 -->
  15. <view class="info">
  16. <view class="info_time">
  17. {{ info.startTimeMonth }}月{{ info.startTimeDay }}日
  18. <text class="gap">{{ info.startTimeWeek }}</text>
  19. <view class="time_line"></view>
  20. <view class="time_num">{{ info.nightNum }}晚</view>
  21. <view class="time_line"></view>
  22. <view class="gap">{{ info.endTimeMonth }}月{{ info.endTimeDay }}日</view>
  23. <text>{{ info.endTimeWeek }}</text>
  24. </view>
  25. <view class="info_msg">{{ info.item.hName }}</view>
  26. <view class="info_type">
  27. <view class="type_item">{{ info.hTypeName }}</view>
  28. </view>
  29. <view class="info_tag">
  30. <view class="tag_item">{{ info.item.hAreas }}㎡</view>
  31. <view class="tag_item" v-for="tag in info.item.hConfigList" :key="tag.id">{{ tag.name }}</view>
  32. </view>
  33. </view>
  34. <!-- 入住信息区域 -->
  35. <view class="msg">
  36. <view class="msg_title">入住信息</view>
  37. <view class="msg_box">
  38. <view class="box_key">房间数量</view>
  39. <view class="box_value">{{ roomCount }}间</view>
  40. <view class="box_icon">
  41. <img class="img" src="../../static/index/add.png" @click="handleAdd" />
  42. <img class="img2" src="../../static/index/minus.png" @click="handleMinus" />
  43. </view>
  44. </view>
  45. <view class="msg_box">
  46. <view class="box_key">住客姓名</view>
  47. <view class="box_value">
  48. <input disabled type="text" placeholder="请选择住客" v-model="clientName" />
  49. </view>
  50. <view class="box_icon" @click="handleSelectClient">
  51. <img class="img2" src="../../static/index/people.png" />
  52. </view>
  53. </view>
  54. <view class="msg_box">
  55. <view class="box_key">联系电话</view>
  56. <view class="box_value">
  57. <input disabled type="number" maxlength="11" placeholder="请选择联系电话" v-model="clientPhone" />
  58. </view>
  59. </view>
  60. <!-- <view class="msg_box" @click="handleSelectTime">
  61. <view class="box_key">预计到店</view>
  62. <view class="box_value" :class="{ color: !arriveTime }">{{ arriveTime ? arriveTime : '请选择预计到店时间' }}</view>
  63. <view class="box_icon">
  64. <img class="img3" src="../../static/index/right2.png" />
  65. </view>
  66. </view> -->
  67. <uv-datetime-picker
  68. ref="datetimePicker"
  69. v-model="timeValue"
  70. mode="datetime"
  71. :closeOnClickOverlay="false"
  72. confirmColor="#096562"
  73. :formatter="formatter"
  74. @confirm="confirm"
  75. ></uv-datetime-picker>
  76. </view>
  77. <!-- 本单可享区域 -->
  78. <view class="coupon" v-if="couponNum">
  79. <view class="coupon_title">本单可享</view>
  80. <view class="coupon_box">
  81. <view class="box_key">
  82. <img src="../../static/index/coupon.png" />
  83. 优惠券
  84. </view>
  85. <view class="box_value" @click="handleGoPage">
  86. <view class="value_count">{{ couponNum }}张可用</view>
  87. <img src="../../static/index/right2.png" />
  88. </view>
  89. </view>
  90. </view>
  91. <!-- 费用明细区域 -->
  92. <view class="price">
  93. <view class="price_title">费用明细</view>
  94. <view class="price_box">
  95. <view class="box_key">在线支付</view>
  96. <view class="box_value">
  97. {{ roomCount }}间{{ info.nightNum }}晚 共
  98. <text>¥</text>
  99. <span>{{ totalPrice }}</span>
  100. </view>
  101. </view>
  102. </view>
  103. <!-- 房费区域 -->
  104. <view class="all">
  105. <view class="all_title">
  106. <text>房费</text>
  107. <text class="mr_30">¥{{ totalPrice }}</text>
  108. </view>
  109. <view class="all_box">
  110. <view class="box_list">
  111. <view class="list_item" v-for="(item, index) in dayList" :key="index">
  112. {{ item.date }}
  113. <text>{{ item.topinfo }}</text>
  114. </view>
  115. </view>
  116. <view class="box_total">
  117. {{ roomCount }}间 x {{ info.nightNum }}晚
  118. <!-- x ¥{{ info.item.price }} -->
  119. </view>
  120. </view>
  121. </view>
  122. <!-- 优惠区域 -->
  123. <view class="sale" v-if="chooseObj.discountAmount">
  124. <view class="sale_top">
  125. <view class="top_key">优惠</view>
  126. <view class="top_value">- ¥{{ chooseObj.discountAmount }}</view>
  127. </view>
  128. <view class="sale_bottom">
  129. <view class="bottom_key">
  130. <img src="../../static/index/coupon.png" />
  131. {{ chooseObj.typeName }}
  132. </view>
  133. <view class="bottom_value">- ¥{{ chooseObj.discountAmount }}</view>
  134. </view>
  135. </view>
  136. </view>
  137. <!-- 底部提交订单区域 -->
  138. <view class="foot">
  139. <view class="foot_left">
  140. <text>¥</text>
  141. {{ totalPrice }}
  142. </view>
  143. <view class="foot_right" @click="goPagePay">提交订单</view>
  144. </view>
  145. </view>
  146. </template>
  147. <script>
  148. export default {
  149. data() {
  150. return {
  151. info: {},
  152. // 预定房间数量
  153. roomCount: 1,
  154. // 住客姓名
  155. clientName: '',
  156. // 联系电话
  157. clientPhone: '',
  158. // 预计到店时间
  159. arriveTime: '',
  160. // 当前时间
  161. timeValue: Number(new Date()),
  162. // 民宿名称
  163. hotelName: '',
  164. // 状态栏高度
  165. statusBarH: 0,
  166. // 胶囊按钮栏高度
  167. customBarH: 0,
  168. // 优惠券数量
  169. couponNum: 0,
  170. chooseObj: {},
  171. dayList: [],
  172. totalMoney: 0
  173. }
  174. },
  175. created() {
  176. // 获取系统信息
  177. uni.getSystemInfo({
  178. success: (e) => {
  179. // 获取状态栏高度
  180. this.statusBarH = e.statusBarHeight + 10
  181. // // 获取菜单按钮栏高度
  182. let custom = uni.getMenuButtonBoundingClientRect()
  183. this.customBarH = custom.height + 10
  184. }
  185. })
  186. },
  187. onShow() {
  188. this.getCouponNum()
  189. },
  190. onLoad(options) {
  191. this.info = JSON.parse(options.info)
  192. // console.log(this.info)
  193. this.hotelName = this.info.hotelName
  194. this.getDayList()
  195. uni.$on('change', this.change)
  196. uni.$on('choose', this.choose)
  197. },
  198. computed: {
  199. // 总费用
  200. totalPrice() {
  201. // if (this.info.item) {
  202. // return (this.roomCount * this.info.item.price * this.info.nightNum - (this.chooseObj.discountAmount * 1 || 0)).toFixed(2)
  203. // }
  204. if (this.info.item) {
  205. let tem = this.roomCount * this.totalMoney - (this.chooseObj.discountAmount * 1 || 0)
  206. let res = tem > 0 ? tem.toFixed(2) : 0
  207. return res
  208. }
  209. }
  210. },
  211. methods: {
  212. async getDayList() {
  213. const res = await this.$myRequest({
  214. url: '/mhotel/house/price/dailyPrice.action',
  215. data: {
  216. roomId: this.info.item.id,
  217. startTime: this.info.queryStartTime,
  218. endTime: this.info.queryEndTime
  219. }
  220. })
  221. // console.log(res)
  222. if (res.code === 200) {
  223. this.dayList = res.data.list
  224. this.totalMoney = res.data.totalPrice
  225. }
  226. },
  227. async getCouponNum() {
  228. const res = await this.$myRequest({
  229. url: '/mhotel/hcusefulCoupon.action',
  230. data: {
  231. hotelId: this.info.hotelId,
  232. page: 1,
  233. rows: 1,
  234. userId: uni.getStorageSync('userInfo').id
  235. }
  236. })
  237. // console.log(res);
  238. if (res.code === 200) {
  239. this.couponNum = res.page.total
  240. }
  241. },
  242. change(e) {
  243. this.clientName = e.name
  244. this.clientPhone = e.phone
  245. },
  246. choose(e) {
  247. this.chooseObj = e.data
  248. // console.log(this.chooseObj)
  249. },
  250. handleSelectClient() {
  251. uni.navigateTo({
  252. url: '/pages/common/common?type=1'
  253. })
  254. },
  255. confirm(e) {
  256. // console.log(e.value)
  257. let date = new Date(e.value)
  258. let month = date.getMonth() + 1
  259. let day = date.getDate()
  260. let H = date.getHours()
  261. let M = date.getMinutes()
  262. this.arriveTime = `${month}月${day}日${H}:${M}分之前`
  263. },
  264. formatter(type, value) {
  265. if (type === 'year') {
  266. return `${value}年`
  267. }
  268. if (type === 'month') {
  269. return `${value}月`
  270. }
  271. if (type === 'day') {
  272. return `${value}日`
  273. }
  274. return value
  275. },
  276. handleSelectTime() {
  277. this.$refs.datetimePicker.open()
  278. },
  279. handleAdd() {
  280. this.roomCount++
  281. },
  282. handleMinus() {
  283. if (this.roomCount > 1) {
  284. this.roomCount--
  285. } else {
  286. uni.showToast({
  287. title: '至少需要预定1间',
  288. icon: 'none'
  289. })
  290. }
  291. },
  292. // 提交订单按钮回调
  293. async goPagePay() {
  294. const reName = /^[\u4e00-\u9fa5]{2,4}$/
  295. const rePhone = /^[1][3,4,5,7,8,9][0-9]{9}$/
  296. if (this.totalPrice <= 0) {
  297. uni.showToast({
  298. title: '支付金额不能小于等于0',
  299. icon: 'none',
  300. mask: true
  301. })
  302. return
  303. }
  304. if (!this.clientName) {
  305. uni.showToast({
  306. title: '请选择住客',
  307. icon: 'none',
  308. mask: true
  309. })
  310. return
  311. }
  312. if (!reName.test(this.clientName)) {
  313. uni.showToast({
  314. title: '姓名格式有误',
  315. icon: 'none'
  316. })
  317. return
  318. }
  319. if (!this.clientPhone) {
  320. uni.showToast({
  321. title: '请选择联系电话',
  322. icon: 'none',
  323. mask: true
  324. })
  325. return
  326. }
  327. if (!rePhone.test(this.clientPhone)) {
  328. uni.showToast({
  329. title: '电话号码格式有误',
  330. icon: 'none'
  331. })
  332. return
  333. }
  334. const res = await this.$myRequest({
  335. url: '/mhotel/abkcreateOrder.action',
  336. data: {
  337. houseId: this.info.item.id,
  338. startTime: this.info.queryStartTime,
  339. endTime: this.info.queryEndTime,
  340. houseOrderNumber: this.roomCount,
  341. userName: this.clientName,
  342. userPhone: this.clientPhone,
  343. userId: uni.getStorageSync('userInfo').id,
  344. complaintId: this.chooseObj.complaintId || '',
  345. useId: this.chooseObj.id || ''
  346. }
  347. })
  348. // console.log(res)
  349. if (res.code === 200) {
  350. uni.navigateTo({
  351. url: `/pages/pay/pay?id=${res.data}`
  352. })
  353. }
  354. },
  355. handleBack() {
  356. uni.navigateBack(1)
  357. },
  358. handleGoPage() {
  359. let temTotalPrice = (this.roomCount * this.totalMoney).toFixed(2)
  360. uni.navigateTo({
  361. url: `/pages/coupon/coupon?id=${this.info.hotelId}&totalPrice=${temTotalPrice}&complaintId=${this.chooseObj.complaintId}`
  362. })
  363. }
  364. }
  365. }
  366. </script>
  367. <style lang="scss" scoped>
  368. .container {
  369. position: relative;
  370. display: flex;
  371. flex-direction: column;
  372. height: 100vh;
  373. overflow: hidden;
  374. background-color: #ebeced;
  375. .header {
  376. position: relative;
  377. height: 180rpx;
  378. overflow: hidden;
  379. img {
  380. width: 100%;
  381. }
  382. .header_title {
  383. position: absolute;
  384. top: 0;
  385. left: 182rpx;
  386. width: 50%;
  387. color: #fff;
  388. text-align: center;
  389. font-size: 28rpx;
  390. overflow: hidden;
  391. text-overflow: ellipsis;
  392. white-space: nowrap;
  393. }
  394. .header_icon {
  395. position: absolute;
  396. top: 0;
  397. left: 5rpx;
  398. width: 47rpx;
  399. height: 70rpx;
  400. img {
  401. width: 47rpx;
  402. height: 47rpx;
  403. }
  404. }
  405. }
  406. .body {
  407. height: calc(100vh - 306rpx);
  408. overflow-y: auto;
  409. .info {
  410. display: flex;
  411. flex-direction: column;
  412. box-sizing: border-box;
  413. padding: 0 30rpx;
  414. margin: 0 auto;
  415. margin-top: 18rpx;
  416. width: 710rpx;
  417. border-radius: 15rpx;
  418. background-color: #fff;
  419. .info_time {
  420. display: flex;
  421. align-items: center;
  422. margin-top: 20rpx;
  423. font-size: 32rpx;
  424. font-weight: bold;
  425. .time_line {
  426. width: 17rpx;
  427. height: 1rpx;
  428. background-color: #096562;
  429. }
  430. .time_num {
  431. box-sizing: border-box;
  432. padding: 0 15rpx;
  433. height: 46rpx;
  434. line-height: 46rpx;
  435. font-size: 24rpx;
  436. font-weight: 400;
  437. border-radius: 66rpx;
  438. border: 1rpx solid #096562;
  439. background-color: #f0f2f5;
  440. }
  441. .gap {
  442. margin: 0 10rpx;
  443. }
  444. text {
  445. font-size: 24rpx;
  446. font-weight: 400;
  447. }
  448. }
  449. .info_msg {
  450. margin-top: 15rpx;
  451. font-size: 28rpx;
  452. font-weight: bold;
  453. }
  454. .info_type {
  455. display: flex;
  456. flex-wrap: wrap;
  457. margin-top: 15rpx;
  458. .type_item {
  459. box-sizing: border-box;
  460. padding: 0 15rpx;
  461. margin-right: 20rpx;
  462. height: 41rpx;
  463. line-height: 41rpx;
  464. font-size: 24rpx;
  465. color: #fff;
  466. border-radius: 34rpx;
  467. background-color: #096562;
  468. }
  469. }
  470. .info_tag {
  471. display: flex;
  472. flex-wrap: wrap;
  473. margin: 18rpx 0 30rpx;
  474. color: #808080;
  475. font-size: 24rpx;
  476. .tag_item {
  477. margin-right: 20rpx;
  478. }
  479. }
  480. }
  481. .msg {
  482. box-sizing: border-box;
  483. padding-left: 26rpx;
  484. margin: auto;
  485. margin-top: 20rpx;
  486. width: 710rpx;
  487. border-radius: 15rpx;
  488. background-color: #fff;
  489. .msg_title {
  490. height: 87rpx;
  491. line-height: 87rpx;
  492. font-size: 28rpx;
  493. font-weight: bold;
  494. border-bottom: 1rpx solid #e6e6e6;
  495. }
  496. .msg_box {
  497. display: flex;
  498. align-items: center;
  499. height: 97rpx;
  500. font-size: 28rpx;
  501. border-bottom: 1rpx solid #e6e6e6;
  502. .box_key {
  503. width: 120rpx;
  504. color: #808080;
  505. }
  506. .box_value {
  507. margin-left: 30rpx;
  508. flex: 1;
  509. input {
  510. box-sizing: border-box;
  511. padding-right: 30rpx;
  512. width: 100%;
  513. }
  514. }
  515. .color {
  516. color: #808080;
  517. }
  518. .box_icon {
  519. display: flex;
  520. align-items: center;
  521. height: 100%;
  522. .img {
  523. width: 47rpx;
  524. height: 47rpx;
  525. }
  526. .img2 {
  527. margin: 0 30rpx;
  528. width: 37rpx;
  529. height: 37rpx;
  530. }
  531. .img3 {
  532. margin: 0 30rpx;
  533. width: 40rpx;
  534. height: 40rpx;
  535. }
  536. }
  537. }
  538. }
  539. .coupon {
  540. box-sizing: border-box;
  541. padding-left: 26rpx;
  542. margin: 20rpx auto 0;
  543. width: 710rpx;
  544. height: 197rpx;
  545. border-radius: 15rpx;
  546. background-color: #fff;
  547. .coupon_title {
  548. line-height: 92rpx;
  549. font-size: 28rpx;
  550. font-weight: bold;
  551. border-bottom: 1rpx solid #e6e6e6;
  552. }
  553. .coupon_box {
  554. display: flex;
  555. align-items: center;
  556. justify-content: space-between;
  557. height: 105rpx;
  558. .box_key {
  559. display: flex;
  560. align-items: center;
  561. font-size: 28rpx;
  562. img {
  563. margin-right: 10rpx;
  564. width: 40rpx;
  565. height: 40rpx;
  566. }
  567. }
  568. .box_value {
  569. display: flex;
  570. align-items: center;
  571. .value_count {
  572. display: flex;
  573. justify-content: center;
  574. align-items: center;
  575. width: 105rpx;
  576. height: 45rpx;
  577. color: #fff;
  578. font-size: 24rpx;
  579. border-radius: 7rpx;
  580. background-color: #ff5733;
  581. }
  582. img {
  583. margin-right: 17rpx;
  584. width: 40rpx;
  585. height: 40rpx;
  586. }
  587. }
  588. }
  589. }
  590. .price {
  591. box-sizing: border-box;
  592. padding-left: 26rpx;
  593. margin: 20rpx auto;
  594. width: 710rpx;
  595. height: 197rpx;
  596. border-radius: 15rpx;
  597. background-color: #fff;
  598. .price_title {
  599. line-height: 92rpx;
  600. font-size: 28rpx;
  601. font-weight: bold;
  602. border-bottom: 1rpx solid #e6e6e6;
  603. }
  604. .price_box {
  605. display: flex;
  606. justify-content: space-between;
  607. align-items: center;
  608. height: 92rpx;
  609. font-size: 28rpx;
  610. .box_key {
  611. color: #808080;
  612. }
  613. .box_value {
  614. display: flex;
  615. align-items: center;
  616. text {
  617. color: #ff5733;
  618. font-size: 24rpx;
  619. }
  620. span {
  621. margin-right: 30rpx;
  622. color: #ff5733;
  623. }
  624. }
  625. }
  626. }
  627. .all {
  628. box-sizing: border-box;
  629. padding-left: 26rpx;
  630. margin: 0 auto 20rpx;
  631. width: 710rpx;
  632. border-radius: 15rpx;
  633. background-color: #fff;
  634. .all_title {
  635. display: flex;
  636. height: 92rpx;
  637. justify-content: space-between;
  638. align-items: center;
  639. font-size: 28rpx;
  640. font-weight: bold;
  641. border-bottom: 1rpx solid #e6e6e6;
  642. .mr_30 {
  643. margin-right: 30rpx;
  644. }
  645. }
  646. .all_box {
  647. box-sizing: border-box;
  648. padding-right: 26rpx;
  649. display: flex;
  650. justify-content: space-between;
  651. font-size: 28rpx;
  652. .box_list {
  653. margin-bottom: 28rpx;
  654. color: #808080;
  655. .list_item {
  656. margin-top: 30rpx;
  657. text {
  658. margin-left: 120rpx;
  659. }
  660. }
  661. }
  662. .box_total {
  663. display: flex;
  664. justify-content: center;
  665. align-items: center;
  666. }
  667. }
  668. }
  669. .sale {
  670. margin: 0 auto 20rpx;
  671. box-sizing: border-box;
  672. padding: 0 30rpx;
  673. width: 710rpx;
  674. height: 209rpx;
  675. border-radius: 15rpx;
  676. background-color: #fff;
  677. .sale_top {
  678. display: flex;
  679. align-items: center;
  680. justify-content: space-between;
  681. height: 92rpx;
  682. font-size: 28rpx;
  683. font-weight: bold;
  684. .top_key {
  685. }
  686. .top_value {
  687. color: #ff5733;
  688. }
  689. }
  690. .sale_bottom {
  691. display: flex;
  692. align-items: center;
  693. justify-content: space-between;
  694. box-sizing: border-box;
  695. padding: 0 26rpx;
  696. width: 650rpx;
  697. height: 80rpx;
  698. font-size: 24rpx;
  699. border-radius: 7rpx;
  700. background-color: #f2f2f2;
  701. .bottom_key {
  702. display: flex;
  703. align-items: center;
  704. img {
  705. margin-right: 10rpx;
  706. width: 34rpx;
  707. height: 34rpx;
  708. }
  709. }
  710. .bottom_value {
  711. }
  712. }
  713. }
  714. }
  715. .foot {
  716. position: absolute;
  717. left: 0;
  718. right: 0;
  719. bottom: 0;
  720. padding: 0 20rpx;
  721. display: flex;
  722. justify-content: space-between;
  723. align-items: center;
  724. height: 126rpx;
  725. background-color: #fff;
  726. .foot_left {
  727. margin-top: -10rpx;
  728. font-size: 40rpx;
  729. color: #ff5733;
  730. text {
  731. font-size: 24rpx;
  732. }
  733. }
  734. .foot_right {
  735. margin-top: -10rpx;
  736. display: flex;
  737. justify-content: center;
  738. align-items: center;
  739. width: 238rpx;
  740. height: 80rpx;
  741. color: #fff;
  742. font-size: 32rpx;
  743. border-radius: 64rpx;
  744. background-color: #096562;
  745. }
  746. }
  747. }
  748. </style>