index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. <template>
  2. <div class="scenicSpotTicket">
  3. <scroll-view @scrolltolower="scrolltolower" class="scroll-view" :scroll-y="true" :scroll-top="scrollTop" @scroll="scroll" :lower-threshold="100">
  4. <div class="head_box">
  5. <uni-easyinput prefixIcon="search" suffixIcon="搜索" v-model="qda.keyWord" placeholder="景点、目的地址、景点主题..." @confirm="onsearch" @change="onsearch" confirmType="search"/>
  6. <div class="filter_box flex_r">
  7. <div class="filter_item" @click="showAddress = true">
  8. <span class="item_name">{{qda.cityName}}</span>
  9. <span class="iconfont ico">&#xeb6d;</span>
  10. </div>
  11. <div class="filter_item" @click="popupOpen">
  12. <span class="item_name">{{sortFit}}</span>
  13. <span class="iconfont ico">&#xeb6d;</span>
  14. </div>
  15. </div>
  16. </div>
  17. <div class="scenicList" v-if="list.length">
  18. <div class="scenic_item flex_r flex_jb flex_wrap" v-for="(i,s) in list" :key="s" @click="goScenic({id:i.scenicId})">
  19. <image :src="i.mainImage" mode="aspectFill" class="s_img" />
  20. <div class="info">
  21. <div class="scenicName">{{i.scenicName}}</div>
  22. <div class="address">{{ i.address }}</div>
  23. <div class="s_info">
  24. <span>{{ i.themeGroups }}</span>
  25. <span v-if="i.distance">距我{{i.distance}}km</span>
  26. <span class="hotelStar">{{ i.star }}A</span>
  27. </div>
  28. <div class="avgScore flex_r flex_jb">
  29. <div class="avgScore_num flex_r flex_jb flex_ac">
  30. <uni-rate :max="5" :value="i.commentScore" :size="12" allow-half />
  31. <span class="commentScore">{{i.commentScore}}分</span>
  32. </div>
  33. <div class="dinB price" v-if="i.marketPrice">{{ i.marketPrice }}</div>
  34. <div class="price" v-else>暂无报价</div>
  35. </div>
  36. </div>
  37. <div class="openTime">{{ i.openTime }}</div>
  38. </div>
  39. </div>
  40. <div class="onlist" v-if="onlist">
  41. <image class="errimg" src="http://teaclub.oss-cn-chengdu.aliyuncs.com/CloudShop/head_pic/8ff923549b8ef026eeca56d23d5e4bdc3a69299epng" mode="widthFix" />
  42. <div class="errmsg">没有搜索到景区喔~</div>
  43. </div>
  44. </scroll-view>
  45. <div class="BackTop iconfont" @click="onBackTop" v-if="oldscrollTop > 500">&#xe632;</div>
  46. <h-address @select="selectaddress" :visible.sync="showAddress" />
  47. <uni-popup ref="popup" :safe-area="false">
  48. <div class="popup_con">
  49. <div class="sort_li">
  50. <div class="sort_item flex_r flex_jb flex_ac" v-for="(i,s) in sorts" :key="s" @click="onsort(i.v)">
  51. <span :class="{corg:i.v == qda.sort}">{{ i.t }}</span>
  52. <span class="iconfont ico" v-if="i.v == qda.sort">&#xe612;</span>
  53. </div>
  54. </div>
  55. </div>
  56. </uni-popup>
  57. </div>
  58. </template>
  59. <script>
  60. import hAddress from "@/pagesB/components/h-address/address.vue";
  61. import { post } from "@/request/api.js";
  62. import QQMapWX from '@/pagesB/static/js/qqmap-wx-jssdk.min.js';
  63. const showmap = new QQMapWX({ key: 'K7LBZ-RE23Q-JEN5D-4ZNEI-MS54Q-BHF6D' });
  64. export default {
  65. name: "scenicSpotTicket",
  66. props: {},
  67. components: {
  68. hAddress
  69. },
  70. data() {
  71. return {
  72. qda: {
  73. pageIndex: 1,
  74. pageSize: 20,
  75. sort: 0,
  76. distanceRange: 600,
  77. },
  78. listcount: 20,
  79. list: [], //景区列表
  80. showAddress: false,
  81. sorts: [
  82. {v:0,t:"综合排序"},
  83. {v:1,t:"好评优先"},
  84. {v:2,t:"距我最近"},
  85. {v:3,t:"星级最高"},
  86. ],
  87. scrollTop: 0,
  88. oldscrollTop: 0,
  89. onlist:false
  90. };
  91. },
  92. methods: {
  93. // 获取列表
  94. getlist() {
  95. let da = Object.assign({}, this.qda);
  96. uni.showLoading();
  97. post("local/ticket/scenicList", da).then((res) => {
  98. if (res.code == 0) {
  99. if (this.qda.pageIndex == 1) this.list = [];
  100. let da = res.data.data.scenicList;
  101. this.list = [...this.list, ...da];
  102. this.listcount = res.data.data.count;
  103. if(da.length) this.onlist = false
  104. else this.onlist = true
  105. }
  106. uni.hideLoading();
  107. });
  108. },
  109. // 滚动到底部拉取数据
  110. scrolltolower() {
  111. if (this.qda.pageIndex * this.qda.pageSize < this.listcount) {
  112. this.qda.pageIndex++;
  113. this.getlist();
  114. }
  115. },
  116. selectaddress(da) {
  117. this.qda.cityName = da.title;
  118. delete this.qda.latitude
  119. delete this.qda.longitude
  120. this.onsearch();
  121. this.showAddress = false;
  122. },
  123. openpicker(){
  124. this.$refs.cityPicker.show()
  125. },
  126. hidepicker(){
  127. this.$refs.cityPicker.show()
  128. },
  129. // 点击搜索
  130. onsearch() {
  131. this.qda.pageIndex = 1;
  132. this.getlist();
  133. },
  134. // 页面滚动
  135. scroll(e) {
  136. this.oldscrollTop = e.detail.scrollTop
  137. },
  138. // 返回顶部
  139. onBackTop(){
  140. this.scrollTop = this.oldscrollTop
  141. this.$nextTick(function() {
  142. this.scrollTop = 0;
  143. this.oldscrollTop = 0;
  144. });
  145. },
  146. popupOpen(){
  147. this.$refs.popup.open('bottom')
  148. },
  149. onsort(va){
  150. this.qda.sort = va;
  151. this.$refs.popup.close();
  152. this.onsearch();
  153. },
  154. goScenic(da){
  155. this.goto("/pagesB/scenicSpotTicket/scenic",da)
  156. }
  157. },
  158. onLoad(da) {
  159. let that = this
  160. showmap.reverseGeocoder({
  161. success(res) {
  162. let da = res.result.ad_info;
  163. that.citys = da.city_code.replace(da.nation_code, "");
  164. let { lat, lng } = res.result.location;
  165. that.qda = {
  166. ...that.qda,
  167. cityName: da.city,
  168. longitude: lng,
  169. latitude: lat
  170. }
  171. that.getlist();
  172. }
  173. });
  174. },
  175. onShow() {},
  176. mounted() {},
  177. computed: {
  178. sortFit() {
  179. for (const i of this.sorts) {
  180. if(i.v == this.qda.sort){
  181. return i.t
  182. }
  183. }
  184. }
  185. },
  186. };
  187. </script>
  188. <style scoped lang='scss'>
  189. .head_box {
  190. background-color: #fff;
  191. padding: 28rpx 32rpx;
  192. .inp_search{
  193. border: none;
  194. }
  195. }
  196. .filter_box{
  197. margin-top: 12rpx;
  198. font-size: 26rpx;
  199. .filter_item{
  200. margin-left: 36rpx;
  201. &:first-child{
  202. margin-left: 0;
  203. }
  204. .ico{
  205. font-size: 20rpx;
  206. margin-left: 12rpx;
  207. }
  208. }
  209. }
  210. .scroll-view {
  211. height: 100vh;
  212. }
  213. .scenicList {
  214. padding: 28rpx 32rpx 60rpx;
  215. }
  216. .scenic_item {
  217. background-color: #fff;
  218. padding: 26rpx 30rpx;
  219. margin-bottom: 16rpx;
  220. border-radius: 12rpx;
  221. box-shadow: 4rpx 4rpx 18rpx 2rpx rgba(17, 18, 29, 0.1);
  222. &:last-child {
  223. margin-bottom: 0;
  224. }
  225. .s_img {
  226. width: 160rpx;
  227. height: 230rpx;
  228. border-radius: 8rpx;
  229. }
  230. .info {
  231. position: relative;
  232. width: calc(100% - 186rpx);
  233. padding-bottom: 50rpx;
  234. .scenicName {
  235. font-size: 30rpx;
  236. font-weight: 600;
  237. margin-bottom: 8rpx;
  238. }
  239. .address {
  240. font-size: 22rpx;
  241. color: #666;
  242. }
  243. .s_info {
  244. font-size: 24rpx;
  245. color: #666;
  246. margin-top: 10rpx;
  247. span {
  248. margin-right: 18rpx;
  249. &:last-child {
  250. margin-right: 0;
  251. }
  252. }
  253. }
  254. .avgScore {
  255. width: 100%;
  256. position: absolute;
  257. bottom: 0;
  258. right: 0;
  259. }
  260. .avgScore_num {
  261. font-size: 24rpx;
  262. .commentScore {
  263. margin-left: 12rpx;
  264. }
  265. }
  266. .price {
  267. color: #666;
  268. font-size: 30rpx;
  269. }
  270. .dinB {
  271. font-size: 36rpx;
  272. color: #00B76C;
  273. &::before {
  274. content: "¥";
  275. font-size: 22rpx;
  276. }
  277. &::after {
  278. content: "起";
  279. margin-left: 6rpx;
  280. font-size: 22rpx;
  281. }
  282. }
  283. }
  284. .openTime {
  285. width: 100%;
  286. border-top: 2rpx dashed rgba($color: #000, $alpha: 0.25);
  287. margin-top: 16rpx;
  288. font-size: 26rpx;
  289. color: #666;
  290. padding-top: 8rpx;
  291. }
  292. }
  293. .popup_con{
  294. min-height: 500rpx;
  295. background-color: #fff;
  296. border-radius: 26rpx 26rpx 0 0;
  297. padding: 30rpx 32rpx 56rpx;
  298. .sort_item{
  299. padding: 16rpx 0;
  300. border-bottom: 1rpx solid rgba($color: #000, $alpha: 0.1);
  301. .ico{
  302. color: #00B76C;
  303. font-size: 32rpx;
  304. }
  305. .corg{
  306. color: #00B76C;
  307. }
  308. span{
  309. font-size: 30rpx;
  310. }
  311. }
  312. }
  313. .BackTop{
  314. width: 86rpx;
  315. height: 86rpx;
  316. text-align: center;
  317. line-height: 86rpx;
  318. font-size: 40rpx;
  319. position: fixed;
  320. right: 38rpx;
  321. bottom: 300rpx;
  322. background-color: rgba($color: #000, $alpha: 0.2);
  323. border-radius: 50%;
  324. color: #666;
  325. }
  326. .onlist{
  327. padding-top: 100rpx;
  328. text-align: center;
  329. .errimg{
  330. width: 500rpx;
  331. }
  332. .errmsg{
  333. font-size: 28rpx;
  334. color: #999;
  335. }
  336. }
  337. </style>
  338. <style>
  339. .uni-data-tree-input{
  340. display: none;
  341. }
  342. </style>