shopDetail.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. <template>
  2. <view class="container-shop">
  3. <navbar :config="config" backColor="#666"></navbar>
  4. <view class="header">
  5. <view class="banner" v-if="shopInfo.store_images">
  6. <image :src="shopInfo.store_images.split(',')[0]" mode="aspectFill"></image>
  7. </view>
  8. <view class="shop-name">
  9. <view class="title">
  10. <view class="title-label omit">
  11. {{shopInfo.shop_name}}
  12. </view>
  13. <view class="score">
  14. <rate :value="Math.round(shopInfo.average)"></rate>
  15. <view class="score-txt omit" v-if="shopInfo.average">{{shopInfo.average.toFixed(2)}}分</view>
  16. </view>
  17. <view class="tip">
  18. <text class="iconfont3 notice">&#xe623;</text>
  19. <text class="notice-text omit">{{shopInfo.special_offers || '暂无优惠信息'}}</text>
  20. </view>
  21. </view>
  22. <image class="shop-logo" :src="shopInfo.logo" mode="aspectFill"></image>
  23. <view class="help">
  24. <view class="btn" @click="callPhone">
  25. <view class="iconfont3 help-icon">&#xe679;</view>
  26. <view>打电话</view>
  27. </view>
  28. <view class="btn" @click="jumpNavigator">
  29. <view class="iconfont3 help-icon">&#xe613;</view>
  30. <view>导航去</view>
  31. </view>
  32. </view>
  33. </view>
  34. </view>
  35. <view class="tabs" :class="{'tabSticky': sticky}" :style="{'top': stickyHeight + 'px'}">
  36. <view class="tab" :class="{'activeTab': currentTab == index}" v-for="(item, index) in tabs" :key="item.i"
  37. @click="tabsChange(index)">
  38. <view class="label">
  39. {{item.label}}
  40. </view>
  41. </view>
  42. </view>
  43. <view v-if="sticky" :style="{'height': viewHeight + 'px'}"></view>
  44. <view class="mian" :style="{'height': mainHeight + 'px'}">
  45. <view class="body">
  46. <template v-if="currentTab == 0">
  47. <scroll-view class="scrollview" scroll-y="true">
  48. <view class="classifyTab" :class="{'classifyActiveTab': classifyCurrentTab == index}"
  49. v-for="(item, index) in classifyTabs" :key="item.id" @click="classifyChange(index, item)">
  50. <view class="class-name">
  51. {{item.name}}
  52. </view>
  53. </view>
  54. </scroll-view>
  55. <scroll-view class="scrollview" scroll-y="true">
  56. <view v-for="(item, index) in goodsList" :key="item.id" @click="jumpGoogsDetail(item)">
  57. <shop-goods :goodsDetail="item"></shop-goods>
  58. </view>
  59. <noData v-if="goodsList.length<=0"></noData>
  60. </scroll-view>
  61. </template>
  62. <template v-if="currentTab == 1">
  63. <view class="introduction">
  64. <view class="shop-text">
  65. <view class="label">
  66. <view class="iconfont3 text-icon">&#xe639;</view>
  67. 门店简介:
  68. </view>
  69. <view class="text">
  70. {{shopInfo.remark}}
  71. </view>
  72. </view>
  73. <view class="shop-text">
  74. <view class="label">
  75. <view class="iconfont3 text-icon">&#xe639;</view>
  76. 营业时间:
  77. </view>
  78. <view class="text">
  79. {{shopInfo.time_quantum}}
  80. </view>
  81. </view>
  82. <view class="shop-text">
  83. <view class="label">
  84. <view class="iconfont3 text-icon">&#xe639;</view>
  85. 门店地址:
  86. </view>
  87. <view class="text">
  88. {{shopInfo.address}}
  89. </view>
  90. </view>
  91. </view>
  92. </template>
  93. </view>
  94. </view>
  95. </view>
  96. </template>
  97. <script>
  98. import rate from "@/components/rate.vue";
  99. import shopGoods from "@/components/shop-goods.vue";
  100. import noData from "@/components/noData/nodata.vue"
  101. export default {
  102. components: {
  103. rate,
  104. shopGoods,
  105. noData
  106. },
  107. data() {
  108. return {
  109. config: {
  110. back: true,
  111. title: '门店',
  112. color: '#1a1a1a',
  113. backgroundColor: [1, "#fff"],
  114. statusBarFontColor: '#FFFFFF',
  115. leftSlot: true
  116. },
  117. headerHeight: 0,
  118. stickyHeight: 0,
  119. viewHeight: 0,
  120. mainHeight: 0,
  121. sticky: false,
  122. shopId: '',
  123. shopInfo: {},
  124. tabs: [{
  125. label: '商品',
  126. i: 0
  127. },
  128. {
  129. label: '商家简介',
  130. i: 1
  131. }
  132. ],
  133. currentTab: 0,
  134. classifyTabs: [],
  135. classifyCurrentTab: 0,
  136. goodsList: []
  137. }
  138. },
  139. onLoad(options) {
  140. if (options && options.shopId) {
  141. this.shopId = options.shopId
  142. this.getShopInfo(options.shopId)
  143. this.getGoodsClassify(options.shopId)
  144. }
  145. },
  146. onShow() {
  147. this.$nextTick(() => {
  148. let sysInfo = uni.getSystemInfoSync()
  149. this.$u.getRect('.header').then(res => {
  150. this.headerHeight = res.height
  151. this.stickyHeight = sysInfo.statusBarHeight + 44
  152. })
  153. this.$u.getRect('.tabs').then(res => {
  154. this.viewHeight = res.height
  155. this.mainHeight = sysInfo.screenHeight - sysInfo.statusBarHeight - 44 - res.height
  156. })
  157. })
  158. },
  159. onReady() {},
  160. onPageScroll(e) {
  161. if (e.scrollTop >= this.headerHeight) {
  162. this.sticky = true
  163. } else {
  164. this.sticky = false
  165. }
  166. },
  167. methods: {
  168. // 获取店铺信息
  169. getShopInfo(shopId) {
  170. this.$http.get("/yxt/shop/info/" + shopId).then((res) => {
  171. // uni.stopPullDownRefresh();
  172. // this.loading = false;
  173. if (res.data && res.code == 200) {
  174. this.shopInfo = res.data;
  175. }
  176. });
  177. },
  178. // 获取商品分类
  179. getGoodsClassify(shopId) {
  180. this.$http.get("/offlinetype/goods/list", {
  181. shopId: shopId,
  182. isGoods: 0
  183. }).then(res => {
  184. if (res.code == 200) {
  185. if (res.list.length > 0) {
  186. this.classifyTabs = res.list
  187. this.getClassifyGoods(res.list[0].id, shopId)
  188. }
  189. }
  190. })
  191. },
  192. // 获取商品
  193. getClassifyGoods(classifyId, shopId) {
  194. this.$http.get("/offline/goods/page", {
  195. isUp: 1,
  196. typeId: classifyId,
  197. isGoods: 0,
  198. shopId: shopId,
  199. }).then(res => {
  200. if (res.code == 200) {
  201. this.goodsList = res.page.list
  202. }
  203. })
  204. },
  205. tabsChange(i) {
  206. if (this.currentTab == i) {
  207. return false
  208. }
  209. this.currentTab = i
  210. },
  211. classifyChange(i, item) {
  212. if (this.classifyCurrentTab == i) {
  213. return false
  214. }
  215. this.classifyCurrentTab = i
  216. this.getClassifyGoods(item.id, item.shop_id)
  217. },
  218. callPhone() {
  219. if (!this.shopInfo.mobile) {
  220. return this.$mUtil.toast('暂无客服热线')
  221. }
  222. this.$mUtil.callup(this.shopInfo.mobile)
  223. },
  224. jumpNavigator() {
  225. if (!this.shopInfo.tx_latitude || !this.shopInfo.tx_longitude) {
  226. return this.$mUtil.toast('暂无地址')
  227. }
  228. this.$mUtil.jumpLocation(this.shopInfo.tx_latitude, this.shopInfo.tx_longitude)
  229. },
  230. jumpGoogsDetail(item) {
  231. uni.navigateTo({
  232. url: `/pages/nearbyShop/goodsDetail?goodsId=${item.id}&shopId=${item.shop_id}`
  233. })
  234. }
  235. }
  236. }
  237. </script>
  238. <style lang="scss" scoped>
  239. .container-shop {
  240. .header {
  241. width: 100%;
  242. height: auto;
  243. background-color: #fff;
  244. .banner {
  245. width: 100%;
  246. height: 290rpx;
  247. image {
  248. width: 100%;
  249. height: 100% !important;
  250. vertical-align: middle;
  251. }
  252. }
  253. .shop-name {
  254. position: relative;
  255. width: 720rpx;
  256. height: 306rpx;
  257. margin: -84rpx auto 0;
  258. background-color: #fff;
  259. background: url('@/static/shop/shop-bg.png') no-repeat;
  260. background-size: 100% 100%;
  261. .title {
  262. max-width: 400rpx;
  263. margin-bottom: 30rpx;
  264. padding: 34rpx 0 0 45rpx;
  265. font-size: 30rpx;
  266. font-family: PingFang SC, PingFang SC-Bold;
  267. font-weight: 700;
  268. }
  269. .title-label {
  270. margin-bottom: 14rpx;
  271. color: #333333;
  272. }
  273. .shop-logo {
  274. position: absolute;
  275. top: -57rpx;
  276. right: 45rpx;
  277. width: 226rpx;
  278. height: 221rpx !important;
  279. flex-shrink: 0;
  280. border-radius: 20rpx;
  281. }
  282. .score {
  283. display: flex;
  284. align-items: center;
  285. margin-bottom: 15rpx;
  286. font-weight: 500;
  287. /deep/ .box {
  288. display: flex;
  289. align-items: center;
  290. }
  291. .score-txt {
  292. flex: 1;
  293. width: 0;
  294. }
  295. }
  296. .tip {
  297. display: flex;
  298. align-items: center;
  299. font-size: 24rpx;
  300. font-family: PingFang SC, PingFang SC-Regular;
  301. font-weight: 400;
  302. .notice {
  303. font-size: 26rpx;
  304. color: #FA6138;
  305. margin-right: 4rpx;
  306. }
  307. }
  308. .omit {
  309. overflow: hidden;
  310. text-overflow: ellipsis;
  311. white-space: nowrap;
  312. }
  313. .help {
  314. display: flex;
  315. width: 690rpx;
  316. margin: 0 auto;
  317. border-top: 1rpx solid #f2f2f2;
  318. .btn {
  319. display: flex;
  320. justify-content: center;
  321. align-items: center;
  322. width: 50%;
  323. padding: 30rpx 0 20rpx;
  324. text-align: center;
  325. font-size: 28rpx;
  326. font-family: PingFang SC, PingFang SC-Regular;
  327. font-weight: 400;
  328. color: #333333;
  329. .help-icon {
  330. margin-right: 7rpx;
  331. color: #ff6600;
  332. font-size: 36rpx;
  333. }
  334. }
  335. }
  336. }
  337. }
  338. .tabs {
  339. display: flex;
  340. align-items: center;
  341. justify-content: space-between;
  342. width: 100%;
  343. padding: 0 202rpx 30rpx;
  344. background-color: #fff;
  345. .tab {
  346. position: relative;
  347. padding: 12rpx 0 9rpx;
  348. color: #1A1A1A;
  349. font-size: 30px;
  350. font-family: PingFang SC, PingFang SC-Bold;
  351. font-weight: 700;
  352. }
  353. .activeTab {
  354. color: #FA6138;
  355. &::after {
  356. display: block;
  357. content: '';
  358. position: absolute;
  359. bottom: 0;
  360. width: 100%;
  361. height: 4rpx;
  362. background: #FA6138;
  363. border-radius: 2rpx;
  364. z-index: 3;
  365. }
  366. }
  367. }
  368. .tabSticky {
  369. position: fixed;
  370. z-index: 9;
  371. }
  372. .mian {
  373. .body {
  374. height: 100%;
  375. display: flex;
  376. .scrollview {
  377. height: 100%;
  378. }
  379. .scrollview:first-child {
  380. width: 180rpx;
  381. flex-shrink: 0;
  382. background-color: #f6f6f6;
  383. font-size: 24rpx;
  384. font-family: PingFang SC, PingFang SC-Regular;
  385. font-weight: 400;
  386. text-align: center;
  387. color: #666666;
  388. .classifyTab {
  389. position: relative;
  390. text-align: center;
  391. line-height: 120rpx;
  392. background-color: #f6f6f6;
  393. display: flex;
  394. justify-content: center;
  395. .class-name {
  396. width: 80%;
  397. overflow: hidden;
  398. text-overflow: ellipsis;
  399. white-space: nowrap;
  400. }
  401. }
  402. .classifyActiveTab {
  403. background-color: #fff;
  404. font-size: 28rpx;
  405. font-family: PingFang SC, PingFang SC-Bold;
  406. font-weight: 700;
  407. color: #FA6138;
  408. &::before {
  409. display: block;
  410. content: '';
  411. position: absolute;
  412. left: 0;
  413. top: 50%;
  414. transform: translateY(-50%);
  415. width: 6rpx;
  416. height: 40rpx;
  417. background-color: #FA6138;
  418. }
  419. }
  420. }
  421. .scrollview:last-child {
  422. padding-left: 36rpx;
  423. padding-right: 30rpx;
  424. font-size: 24rpx;
  425. font-family: PingFang SC, PingFang SC-Regular;
  426. font-weight: 400;
  427. color: #181818;
  428. /deep/ .no-data-view {
  429. margin-top: 0 !important;
  430. }
  431. }
  432. .introduction {
  433. padding: 40rpx;
  434. .shop-text {
  435. margin-bottom: 17rpx;
  436. }
  437. .label {
  438. display: flex;
  439. align-items: center;
  440. margin-bottom: 10rpx;
  441. font-size: 28rpx;
  442. font-family: PingFang SC, PingFang SC-Bold;
  443. font-weight: 700;
  444. color: #1a1a1a;
  445. .text-icon {
  446. font-size: 40rpx;
  447. color: #FF6600;
  448. margin-right: 5rpx;
  449. }
  450. }
  451. .text {
  452. font-size: 24rpx;
  453. font-family: PingFang SC, PingFang SC-Regular;
  454. font-weight: 400;
  455. text-align: left;
  456. color: #666666;
  457. line-height: 40rpx;
  458. }
  459. }
  460. }
  461. }
  462. }
  463. </style>