home.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <template>
  2. <view class="container">
  3. <!-- 搜索框区域 -->
  4. <uv-row custom-style="margin: 10px 0px" gutter="10">
  5. <picker @change="bindPickerChange" :value="placeIndex" :range="placeList">
  6. <view class="address">
  7. <view class="address_text">{{ placeList[placeIndex] }}</view>
  8. <img src="../../static/index/bottom.png" />
  9. </view>
  10. </picker>
  11. <view class="search">
  12. <view class="add">
  13. <image class="img" src="../../static/index/search.png" mode="aspectFit"></image>
  14. </view>
  15. <input class="inp" type="text" v-model="keywords" placeholder="请输入关键字搜索" />
  16. <view class="btnSearch" @click="searchHandler">搜索</view>
  17. </view>
  18. </uv-row>
  19. <!-- 名宿列表区域 -->
  20. <view class="body" v-if="hotelList.length">
  21. <!-- 每一个名宿区域 -->
  22. <view class="item" v-for="item in hotelList" :key="item.id" @click="goPageDetail(item)">
  23. <image class="item-img" :src="item.coverImg || '../../static/search/img.png'" mode="scaleToFill"></image>
  24. <view class="descrition">
  25. <text class="title">{{ item.hname || '默认名字' }}</text>
  26. <text class="type">{{ item.htype || '默认' }}型</text>
  27. <text class="distance" v-if="showdDistance">距您直线{{ item.distance || 0 }}公里</text>
  28. <view class="detail">
  29. <img class="img" src="../../static/index/hotel.png" />
  30. <view class="price">
  31. <text class="txt1">¥{{ item.min_price || 180 }}</text>
  32. <text class="txt2">起</text>
  33. </view>
  34. </view>
  35. </view>
  36. </view>
  37. </view>
  38. <!-- 没有数据时展示的页面 -->
  39. <view class="noData" v-else>
  40. <img src="../../static/images/noData.png" />
  41. 暂无数据
  42. </view>
  43. </view>
  44. </template>
  45. <script>
  46. export default {
  47. data() {
  48. return {
  49. // 是否显示距离差
  50. showdDistance: false,
  51. // 搜索框绑定数据
  52. keywords: '',
  53. // 民宿列表数组
  54. hotelList: [],
  55. // 地区数组
  56. placeList: ['靖安县', '宝峰镇', '三爪乡'],
  57. // 当前选择地区索引
  58. placeIndex: 0,
  59. // 当前页
  60. page: 1,
  61. // 每页多少条
  62. rows: 6,
  63. // 总条数
  64. total: null,
  65. // 当前用户定位经度
  66. myLng: 0,
  67. // 当前用户定位纬度
  68. myLat: 0,
  69. // 签到点中心经度
  70. centerLng: 0,
  71. // 签到点中心纬度
  72. centerLat: 0,
  73. // 距离签到点的距离
  74. distance: 0
  75. }
  76. },
  77. onLoad() {
  78. this.getLocation()
  79. // this.getHotelList()
  80. },
  81. methods: {
  82. // 获取用户当前位置
  83. getLocation() {
  84. uni.getSetting({
  85. success: (res) => {
  86. if (!res.authSetting['scope.userLocation']) {
  87. uni.authorize({
  88. scope: 'scope.userLocation',
  89. success: (res) => {
  90. // 授权成功
  91. uni.getLocation({
  92. type: 'gcj02',
  93. success: (res) => {
  94. this.myLat = res.latitude
  95. this.myLng = res.longitude
  96. this.showdDistance = true
  97. this.getHotelList()
  98. console.log('2当前位置的经度:' + res.longitude)
  99. console.log('2当前位置的纬度:' + res.latitude)
  100. }
  101. })
  102. },
  103. fail: () => {
  104. uni.showModal({
  105. content: '获取定位权限失败将会影响使用部分功能,是否去设置打开?',
  106. confirmText: '确认',
  107. cancelText: '取消',
  108. success: (res) => {
  109. if (res.confirm) {
  110. uni.openSetting({
  111. success: (res) => {
  112. console.log(res)
  113. this.getLocation()
  114. }
  115. })
  116. } else {
  117. this.showdDistance = false
  118. this.getHotelList()
  119. uni.showToast({
  120. title: '获取定位权限失败',
  121. icon: 'none'
  122. })
  123. }
  124. }
  125. })
  126. }
  127. })
  128. } else {
  129. uni.getLocation({
  130. type: 'gcj02',
  131. success: (res) => {
  132. this.myLat = res.latitude
  133. this.myLng = res.longitude
  134. this.showdDistance = true
  135. this.getHotelList()
  136. console.log('当前位置的经度:' + res.longitude)
  137. console.log('当前位置的纬度:' + res.latitude)
  138. }
  139. })
  140. }
  141. }
  142. })
  143. },
  144. // 获取民宿列表
  145. async getHotelList() {
  146. const res = await this.$myRequest({
  147. url: '/mhotel/ahphomePage.action',
  148. data: {
  149. queryValue: this.keywords,
  150. page: this.page,
  151. rows: this.rows
  152. }
  153. })
  154. // console.log(res)
  155. this.hotelList = res.pageList
  156. console.log(this.myLat)
  157. console.log(this.myLng)
  158. if (this.showdDistance && this.hotelList.length) {
  159. this.hotelList.forEach((ele) => {
  160. ele.distance = this.calculateDistance(28.86054, 115.361744)
  161. })
  162. }
  163. console.log(this.hotelList)
  164. this.total = res.total
  165. },
  166. // 计算两个点之间的距离
  167. calculateDistance(lat, lng) {
  168. let centerLat = lat
  169. let centerLng = lng
  170. let red1 = (this.myLat * Math.PI) / 180.0
  171. let red2 = (centerLat * Math.PI) / 180.0
  172. let a = red1 - red2
  173. let b = (this.myLng * Math.PI) / 180.0 - (centerLng * Math.PI) / 180.0
  174. let R = 6378137
  175. let distance = R * 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(red1) * Math.cos(red2) * Math.pow(Math.sin(b / 2), 2)))
  176. let res = (distance / 1000).toFixed(2) * 1
  177. return res
  178. },
  179. // 搜索按钮点击回调
  180. searchHandler() {
  181. console.log(this.keywords)
  182. // this.page = 1
  183. // this.getHotelList()
  184. },
  185. // 点击每一个名宿卡片回调
  186. goPageDetail(item) {
  187. // console.log(item)
  188. const info = JSON.stringify(item)
  189. uni.navigateTo({
  190. url: `/pages/detail/detail?info=${info}`
  191. })
  192. },
  193. // 选择地区时的回调
  194. bindPickerChange(e) {
  195. console.log('picker发送选择改变,携带值为', e.detail.value)
  196. this.placeIndex = e.detail.value
  197. }
  198. }
  199. }
  200. </script>
  201. <style lang="scss" scoped>
  202. .container {
  203. display: flex;
  204. flex-direction: column;
  205. width: 750rpx;
  206. min-height: 100vh;
  207. padding: 0 30rpx;
  208. box-sizing: border-box;
  209. background-color: #f7f7f7;
  210. .address {
  211. display: flex;
  212. width: 152rpx;
  213. font-size: 28rpx;
  214. .address_text {
  215. width: 104rpx;
  216. text-align: center;
  217. overflow: hidden;
  218. white-space: nowrap;
  219. text-overflow: ellipsis;
  220. }
  221. img {
  222. width: 48rpx;
  223. height: 48rpx;
  224. }
  225. }
  226. .search {
  227. display: flex;
  228. justify-content: space-between;
  229. align-items: center;
  230. width: 538rpx;
  231. height: 80rpx;
  232. opacity: 1;
  233. border-radius: 70px;
  234. background-color: #fff;
  235. .add {
  236. display: flex;
  237. justify-content: center;
  238. align-items: center;
  239. margin-left: 10rpx;
  240. width: 60rpx;
  241. font-size: 50rpx;
  242. height: 60rpx;
  243. line-height: 60rpx;
  244. color: rgba(30, 125, 251, 1);
  245. .img {
  246. width: 30rpx;
  247. height: 30rpx;
  248. }
  249. }
  250. .inp {
  251. height: 60rpx;
  252. line-height: 60rpx;
  253. flex-grow: 1;
  254. font-size: 28rpx;
  255. }
  256. .btnSearch {
  257. width: 100rpx;
  258. text-align: center;
  259. margin-right: 10rpx;
  260. height: 60rpx;
  261. line-height: 60rpx;
  262. opacity: 1;
  263. font-size: 28rpx;
  264. font-weight: 400;
  265. height: 2rem;
  266. color: #096562;
  267. }
  268. }
  269. .body {
  270. display: flex;
  271. justify-content: space-between;
  272. flex-wrap: wrap;
  273. .item {
  274. width: 335rpx;
  275. box-sizing: border-box;
  276. margin-bottom: 20rpx;
  277. .item-img {
  278. width: 100%;
  279. height: 223rpx;
  280. border-radius: 18rpx 18rpx 0 0;
  281. box-sizing: border-box;
  282. }
  283. .descrition {
  284. display: flex;
  285. flex-direction: column;
  286. width: 100%;
  287. border-radius: 0 0 18rpx 18rpx;
  288. box-sizing: border-box;
  289. background: rgba(255, 255, 255, 1);
  290. margin-top: -10rpx;
  291. .title {
  292. font-size: 28rpx;
  293. font-weight: 600;
  294. padding: 20rpx 20rpx 10rpx;
  295. color: rgba(0, 0, 0, 1);
  296. }
  297. .type {
  298. padding: 5rpx 20rpx;
  299. font-size: 24rpx;
  300. color: #a6a6a6;
  301. }
  302. .distance {
  303. padding: 10rpx 20rpx;
  304. font-size: 24rpx;
  305. color: #a6a6a6;
  306. }
  307. .detail {
  308. display: flex;
  309. flex-direction: row;
  310. justify-content: space-between;
  311. align-items: center;
  312. padding: 0 20rpx 20rpx 20rpx;
  313. color: rgba(0, 0, 0, 1);
  314. .img {
  315. width: 40rpx;
  316. height: 40rpx;
  317. }
  318. .price {
  319. .txt1 {
  320. font-size: 36rpx;
  321. font-weight: 600;
  322. color: rgba(255, 87, 51, 1);
  323. }
  324. .txt2 {
  325. font-size: 24rpx;
  326. font-weight: 400;
  327. color: #a6a6a6;
  328. }
  329. }
  330. .score {
  331. font-size: 24rpx;
  332. font-weight: 400;
  333. padding-top: 10rpx;
  334. color: rgba(166, 166, 166, 1);
  335. }
  336. }
  337. }
  338. }
  339. }
  340. .noData {
  341. display: flex;
  342. flex-direction: column;
  343. justify-content: center;
  344. align-items: center;
  345. img {
  346. margin-top: 150rpx;
  347. width: 600rpx;
  348. height: 600rpx;
  349. }
  350. }
  351. }
  352. </style>