city.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. <template>
  2. <view class="container">
  3. <navbar id="navbar" :config="config" backColor="#666666"></navbar>
  4. <view class="search-top" :style="{'top': sticky + 'px'}">
  5. <view class="city-text" @click="addressShow=true">
  6. <image mode="widthFix" src="/static/shop/location-icon.png"></image>
  7. <view>{{cityName}}</view>
  8. </view>
  9. <view class="searchBox">
  10. <u-search v-model="param.shop_name" shape="round" :clearabled="false" height="70" bg-color="#f7f7f7"
  11. border-color="#D9D9D9" laceholder-color="#CCCCCC" search-icon="/static/shop/search-icon.png"
  12. @search="$u.throttle(search, 1000)" @custom="$u.throttle(search, 1000)"></u-search>
  13. </view>
  14. </view>
  15. <view style="height: 110rpx;"></view>
  16. <view class="u-skeleton">
  17. <view class="banner" v-if="bannerList.length > 0||skeletonShow">
  18. <!-- <image src="/static/shop/banner.png" mode="aspectFill"></image> -->
  19. <u-swiper class="u-skeleton-fillet" :list="bannerList" name="cover" height="360" :mode="bannerList.length>1?'round':'none'"
  20. bg-color="transparent" @click="bannerClick"></u-swiper>
  21. </view>
  22. <view class="menu" v-if="typeList.length > 0 || iconList.length > 0||skeletonShow">
  23. <swiper class="swiper u-skeleton-fillet" :indicator-dots="true" :autoplay="false" :current="current"
  24. :style="{'height':((iconList[current]&&iconList[current].length)>5?'350rpx':'150rpx')}" @change="swiperChange">
  25. <swiper-item class="swiper-item" v-for="(el, k) in iconList">
  26. <view class="item" v-for="(v,i) in (skeletonShow?5:el)" :key="i" @click="goShop(v)">
  27. <view class="img">
  28. <image class="u-skeleton-fillet" :src="v.icon" mode="widthFix"></image>
  29. </view>
  30. <text class="u-skeleton-fillet">{{v.name||'加载中'}}</text>
  31. </view>
  32. </swiper-item>
  33. </swiper>
  34. </view>
  35. <view class="con-box">
  36. <u-section class="u-skeleton-fillet" title="附近门店" font-size="36" :bold="true" color="#333333" :show-line="false" sub-title="查看更多"
  37. sub-color="#333333" @click="goShop()">
  38. </u-section>
  39. <view class="items">
  40. <view class="item " v-for="(v, index) in (skeletonShow?10:listData)" :key="index" @click="goDetails(v)">
  41. <view class="shop-img">
  42. <image class="u-skeleton-fillet" :src="v.logo" mode="aspectFill"></image>
  43. </view>
  44. <view class="right">
  45. <view class="title u-skeleton-fillet">{{v.shop_name||'加载中'}}</view>
  46. <view class="score-box u-skeleton-fillet">
  47. <view class="score ">
  48. <rate :value="Math.round(v.average||0)"></rate>
  49. </view>
  50. <text class="score-text ">{{v.average?v.average.toFixed(2):''}}分</text>
  51. <text class="ju">距离:{{Math.round(v.distance/1000*100)/100}}KM</text>
  52. </view>
  53. <view class="address-box u-skeleton-fillet">
  54. <view class="left">
  55. <image class="location1" src="/static/shop/location-icon.png" mode="widthFix">
  56. </image>
  57. <view class="district">{{v.map_punctuation || '商户暂无地理位置'}}</view>
  58. </view>
  59. <view class="goShopping">
  60. <text class="iconfont3">&#xe787;</text>
  61. <text class="text">去逛逛</text>
  62. </view>
  63. </view>
  64. <!-- <view class="location2-box">
  65. <image class="location2" src="/static/convenienceService/location2.png" mode="widthFix">
  66. </image>
  67. <view>{{v.map_punctuation}}&gt;</view>
  68. </view> -->
  69. </view>
  70. </view>
  71. </view>
  72. </view>
  73. <view>
  74. <noData v-if="listData.length<=0"></noData>
  75. </view>
  76. <!-- <u-loadmore :status="loadStatus" /> -->
  77. <u-skeleton :loading="skeletonShow" :animation="true" bgColor="#FFF"></u-skeleton>
  78. </view>
  79. <!-- 选择地区 -->
  80. <u-select v-model="addressShow" mode="mutil-column-auto" :list="cityTree" @confirm="addressConfirm">
  81. </u-select>
  82. <entrepreneurship-zone-tabbar :current="2"></entrepreneurship-zone-tabbar>
  83. </view>
  84. </template>
  85. <script>
  86. import rate from "@/components/rate.vue"
  87. import noData from "@/components/noData/nodata.vue"
  88. import {
  89. number
  90. } from "mathjs";
  91. export default {
  92. components: {
  93. rate,
  94. noData
  95. },
  96. data() {
  97. return {
  98. config: {
  99. back: true,
  100. title: '附近门店',
  101. color: '#1A1A1A',
  102. backgroundColor: [1, "#fff"],
  103. // statusBarFontColor: '#1A1A1A',
  104. leftSlot: true
  105. },
  106. //手机状态栏高度
  107. statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
  108. sticky: uni.getSystemInfoSync().statusBarHeight + 44,
  109. // loadStatus: 'loadmore', //loading / nomore
  110. pageParams: {
  111. page: 1,
  112. limit: 10,
  113. city_code: 420100, //武汉市
  114. },
  115. listData: [],
  116. loading: false,
  117. cityName: '洪山区',
  118. addressShow: false,
  119. param: {
  120. union_business: true
  121. },
  122. cityTree: [],
  123. typeList: [],
  124. iconList: [],
  125. bannerList: [],
  126. current: 0,
  127. skeletonShow:true
  128. }
  129. },
  130. onLoad() {
  131. this.getCitys();
  132. this.getLoca();
  133. this.getTypeList();
  134. this.getBanner()
  135. // this.getList();
  136. },
  137. onPullDownRefresh() {
  138. this.getList();
  139. this.getTypeList();
  140. this.getBanner();
  141. setTimeout(() => {
  142. uni.stopPullDownRefresh();
  143. }, 1000);
  144. },
  145. methods: {
  146. goShop(item = {}) {
  147. uni.navigateTo({
  148. url: '/pages/nearbyShop/list?id=' + (item.id || '') + '&cityName=' + this.cityName + '&address=' + (this
  149. .param.address || '') + '&area_code=' + (this.param.area_code || '')
  150. })
  151. },
  152. getBanner() {
  153. this.$http.get('/ad/ad/getByCode/localMerchant-banner')
  154. .then(res => {
  155. if (res.code == 200) {
  156. this.bannerList = res.list;
  157. }
  158. })
  159. },
  160. bannerClick(e) {
  161. let item = this.bannerList[e]
  162. this.$mUtil.imgLink(item.model_type, item.model_id, item.url, item.shop_id)
  163. },
  164. // 获取城市
  165. getCitys() {
  166. this.$http.get('/cnarea/tree-lbs').then(res => {
  167. if (res && res.code == 200) {
  168. this.cityTree = res.tree.children
  169. this.cityTree.forEach(v => {
  170. if (v.children.length <= 0) {
  171. v.children = [{}]
  172. }
  173. })
  174. this.skeletonShow=false;
  175. }
  176. })
  177. },
  178. getLoca() {
  179. let that = this
  180. // #ifdef APP-PLUS
  181. uni.getLocation({
  182. type: 'gcj02',
  183. geocode: true,
  184. success: function(res) {
  185. that.cityName = res.address ? res.address.district : '';
  186. that.param.address = res.address.province + res.address.city + res.address.district
  187. that.param.lon = res.longitude;
  188. that.param.lat = res.latitude;
  189. that.getList()
  190. if (!that.cityName) {
  191. uni.request({
  192. url: `https://restapi.amap.com/v3/geocode/regeo?key=47798318a0d39673a1fb9729aa6a468a&location=${res.longitude+','+res.latitude}`, //仅为示例,并非真实接口地址。
  193. method: "GET",
  194. header: {
  195. "content-type": "application/x-www-form-urlencoded"
  196. },
  197. success: (re) => {
  198. console.log(re);
  199. that.cityName = re.data.regeocode
  200. .addressComponent.city;
  201. }
  202. });
  203. }
  204. },
  205. complete(e) {
  206. console.log(e)
  207. }
  208. });
  209. // #endif
  210. // #ifdef H5
  211. this.getList()
  212. // #endif
  213. },
  214. // 获取便民服务分类列表
  215. getTypeList() {
  216. this.$http.get('/union/business/classify/list').then(res => {
  217. if (res && res.code == 200) {
  218. this.typeList = res.list
  219. let list = []
  220. let typePage = Math.ceil(res.list.length / 10)
  221. for (let i = 0; i < typePage; i++) {
  222. list[i] = this.typeList.splice(0, 10)
  223. }
  224. this.iconList = list
  225. }
  226. })
  227. },
  228. swiperChange(e) {
  229. if (e) {
  230. this.current = e.detail.current
  231. }
  232. },
  233. // 选择地区
  234. addressConfirm(e) {
  235. // this.param.city_code = e[2].value ? e[2].value : e[1].value ? e[1].value : e[0].value;
  236. this.cityName = e[2].label ? e[2].label : e[1].label ? e[1].label : e[0].label;
  237. this.param.area_code = e[2].value ? e[2].value : e[1].value ? e[1].value : e[0].value;
  238. delete this.param.address
  239. // this.param.lon = e[1].data.longitude || e[0].data.longitude;
  240. // this.param.lat = e[1].data.latitude || e[0].data.latitude;
  241. console.log(e)
  242. this.getList()
  243. },
  244. // service/goods/nearby /convenience/service/classify/list
  245. getList() {
  246. let that = this;
  247. uni.showLoading({
  248. title: '努力加载中...',
  249. mask: true
  250. });
  251. // this.loadStatus = 'loading';
  252. this.$http.get('/service/goods/nearby', that.param)
  253. .then(res => {
  254. if (res.code == 200) {
  255. that.listData = res.list;
  256. // that.loadStatus = that.listData.length > 0 ? 'loadmore' : 'nomore';
  257. }
  258. })
  259. .finally(() => {
  260. uni.hideLoading();
  261. })
  262. },
  263. // 跳转商品详情
  264. goDetails(v) {
  265. uni.navigateTo({
  266. url: "/pages/nearbyShop/shopDetail?shopId=" + v.shop_id
  267. })
  268. },
  269. search() {
  270. this.getList()
  271. },
  272. }
  273. }
  274. </script>
  275. <style lang="scss" scoped>
  276. .container {
  277. .search-top {
  278. position: fixed;
  279. width: 100%;
  280. height: 110rpx;
  281. display: flex;
  282. justify-content: space-between;
  283. align-items: center;
  284. padding: 0 30rpx;
  285. background-color: #fff;
  286. z-index: 3;
  287. }
  288. .city-text {
  289. margin-right: 12rpx;
  290. font-size: 30rpx;
  291. font-family: PingFang SC, PingFang SC-Regular;
  292. font-weight: 400;
  293. text-align: center;
  294. color: #666666;
  295. display: flex;
  296. align-items: center;
  297. view {
  298. max-width: 100rpx;
  299. white-space: nowrap;
  300. text-overflow: ellipsis;
  301. overflow: hidden;
  302. }
  303. image {
  304. width: 26rpx;
  305. height: 36rpx;
  306. margin-right: 10rpx;
  307. vertical-align: middle;
  308. }
  309. }
  310. .searchBox {
  311. position: relative;
  312. flex: 1;
  313. // width: 580rpx;
  314. height: 70rpx;
  315. image {
  316. width: 35rpx;
  317. height: 35rpx;
  318. }
  319. /deep/ .u-content {
  320. padding-left: 27rpx;
  321. border-radius: 36rpx !important;
  322. .u-input {
  323. margin-left: 22rpx;
  324. margin-right: 124rpx;
  325. }
  326. }
  327. /deep/ .u-action-active {
  328. position: absolute;
  329. top: 0;
  330. right: 0;
  331. width: 124rpx;
  332. height: 70rpx;
  333. margin-left: 0;
  334. background: linear-gradient(98deg,#fa673e 5%, #fdac69 94%);
  335. border-radius: 35rpx;
  336. font-size: 30rpx;
  337. line-height: 70rpx;
  338. font-family: PingFang SC, PingFang SC-Regular;
  339. font-weight: 400;
  340. text-align: center;
  341. color: #ffffff;
  342. }
  343. }
  344. }
  345. .navbar {
  346. position: fixed;
  347. top: 0;
  348. left: 0;
  349. width: 100%;
  350. height: 90rpx;
  351. text-align: center;
  352. line-height: 90rpx;
  353. z-index: 9;
  354. background-color: #fff;
  355. .title {
  356. font-size: 36rpx;
  357. font-family: PingFang SC, PingFang SC-Regular;
  358. font-weight: 400;
  359. text-align: center;
  360. color: #1a1a1a;
  361. }
  362. .left {
  363. position: absolute;
  364. top: 50%;
  365. left: 30rpx;
  366. display: flex;
  367. align-items: center;
  368. font-size: 30rpx;
  369. font-family: PingFang SC, PingFang SC-Regular;
  370. font-weight: 400;
  371. text-align: center;
  372. color: #1a1a1a;
  373. transform: translateY(-50%);
  374. .city-icon {
  375. width: 19rpx;
  376. height: 12rpx;
  377. margin-left: 5rpx;
  378. }
  379. }
  380. }
  381. .banner {
  382. width: 100%;
  383. height: 350rpx;
  384. padding: 0rpx 30rpx 0;
  385. margin-bottom: 20rpx;
  386. image {
  387. width: 100%;
  388. height: 100%;
  389. }
  390. /deep/ uni-swiper {
  391. height: 350rpx !important;
  392. }
  393. }
  394. .menu {
  395. display: flex;
  396. // justify-content: space-between;
  397. // align-items: center;
  398. flex-wrap: wrap;
  399. padding: 0 30rpx;
  400. margin-bottom: 22rpx;
  401. .swiper {
  402. width: 100%;
  403. height: auto;
  404. transition: all .3s;
  405. /deep/ .uni-swiper-dots-horizontal {
  406. bottom: 0;
  407. .uni-swiper-dot-active {
  408. background-color: #FA6138;
  409. }
  410. }
  411. }
  412. .swiper-item {
  413. display: flex;
  414. flex-wrap: wrap;
  415. }
  416. .item {
  417. display: flex;
  418. flex-direction: column;
  419. align-items: center;
  420. width: 20%;
  421. margin-bottom: 30rpx;
  422. .img {
  423. width: 70rpx;
  424. height: 70rpx;
  425. margin-bottom: 13rpx;
  426. // border-radius: 50%;
  427. overflow: hidden;
  428. image {
  429. width: 100%;
  430. height: 100%;
  431. }
  432. }
  433. text {
  434. width: 100%;
  435. font-size: 26rpx;
  436. font-family: PingFang SC, PingFang SC-Regular;
  437. font-weight: 400;
  438. text-align: center;
  439. color: #1a1a1a;
  440. overflow: hidden;
  441. text-overflow: ellipsis;
  442. white-space: nowrap;
  443. }
  444. }
  445. // .item:nth-child(5n) {
  446. // margin-right: 0;
  447. // }
  448. }
  449. .con-box {
  450. padding: 0 30rpx;
  451. .u-section {
  452. margin-bottom: 27rpx;
  453. /deep/ .uicon-arrow-right:before {
  454. color: #666;
  455. }
  456. }
  457. .items {
  458. .item {
  459. display: flex;
  460. align-items: center;
  461. padding: 25rpx 0;
  462. // border-bottom: 1rpx solid #e6e6e6;
  463. .shop-img {
  464. width: 162rpx;
  465. height: 158rpx;
  466. margin-right: 40rpx;
  467. border-radius: 10rpx;
  468. overflow: hidden;
  469. flex-shrink: 0;
  470. image {
  471. width: 100%;
  472. height: 100%;
  473. }
  474. }
  475. .right {
  476. flex: 1;
  477. width: 0;
  478. .score-box,
  479. .address-box,
  480. .location2-box {
  481. display: flex;
  482. align-items: center;
  483. font-size: 24rpx;
  484. font-family: PingFang SC, PingFang SC-Regular;
  485. font-weight: 400;
  486. }
  487. .location1,
  488. .location2 {
  489. width: 20rpx;
  490. height: 27rpx;
  491. flex-shrink: 0;
  492. margin-right: 9rpx;
  493. }
  494. .light-start,
  495. .startt {
  496. width: 30rpx;
  497. height: 30rpx;
  498. margin-right: 12rpx;
  499. }
  500. .title {
  501. margin-bottom: 18rpx;
  502. font-size: 28rpx;
  503. font-family: PingFang SC, PingFang SC-Regular;
  504. color: #1a1a1a;
  505. }
  506. .score-box {
  507. display: flex;
  508. align-items: normal;
  509. margin-bottom: 10rpx;
  510. font-family: PingFang SC, PingFang SC-Semibold;
  511. color: #333333;
  512. .score {
  513. flex-shrink: 0;
  514. }
  515. .score-text {
  516. font-size: 24rpx;
  517. font-family: PingFang SC, PingFang SC-Medium;
  518. font-weight: 500;
  519. text-align: left;
  520. color: #333333;
  521. flex-shrink: 0;
  522. }
  523. .ju {
  524. margin-left: 23rpx;
  525. font-size: 24rpx;
  526. color: #808080;
  527. text-align: left;
  528. overflow: hidden;
  529. text-overflow: ellipsis;
  530. white-space: nowrap;
  531. }
  532. }
  533. .address-box {
  534. // margin-bottom: 10rpx;
  535. font-family: PingFang SC;
  536. color: #666666;
  537. justify-content: space-between;
  538. .left {
  539. flex: 1;
  540. width: 0;
  541. display: flex;
  542. align-items: center;
  543. font-size: 24rpx;
  544. font-family: PingFang SC, PingFang SC-Regular;
  545. font-weight: 400;
  546. text-align: left;
  547. color: #333333;
  548. }
  549. .goShopping {
  550. display: flex;
  551. align-items: center;
  552. font-size: 40rpx;
  553. color: #FA6138;
  554. flex-shrink: 0;
  555. .text {
  556. font-size: 24rpx;
  557. font-family: PingFang SC, PingFang SC-Medium;
  558. font-weight: 500;
  559. text-align: left;
  560. color: #666666;
  561. }
  562. }
  563. .district {
  564. color: #1a1a1a;
  565. margin-right: 40rpx;
  566. overflow: hidden;
  567. text-overflow: ellipsis;
  568. white-space: nowrap;
  569. }
  570. }
  571. .location2-box {
  572. color: #333333;
  573. view {
  574. overflow: hidden;
  575. text-overflow: ellipsis;
  576. white-space: nowrap;
  577. }
  578. }
  579. }
  580. }
  581. }
  582. }
  583. </style>