index.vue 13 KB

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