index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. <template>
  2. <view :style="colorStyle" class="container">
  3. <view class="headerBg">
  4. <!-- #ifdef MP || APP -->
  5. <view :style="{height: getHeight.barTop+'px'}"></view>
  6. <view :style="{height: getHeight.barHeight+'px'}"></view>
  7. <!-- #endif -->
  8. <view style="height: 240rpx;"></view>
  9. </view>
  10. <view class="page acea-row row-column">
  11. <!-- #ifdef MP || APP -->
  12. <NavBar titleText="门店列表" textColor="#FFFFFF"></NavBar>
  13. <!-- #endif -->
  14. <view class="navBox acea-row row-between">
  15. <view :class="{ on: content.store_type === 1 }" class="item acea-row row-center row-middle" @tap="navChange(1)">附近</view>
  16. <view :class="{ on: content.store_type === 2 }" class="item acea-row row-center row-middle" @tap="navChange(2)">常用</view>
  17. <view class="header_search acea-row">
  18. <view class="name acea-row row-middle row-center" @click="btnFn(2)">{{area}}<text class="iconfont icon-ic_down2"></text></view>
  19. <view class="box acea-row row-middle">
  20. <input type="text" confirm-type="search" placeholder="请输入门店名称" class="input" @input="setValue" v-model="content.keyword" />
  21. <text class="iconfont icon-ic_search"></text>
  22. </view>
  23. </view>
  24. <view class="mapbtn" @click="goMap">
  25. <image src="@/static/images/map.png" class="image"></image>
  26. </view>
  27. </view>
  28. <scroll-view scroll-y="true" class="scroll-view">
  29. <!-- 门店列表 -->
  30. <view class="content" v-if="info.length>0">
  31. <view class="list acea-row row-middle" v-for="(item,index) in info" :key="item.id" @click="activeFn(item)">
  32. <image class="image" :src="item.image"></image>
  33. <view class="left">
  34. <view class="name line2">
  35. {{item.name}}
  36. </view>
  37. <view class="adress line1">
  38. {{item.address}}{{item.detailed_address}}
  39. </view>
  40. <view class="distance">
  41. 距您 <text class="range">{{item.range}}</text> km
  42. </view>
  43. </view>
  44. <view class="right">
  45. <view class="gostore acea-row row-center row-middle">进店</view>
  46. </view>
  47. </view>
  48. </view>
  49. <!-- 缺省页 -->
  50. <view class="px-20" v-if="info.length==0">
  51. <emptyPage title="暂无门店信息~" src="/statics/images/noOrder.gif"></emptyPage>
  52. </view>
  53. </scroll-view>
  54. <view :style="{height: pdHeight*2+96+'rpx'}" v-if="showBar"></view>
  55. <view class="safe-area-inset-bottom" v-if="showBar"></view>
  56. </view>
  57. <areaWindow ref="areaWindow" :display="display" :checkStrictly="false" :cityShow="2" :address="addressInfo" @submit="OnChangeAddress" @changeClose="changeClose"></areaWindow>
  58. <pageFooter @newDataStatus="newDataStatus"></pageFooter>
  59. </view>
  60. </template>
  61. <script>
  62. import {
  63. HTTP_REQUEST_URL
  64. } from '@/config/app';
  65. import colors from "@/mixins/color";
  66. import {
  67. getList
  68. } from '@/api/new_store.js'
  69. import {
  70. getGeocoder,
  71. getCityList
  72. } from '@/api/user.js';
  73. import NavBar from '@/components/NavBar.vue';
  74. import emptyPage from '@/components/emptyPage.vue';
  75. import areaWindow from '@/components/areaWindow/index.vue';
  76. import pageFooter from '@/components/pageFooter/index.vue';
  77. export default {
  78. components: {
  79. NavBar,
  80. emptyPage,
  81. areaWindow,
  82. pageFooter,
  83. },
  84. mixins: [colors],
  85. data() {
  86. return {
  87. getHeight: this.$util.getWXStatusHeight(),
  88. imgHost: HTTP_REQUEST_URL,
  89. sortIndex: 0,
  90. active: 1,
  91. content: {
  92. // 自己的位置
  93. latitude: uni.getStorageSync('user_latitude'),
  94. longitude: uni.getStorageSync('user_longitude'),
  95. store_type: 1,
  96. keyword: "",
  97. province: 0,
  98. city: 0,
  99. area: 0,
  100. },
  101. info: [],
  102. map: 1,
  103. header: 1,
  104. comeType: 0,
  105. // 门店位置
  106. latitudeStore: uni.getStorageSync('user_latitude'),
  107. longitudeStore: uni.getStorageSync('user_longitude'),
  108. covers: [],
  109. display: false,
  110. addressInfo: [],
  111. showBar: 0,
  112. pdHeight: 0,
  113. };
  114. },
  115. computed: {
  116. area() {
  117. let area = '全部';
  118. for (let i = 0; i < this.addressInfo.length; i++) {
  119. if (this.addressInfo[i].value) {
  120. area = this.addressInfo[i].label
  121. }
  122. }
  123. return area;
  124. }
  125. },
  126. onLoad(options) {
  127. // this.comeType = options.type
  128. // this.sortIndex = options.storeId
  129. // this.isCollage = options.isCollage
  130. this.getlist()
  131. },
  132. methods: {
  133. goMap() {
  134. uni.navigateTo({
  135. // #ifdef APP
  136. url: `/pages/store/mapnvue/index?province=${this.content.province}&city=${this.content.city}&area=${this.content.area}`
  137. // #endif
  138. // #ifndef APP
  139. url: `/pages/store/map/index?province=${this.content.province}&city=${this.content.city}&area=${this.content.area}`
  140. // #endif
  141. })
  142. },
  143. navChange(type) {
  144. this.content.store_type = type;
  145. this.getlist();
  146. },
  147. getCityList({
  148. province,
  149. city,
  150. district
  151. }) {
  152. getCityList(`${province}/${city}/${district}`).then(({
  153. data
  154. }) => {
  155. this.addressInfo = data;
  156. this.content.province = data[0].value;
  157. this.content.city = data[1].value;
  158. this.content.area = data[2].value;
  159. this.getlist();
  160. });
  161. },
  162. getGeocoder(location) {
  163. getGeocoder(location).then(res => {
  164. const {
  165. province,
  166. city,
  167. district
  168. } = res.data.address_component;
  169. this.getCityList({
  170. province,
  171. city,
  172. district
  173. });
  174. });
  175. },
  176. selfLocation() {
  177. let self = this
  178. // #ifdef H5
  179. if (self.$wechat.isWeixin()) {
  180. self.$wechat.location().then(res => {
  181. this.content.latitude = res.latitude;
  182. this.content.longitude = res.longitude;
  183. uni.setStorageSync('user_latitude', res.latitude);
  184. uni.setStorageSync('user_longitude', res.longitude);
  185. self.getlist();
  186. }).catch(err => {
  187. self.getlist();
  188. })
  189. } else {
  190. // #endif
  191. uni.getLocation({
  192. type: 'wgs84',
  193. success: ({
  194. latitude,
  195. longitude
  196. }) => {
  197. try {
  198. // this.content.latitude = res.latitude;
  199. // this.content.longitude = res.longitude;
  200. // uni.setStorageSync('user_latitude', res.latitude);
  201. // uni.setStorageSync('user_longitude', res.longitude);
  202. this.getGeocoder({
  203. lat: latitude,
  204. long: longitude
  205. });
  206. } catch {}
  207. // self.getlist();
  208. },
  209. complete: function() {
  210. // self.getlist();
  211. }
  212. });
  213. // #ifdef H5
  214. }
  215. // #endif
  216. },
  217. // 门店列表
  218. getlist() {
  219. getList(this.content).then(res => {
  220. this.info = res.data
  221. res.data.forEach(item => {
  222. if (this.sortIndex == item.id) {
  223. this.latitudeStore = item.latitude;
  224. this.longitudeStore = item.longitude;
  225. this.covers.push({
  226. title: item.name,
  227. latitude: item.latitude,
  228. longitude: item.longitude,
  229. iconPath: item.image,
  230. width: 30,
  231. height: 30
  232. })
  233. }
  234. })
  235. })
  236. },
  237. // 输入关键字搜索门店
  238. setValue(e) {
  239. this.getlist()
  240. },
  241. // 点击高亮
  242. activeFn(row) {
  243. uni.navigateTo({
  244. url: '/pages/store/home/index?mapFrom=1&id=' + row.id
  245. })
  246. },
  247. // 搜索门店
  248. searchMap() {
  249. this.header = 0
  250. },
  251. // 收起地图
  252. putMap() {
  253. if (this.map == 1) {
  254. this.map = 0
  255. } else if (this.map == 0) {
  256. this.map = 1
  257. }
  258. },
  259. // 打电话
  260. callPhone(row) {
  261. uni.makePhoneCall({
  262. phoneNumber: row.phone //仅为示例
  263. });
  264. },
  265. btnFn(num) {
  266. // switch (num) {
  267. // case 1:
  268. // this.active = 1
  269. // this.content.store_type = 1
  270. // break;
  271. // case 2:
  272. // this.active = 2
  273. // this.content.store_type = 2
  274. // break;
  275. // }
  276. // this.getlist()
  277. this.display = true;
  278. },
  279. showMaoLocation(e) {
  280. let self = this;
  281. // #ifdef H5
  282. if (self.$wechat.isWeixin()) {
  283. return self.$wechat.seeLocation({
  284. latitude: Number(e.latitude),
  285. longitude: Number(e.longitude),
  286. name: e.name,
  287. scale: 13,
  288. address: `${e.address}-${e.detailed_address}`,
  289. }).then(res => {})
  290. }
  291. // #endif
  292. uni.openLocation({
  293. latitude: Number(e.latitude),
  294. longitude: Number(e.longitude),
  295. name: e.name,
  296. address: `${e.address}-${e.detailed_address}`,
  297. success: function() {
  298. Number
  299. }
  300. });
  301. },
  302. changeClose() {
  303. this.display = false;
  304. },
  305. OnChangeAddress(address) {
  306. this.addressInfo = address;
  307. this.content.province = address[0] ? address[0].value : 0;
  308. this.content.city = address[1] ? address[1].value : 0;
  309. this.content.area = address[2] ? address[2].value : 0;
  310. this.getlist();
  311. },
  312. newDataStatus(val, num) {
  313. this.showBar = val;
  314. this.pdHeight = num;
  315. },
  316. }
  317. }
  318. </script>
  319. <style lang="scss">
  320. .safe-area-inset-bottom {
  321. height: constant(safe-area-inset-bottom);
  322. height: env(safe-area-inset-bottom);
  323. }
  324. page {
  325. background: #F5F5F5;
  326. }
  327. .container {
  328. position: absolute;
  329. top: 0;
  330. right: 0;
  331. bottom: 0;
  332. left: 0;
  333. overflow: hidden;
  334. flex-wrap: nowrap;
  335. }
  336. .headerBg {
  337. position: absolute;
  338. top: 0;
  339. left: 0;
  340. width: 100%;
  341. background: linear-gradient(360deg, #F8F8F8 0%, rgba(248, 248, 248, 0) 100%),
  342. linear-gradient(-90deg, var(--view-gradient) 37%, var(--view-theme) 100%);
  343. background-position: left bottom, left bottom;
  344. background-repeat: no-repeat;
  345. background-size: 100% 114rpx, 100% 100%;
  346. }
  347. .page {
  348. position: relative;
  349. flex-wrap: nowrap;
  350. height: 100%;
  351. }
  352. .nearby .active,
  353. .content .active {
  354. position: relative;
  355. border: 1px solid var(--view-theme) !important;
  356. .icon-xuanzhong6 {
  357. font-size: 46rpx;
  358. position: absolute;
  359. bottom: -8rpx;
  360. right: -6rpx;
  361. color: var(--view-theme);
  362. }
  363. }
  364. .activeColor {
  365. background-color: var(--view-theme) !important;
  366. color: #fff !important;
  367. }
  368. .scroll-view {
  369. flex: 1;
  370. min-height: 0;
  371. }
  372. .content {
  373. padding: 0 20rpx;
  374. overflow: hidden;
  375. .list {
  376. padding: 32rpx;
  377. border-radius: 16rpx;
  378. margin-bottom: 20rpx;
  379. background: #FFFFFF;
  380. .image {
  381. width: 140rpx;
  382. height: 140rpx;
  383. border-radius: 12rpx;
  384. }
  385. .left {
  386. flex: 1;
  387. min-width: 0;
  388. padding: 0 32rpx 0 24rpx;
  389. .name {
  390. font-weight: 500;
  391. font-size: 28rpx;
  392. line-height: 40rpx;
  393. color: #333333;
  394. }
  395. .adress {
  396. margin-top: 10rpx;
  397. font-size: 22rpx;
  398. line-height: 30rpx;
  399. color: #999999;
  400. }
  401. .distance {
  402. margin-top: 10rpx;
  403. font-size: 20rpx;
  404. line-height: 20rpx;
  405. color: #999999;
  406. .range {
  407. color: var(--view-theme);
  408. }
  409. }
  410. }
  411. .right {
  412. .gostore {
  413. flex-wrap: nowrap;
  414. width: 108rpx;
  415. height: 52rpx;
  416. border-radius: 26rpx;
  417. background: linear-gradient(-90deg, var(--view-gradient) 37%, var(--view-theme) 100%);
  418. font-weight: 500;
  419. font-size: 22rpx;
  420. color: #FFFFFF;
  421. }
  422. }
  423. }
  424. }
  425. .lyric-enter,
  426. .lyric-leave-to {
  427. opacity: 0;
  428. transform: translateY(60px);
  429. }
  430. .lyric-enter-to,
  431. .lyric-leave {
  432. opacity: 1;
  433. }
  434. .lyric-enter-active,
  435. .lyric-leave-active {
  436. transition: all 0.3s;
  437. }
  438. .header_search {
  439. width: 416rpx;
  440. height: 58rpx;
  441. border-radius: 29rpx;
  442. padding: 0 0 0 24rpx;
  443. background: rgba(255, 255, 255, 0.3);
  444. .name {
  445. color: #FFFFFF;
  446. position: relative;
  447. font-size: 24rpx;
  448. .iconfont {
  449. font-size: 16rpx;
  450. margin-left: 6rpx;
  451. }
  452. &:before {
  453. position: absolute;
  454. content: '';
  455. width: 1px;
  456. height: 24rpx;
  457. background-color: rgba(255, 255, 255, 0.4);
  458. right: 0;
  459. top: 50%;
  460. margin-top: -12rpx;
  461. }
  462. padding-right: 20rpx;
  463. }
  464. .box {
  465. flex: 1;
  466. min-width: 0;
  467. height: 58rpx;
  468. padding-right: 18rpx;
  469. .input {
  470. flex: 1;
  471. min-width: 0;
  472. height: 58rpx;
  473. padding-left: 20rpx;
  474. font-size: 24rpx;
  475. color: rgba(255, 255, 255, 1);
  476. }
  477. .input-placeholder {
  478. color: rgba(255, 255, 255, 0.6);
  479. }
  480. .iconfont {
  481. font-size: 32rpx;
  482. color: rgba(255, 255, 255, 0.6);
  483. }
  484. }
  485. }
  486. .navBox {
  487. flex-wrap: nowrap;
  488. padding: 40rpx 20rpx 42rpx 32rpx;
  489. .item {
  490. position: relative;
  491. font-size: 28rpx;
  492. color: rgba(255, 255, 255, 0.6);
  493. }
  494. .on {
  495. font-weight: 500;
  496. font-size: 30rpx;
  497. color: #FFFFFF;
  498. &::after {
  499. position: absolute;
  500. content: '';
  501. width: 36rpx;
  502. height: 30rpx;
  503. border: 2px solid #FFFFFF;
  504. border-left: 2px solid transparent !important;
  505. border-top: 2px solid transparent !important;
  506. border-right: 2px solid transparent !important;
  507. border-radius: 50%;
  508. left: 50%;
  509. bottom: -12rpx;
  510. margin-left: -24rpx;
  511. }
  512. }
  513. .mapbtn {
  514. width: 54rpx;
  515. height: 54rpx;
  516. .image {
  517. width: 100%;
  518. height: 100%;
  519. }
  520. }
  521. }
  522. </style>