index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. <template>
  2. <div class="hotel">
  3. <div class="formbox">
  4. <div class="tabtit">酒店预约</div>
  5. <div class="formbar">
  6. <div class="li flex_r flex_jb flex_ac">
  7. <div class="flex_r flex_jb flex_ac">
  8. <div class="address" @click="showAddress = !showAddress">
  9. <span class="address_name">{{qda.cityName}}</span>
  10. <span class="iconfont ico">&#xeb6d;</span>
  11. </div>
  12. <div class="addressStr">{{ addrStr }}</div>
  13. </div>
  14. <div @click="locationf" class="location">
  15. <span class="iconfont ico2">&#xe61e;</span>
  16. <div class="it">当前位置</div>
  17. </div>
  18. </div>
  19. <div class="li flex_r flex_jb flex_ac" @click="showCaledar = !showCaledar">
  20. <div class="day">
  21. <div class="ti">入住</div>
  22. <div class="daytxt">{{startStr.month}}月{{startStr.day}}日</div>
  23. </div>
  24. <div class="lab">共 {{dayCount}} 晚</div>
  25. <div class="day">
  26. <div class="ti">离店</div>
  27. <div class="daytxt">{{endStr.month}}月{{endStr.day}}日</div>
  28. </div>
  29. </div>
  30. <div class="li">
  31. <input type="text" v-model="qda.queryText" placeholder="关键字/位置/品牌/酒店名称">
  32. </div>
  33. <div class="li" @click="popupShow = true">
  34. <span v-if="priceRange.length || Leve">{{numinfo}} {{LeveStr}}</span>
  35. <input type="text" placeholder="价格/星级" v-else>
  36. </div>
  37. </div>
  38. </div>
  39. <!-- 日期选择 -->
  40. <date-picker mode="2" ref="dayPicker" :isShow.sync="showCaledar" @callback="pickerChange" />
  41. <!-- 城市选择 -->
  42. <h-address @select="selectaddress" :visible.sync="showAddress" />
  43. <dev class="ni_popup" v-if="popupShow">
  44. <div class="starLevel">
  45. <div class="h_numinfo">每晚均价<span class="msg">{{numinfo}}</span></div>
  46. <div class="sliderBar">
  47. <div class="num flex_r flex_jb"><span>¥0</span><span>¥1500+</span></div>
  48. <div class="sb">
  49. <nni-slider v-model="priceRange" activeColor="#00B76C" max="1500" />
  50. </div>
  51. </div>
  52. <div class="nums">
  53. <div :class="{num_item:true,active:activef(i)}" v-for="(i,s) in priceRs" :key="s" @click="onRange(i)">{{i.txt}}</div>
  54. </div>
  55. <div class="LevelB">
  56. <div class="tit">星级</div>
  57. <div class="ls flex_r flex_jb">
  58. <div :class="{ls_i:true,active:Leve == i.v}" v-for="(i,s) in Levels" :key="s" @click="onLevel(i)">{{i.t}}</div>
  59. </div>
  60. </div>
  61. <div class="pbtn flex_r flex_jse">
  62. <div class="btn" @click="reset">重置</div>
  63. <div class="btn corg" @click="confirm">确认</div>
  64. </div>
  65. </div>
  66. </dev>
  67. <div class="footimg">
  68. <image @click="search" class="btn" src="http://teaclub.oss-cn-chengdu.aliyuncs.com/CloudShop/head_pic/7603bae2564783682b68b025003cae9012f917dcpng" mode="widthFix" />
  69. <image class="img" src="https://teaclub.oss-cn-chengdu.aliyuncs.com/CloudShop/head_pic/0c39d34eef6c35fa1ce63101a6f2ff8.jpg" mode="widthFix" />
  70. </div>
  71. </div>
  72. </template>
  73. <script>
  74. import DatePicker from "@/pagesB/components/date-picker/date-picker.vue";
  75. import hAddress from "@/components/h-address/address.vue";
  76. import nniSlider from "@/pagesB/components/nni-slider/slider.vue";
  77. import QQMapWX from '@/pagesB/static/js/qqmap-wx-jssdk.min.js';
  78. const showmap = new QQMapWX({ key: 'K7LBZ-RE23Q-JEN5D-4ZNEI-MS54Q-BHF6D' });
  79. import { post } from "@/request/api.js";
  80. import { setCache } from "@/utils/storage.js"
  81. export default {
  82. name: "hotel",
  83. props: {},
  84. components: {
  85. DatePicker,
  86. hAddress,
  87. nniSlider
  88. },
  89. data() {
  90. return {
  91. qda: {
  92. cityName: "",
  93. cityCode: "",
  94. checkInDate: "",
  95. checkOutDate: "",
  96. pageIndex: 1,
  97. pageSize: 20,
  98. range: 100
  99. },
  100. showCaledar: false,
  101. showAddress: false,
  102. startDate: '',
  103. endDate: '',
  104. startStr: {},
  105. endStr: {},
  106. dayCount: 1,
  107. addrStr: "",
  108. popupShow: false,
  109. priceRange: [],
  110. numinfo: "",
  111. priceRs: [
  112. { p: [0, 100], txt: "¥100以下" },
  113. { p: [100, 200], txt: "¥100-200" },
  114. { p: [200, 300], txt: "¥200-300" },
  115. { p: [300, 400], txt: "¥300-400" },
  116. { p: [400, 600], txt: "¥400-600" },
  117. { p: [600, 800], txt: "¥600-800" },
  118. { p: [800, 1500], txt: "¥800-1500" },
  119. { p: [1500, 1500], txt: "¥1500以上" },
  120. ],
  121. LeveStr: "",
  122. Leve: undefined,
  123. Levels: [
  124. { v: 2, t: "二星/经济" },
  125. { v: 3, t: "三星/舒适" },
  126. { v: 4, t: "四星/高档" },
  127. { v: 5, t: "五星/豪华" },
  128. ]
  129. };
  130. },
  131. methods: {
  132. pickerChange(da) {
  133. this.startStr = da.startStr;
  134. this.endStr = da.endStr;
  135. this.dayCount = da.dayCount;
  136. this.qda.checkInDate = da.startStr.dateStr;
  137. this.qda.checkOutDate = da.endStr.dateStr;
  138. this.showCaledar = false
  139. },
  140. selectaddress(da) {
  141. this.qda.cityName = da.cityName;
  142. this.qda.cityCode = da.cityCode;
  143. this.qda.queryText = da.queryText || undefined;
  144. this.addrStr = "";
  145. delete this.qda.longitude;
  146. delete this.qda.latitude;
  147. this.showAddress = false;
  148. },
  149. search() {
  150. let qd = Object.assign({}, this.qda)
  151. setCache("hotelquery", qd);
  152. this.goto("/pagesB/hotel/hotelList");
  153. },
  154. // 获取当前位置
  155. async getLocation() {
  156. let { lat, lng } = await uni.Location();
  157. this.adres = { longitude: lng, latitude: lat };
  158. this.getToCity()
  159. },
  160. // 获取当前城市
  161. getToCity() {
  162. post("local/hotel/city", this.adres).then(res => {
  163. if (res.code == 0) {
  164. let da = res.data
  165. this.qda.cityName = da.cityName;
  166. this.qda.cityCode = da.cityCode;
  167. }
  168. })
  169. },
  170. locationf() {
  171. delete this.qda.queryText;
  172. this.getLocation();
  173. let that = this;
  174. showmap.reverseGeocoder({
  175. success(result) {
  176. let da = result.result
  177. that.addrStr = da.formatted_addresses.recommend;
  178. let { lat, lng } = da.location
  179. that.qda = { ...that.qda, longitude: lng, latitude: lat }
  180. }
  181. });
  182. },
  183. onRange(va) {
  184. this.priceRange = va.p
  185. setTimeout(() => {
  186. this.numinfo = va.txt
  187. }, 0)
  188. },
  189. activef(va) {
  190. if (va.p[0] == this.priceRange[0] && va.p[1] == this.priceRange[1]) {
  191. return true
  192. } else return false
  193. },
  194. onLevel(va) {
  195. if (this.Leve == va.v) {
  196. this.Leve = undefined
  197. } else this.Leve = va.v
  198. },
  199. confirm() {
  200. if (this.priceRange.length) {
  201. this.qda.minPrice = this.priceRange[0]
  202. if (this.priceRange[0] != this.priceRange[1]) {
  203. this.qda.maxPrice = this.priceRange[1]
  204. } else {
  205. delete this.qda.maxPrice;
  206. }
  207. }
  208. if (this.Leve) {
  209. this.qda.hotelStars = this.Leve
  210. }
  211. this.popupShow = false
  212. },
  213. reset() {
  214. this.priceRange = [];
  215. delete this.qda.minPrice;
  216. delete this.qda.maxPrice;
  217. this.Leve = "";
  218. delete this.qda.hotelStars;
  219. this.popupShow = false
  220. }
  221. },
  222. watch: {
  223. priceRange: {
  224. immediate: true,
  225. deep: true,
  226. handler(va) {
  227. this.numinfo = `¥${va[0]} - ${va[1]}`
  228. }
  229. },
  230. Leve: {
  231. immediate: true,
  232. deep: true,
  233. handler(va) {
  234. for (const i of this.Levels) {
  235. if(i.v == va){
  236. this.LeveStr = i.t
  237. }
  238. }
  239. }
  240. },
  241. },
  242. onLoad(da) {
  243. this.$refs.dayPicker.getInit();
  244. this.locationf();
  245. },
  246. onShow() {},
  247. mounted() {},
  248. };
  249. </script>
  250. <style scoped lang='scss'>
  251. .hotel {
  252. width: 100%;
  253. height: 1350rpx;
  254. background-image: url("https://teaclub.oss-cn-chengdu.aliyuncs.com/CloudShop/head_pic/78b6d4099023da41dd44706cea7381a.jpg");
  255. background-size: 100% 100%;
  256. position: relative;
  257. }
  258. .formbox {
  259. width: calc(100% - 60rpx);
  260. position: absolute;
  261. left: 30rpx;
  262. top: 450rpx;
  263. }
  264. .tabtit {
  265. background-color: #fff;
  266. width: 250rpx;
  267. height: 80rpx;
  268. line-height: 80rpx;
  269. border-radius: 10rpx 10rpx 0 0;
  270. font-size: 38rpx;
  271. font-weight: 600;
  272. text-align: center;
  273. color: #00B76C;
  274. }
  275. .formbar {
  276. background-color: #fff;
  277. border-radius: 0 10rpx 10rpx 10rpx;
  278. padding: 16rpx 40rpx 22rpx;
  279. .li {
  280. border-bottom: 1px solid #d8d8d8;
  281. &:last-child {
  282. border-bottom: 0px;
  283. }
  284. padding: 18rpx 0;
  285. .ico {
  286. font-size: 20rpx;
  287. margin-left: 16rpx;
  288. }
  289. .address {
  290. padding: 0 12rpx;
  291. .address_name {
  292. display: inline-block;
  293. font-weight: 600;
  294. min-width: 66rpx;
  295. }
  296. span {
  297. vertical-align: middle;
  298. }
  299. }
  300. input {
  301. font-size: 28rpx;
  302. }
  303. .lab {
  304. border-bottom: 4rpx solid #00B76C;
  305. padding-bottom: 8rpx;
  306. font-size: 28rpx;
  307. color: #00B76C;
  308. }
  309. .day {
  310. width: 166rpx;
  311. text-align: center;
  312. .ti {
  313. color: #999;
  314. font-size: 24rpx;
  315. margin-bottom: 6rpx;
  316. }
  317. .daytxt {
  318. font-size: 36rpx;
  319. color: #00B76C;
  320. font-weight: 600;
  321. }
  322. }
  323. .day,
  324. .lab {
  325. vertical-align: middle;
  326. }
  327. }
  328. .addressStr {
  329. width: 350rpx;
  330. font-size: 28rpx;
  331. margin-left: 10rpx;
  332. }
  333. .location {
  334. text-align: center;
  335. .ico2 {
  336. font-size: 36rpx;
  337. color: #000;
  338. }
  339. .it {
  340. font-size: 20rpx;
  341. color: #999;
  342. }
  343. }
  344. }
  345. .ni_popup {
  346. width: 100%;
  347. height: 100vh;
  348. background-color: rgba($color: #000, $alpha: .4);
  349. position: fixed;
  350. left: 0;
  351. top: 0;
  352. z-index: 999;
  353. .pbtn {
  354. margin-top: 50rpx;
  355. .btn {
  356. color: #666;
  357. font-size: 34rpx;
  358. width: 250rpx;
  359. text-align: center;
  360. background-color: rgba($color: #00B76C, $alpha: .3);
  361. height: 70rpx;
  362. border-radius: 35rpx;
  363. line-height: 70rpx;
  364. }
  365. .corg {
  366. background-color: #00B76C;
  367. color: #fff;
  368. }
  369. }
  370. }
  371. .starLevel {
  372. width: 100%;
  373. height: 720rpx;
  374. padding: 26rpx 32rpx;
  375. background-color: #fff;
  376. border-radius: 32rpx 32rpx 0 0;
  377. position: absolute;
  378. left: 0;
  379. bottom: 0;
  380. .h_numinfo {
  381. margin-bottom: 26rpx;
  382. font-size: 32rpx;
  383. .msg {
  384. color: #00B76C;
  385. margin-left: 12rpx;
  386. }
  387. }
  388. .sliderBar {
  389. .num {
  390. color: #999;
  391. font-size: 24rpx;
  392. margin-bottom: 18rpx;
  393. }
  394. .sb {
  395. padding: 0 18rpx;
  396. }
  397. }
  398. .nums {
  399. display: grid;
  400. justify-content: space-between;
  401. grid-template-columns: repeat(auto-fill, 160rpx);
  402. grid-gap: 0 1px;
  403. margin-bottom: -10rpx;
  404. margin-top: 45rpx;
  405. .num_item {
  406. color: #333;
  407. width: 160rpx;
  408. text-align: center;
  409. height: 50rpx;
  410. line-height: 50rpx;
  411. font-size: 26rpx;
  412. background-color: rgba($color: #000, $alpha: 0.08);
  413. margin-bottom: 12rpx;
  414. border-radius: 8rpx;
  415. &.active {
  416. color: #000;
  417. background-color: rgba($color: #00B76C, $alpha: 0.8);
  418. }
  419. }
  420. }
  421. .LevelB {
  422. margin-top: 45rpx;
  423. .tit {
  424. font-size: 32rpx;
  425. margin-bottom: 20rpx;
  426. }
  427. .ls_i {
  428. color: #333;
  429. font-size: 26rpx;
  430. background-color: rgba($color: #000, $alpha: 0.08);
  431. padding: 8rpx 22rpx;
  432. border-radius: 8rpx;
  433. &.active {
  434. color: #000;
  435. background-color: rgba($color: #00B76C, $alpha: 0.8);
  436. }
  437. }
  438. }
  439. }
  440. .footimg {
  441. width: 100%;
  442. position: fixed;
  443. bottom: -10rpx;
  444. left: 0;
  445. .btn {
  446. width: 272rpx;
  447. position: absolute;
  448. left: calc(50% - 136rpx);
  449. top: -3rpx;
  450. }
  451. .img {
  452. width: 100%;
  453. }
  454. }
  455. </style>