shop.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. <template>
  2. <app-layout>
  3. <view class="shop" :class=" fixed ? `shop-tab-` + tab:``">
  4. <!-- v1 -->
  5. <view class="shop-head">
  6. <view class="tt-bg"></view>
  7. <view class="black">
  8. <image :src="detail.store.pic_url && detail.store.pic_url.length && detail.store.pic_url[0].pic_url" class="shop-pic" lazy-load mode="aspectFill"></image>
  9. </view>
  10. <view class="shop-summary dir-left-nowrap cross-center" v-if="detail">
  11. <image :src="detail.store.cover_url" class="icon-pic"></image>
  12. <view class="dir-top-nowrap box-grow-1 main-center">
  13. <view class="shop-name t-omit">{{detail.store.name}}</view>
  14. <view class="box-grow-1 shop-goods">
  15. <text>商品:{{detail.goods_count}}</text>
  16. <text>已售:{{detail.order_goods_count}}</text>
  17. </view>
  18. </view>
  19. <view @click="openKfModal" class="cross-center dir-top-nowrap kf" v-if="is_service">
  20. <icon class="icon-kf" type></icon>
  21. <view>客服</view>
  22. </view>
  23. </view>
  24. </view>
  25. <!-- v2 -->
  26. <view class="cross-center main-center shop-tab">
  27. <view class="main-center cross-center box-grow-0 shop-search" @click="goodsSearch">
  28. <icon class="icon-search" type></icon>
  29. </view>
  30. <view class="cross-center main-center box-grow-1" style="padding: 0 32rpx">
  31. <view @click="tabChange(1)" class="cross-center main-center box-grow-1 dir-top-nowrap">
  32. <view :style="{'color': tab === 1 ? getTheme.color : ''}">首页</view>
  33. <view v-if="tab === 1" class="shop-tab-active" :style="{'background-color': getTheme.background}"></view>
  34. </view>
  35. <view @click="tabChange(2)" class="cross-center main-center box-grow-1 dir-top-nowrap">
  36. <view :style="{'color': tab === 2 ? getTheme.color : ''}">全部</view>
  37. <view v-if="tab === 2" class="shop-tab-active" :style="{'background-color': getTheme.background}"></view>
  38. </view>
  39. <view @click="tabChange(5)" class="cross-center main-center box-grow-1 dir-top-nowrap">
  40. <view :style="{'color': tab === 5 ? getTheme.color : ''}">新品</view>
  41. <view v-if="tab === 5" class="shop-tab-active" :style="{'background-color': getTheme.background}"></view>
  42. </view>
  43. <view @click="navigateSummary" class="cross-center main-center box-grow-1 dir-top-nowrap">
  44. <view>简介</view>
  45. </view>
  46. </view>
  47. </view>
  48. <!-- v3 -->
  49. <block v-if="tab === 1">
  50. <view class="shop-home">热销推荐</view>
  51. <u-ordinary-list :reset="reset" :pagination="true" :isShowAttr="true" :previewUrl="order_preview" :submitUrl="order_submit" :list="goods_list" :theme="getTheme" :list-style="2"></u-ordinary-list>
  52. </block>
  53. <block v-if="tab === 2">
  54. <view class="dir-left-nowrap shop-all">
  55. <view class="box-grow-1 dir-left-nowrap main-center cross-center" @click="navCat">
  56. <view>分类</view>
  57. <icon class="icon-cat" type></icon>
  58. </view>
  59. <view class="box-grow-1 dir-left-nowrap main-center cross-center" @click="changeStyle(1)">
  60. <view :style="{'color': sort === 1 ? getTheme.color : ''}">综合</view>
  61. </view>
  62. <view class="box-grow-1 dir-left-nowrap main-center cross-center" @click="changeStyle(4)">
  63. <view :style="{'color': sort === 4 ? getTheme.color : ''}">销量</view>
  64. </view>
  65. <view class="box-grow-1 dir-left-nowrap main-center cross-center" @click="changeStyle(3)">
  66. <view :style="{'color': sort === 3 ? getTheme.color : ''}">价格</view>
  67. <icon v-if="sort === 3 && sort_type === 1" class="icon-price-plus" :style="{'color': getTheme.color,'background-color': getTheme.background}" type></icon>
  68. <icon v-else-if="sort === 3 && sort_type === 0" class="icon-price-less" :style="{'color': getTheme.color,'background-color': getTheme.background}" type></icon>
  69. <icon v-else class="icon-price-default" type></icon>
  70. </view>
  71. </view>
  72. <u-ordinary-list :reset="reset" :pagination="true" :isShowAttr="true" :previewUrl="order_preview" :submitUrl="order_submit" :list="goods_list" :theme="getTheme" :list-style="2"></u-ordinary-list>
  73. </block>
  74. <block v-if="tab === 5">
  75. <view v-for="(v,k) in goods_list" :key="k" v-if="v.goods_list && v.goods_list.length">
  76. <view class="cross-center main-center dir-left-nowrap shop-new">
  77. <view class="line"></view>
  78. <view class="label">{{v.label}}</view>
  79. <view class="line"></view>
  80. </view>
  81. <u-ordinary-list :reset="reset" :pagination="true" :isShowAttr="true" :previewUrl="order_preview" :submitUrl="order_submit" :list="v.goods_list" :theme="getTheme" :list-style="2"></u-ordinary-list>
  82. </view>
  83. </block>
  84. <!-- v4 -->
  85. <view v-if="shopKf">
  86. <view class="act-modal show">
  87. <view class="act-modal-bg" @click="closeKfModal"></view>
  88. <view class="act-modal-pic main-center cross-center">
  89. <view class="shop-model">
  90. <image @click="closeKfModal" src="../../../static/image/icon/close.png"></image>
  91. <view class="kf">联系客服</view>
  92. <view class="cross-center dir-top-nowrap">
  93. <view v-if="mch_setting.is_web_service" @click="navigateCs"
  94. class="shop-info main-center cross-center dir-left-nowrap">
  95. <image :src="mch_setting.web_service_pic ? mch_setting.web_service_pic : './../image/shop-contact.png'"></image>
  96. <view>在线沟通</view>
  97. </view>
  98. <view v-if="detail.store.mobile" @click="callPhone"
  99. class="shop-info main-center cross-center dir-left-nowrap">
  100. <image src="./../image/shop-phone.png"></image>
  101. <view>致电商家</view>
  102. </view>
  103. <view v-if="detail.wechat" @click="copyInfo"
  104. class="shop-info main-center cross-center dir-left-nowrap">
  105. <image src="./../image/shop-wechat.png"></image>
  106. <view>复制微信号</view>
  107. </view>
  108. </view>
  109. </view>
  110. </view>
  111. </view>
  112. </view>
  113. </view>
  114. </app-layout>
  115. </template>
  116. <script>
  117. import {mapGetters, mapState} from 'vuex';
  118. import uOrdinaryList from '../../../components/page-component/u-goods-list/u-ordinary-list.vue';
  119. export default {
  120. name: "shop",
  121. components: {
  122. uOrdinaryList
  123. },
  124. computed: {
  125. ...mapState({
  126. userInfo: state => state.user.info,
  127. }),
  128. ...mapGetters('mallConfig', {
  129. getTheme: 'getTheme',
  130. }),
  131. },
  132. data() {
  133. return {
  134. mch_id: -1,
  135. sort: 1,
  136. cat_id: 0,
  137. sort_type: 0,
  138. page: 1,
  139. load: false,
  140. args: false,
  141. is_service: 0,
  142. detail: {store: {}},
  143. mch_setting: {},
  144. tab: 2,
  145. shopKf: false,
  146. coupon_list: [],
  147. goods_list: [],
  148. fixed: false,
  149. order_preview: this.$api.mch.order_preview,
  150. order_submit: this.$api.mch.order_submit,
  151. attrGoods: {
  152. attrShow: 0,
  153. goods: {}
  154. },
  155. reset: true
  156. }
  157. },
  158. onLoad(options) { this.$commonLoad.onload(options);
  159. //this.$store.dispatch('user/info');
  160. this.mch_id = options.mch_id;
  161. this.cat_id = options.cat_id ? options.cat_id : 0;
  162. this.loadShop();
  163. this.getGoods();
  164. this.getOption();
  165. this.addVisit();
  166. },
  167. onReachBottom: function () {
  168. const self = this;
  169. this.reset = false;
  170. if (self.args || self.load) return;
  171. self.load = true;
  172. let page = self.page + 1;
  173. self.$request({
  174. url: self.$api.mch.goods,
  175. data: {
  176. page: page,
  177. mch_id: self.mch_id,
  178. sort: self.sort,
  179. sort_type: self.sort_type,
  180. mch_status: 2,
  181. cat_id: self.cat_id,
  182. }
  183. }).then(info => {
  184. if (info.code === 0) {
  185. let goods_list;
  186. if (self.sort === 5) {
  187. goods_list = self.formatList(self.goods_list, info.data.list);
  188. } else {
  189. goods_list = self.goods_list.concat(info.data.list);
  190. }
  191. [self.page, self.args, self.goods_list] = [page, info.data.list.length === 0, goods_list];
  192. }
  193. self.load = false;
  194. });
  195. },
  196. // #ifdef MP
  197. onShareAppMessage () {
  198. return this.$shareAppMessage({
  199. title: this.detail.store.name,
  200. path: '/plugins/mch/shop/shop',
  201. params: {
  202. mch_id: this.mch_id,
  203. }
  204. });
  205. },
  206. // #endif
  207. methods: {
  208. goodsSearch() {
  209. uni.navigateTo({url: '/pages/search/search?mch_id=' + this.mch_id});
  210. },
  211. navCat() {
  212. uni.navigateTo({url: '/plugins/mch/cat/cat?mch_id=' + this.mch_id});
  213. },
  214. navigateSummary() {
  215. uni.navigateTo({url: `/plugins/mch/summary/summary?mch_id=` + this.mch_id});
  216. },
  217. navigateCs() {
  218. uni.navigateTo({url: `/pages/web/web?url=` + this.mch_setting.web_service_url});
  219. },
  220. getOption() {
  221. const self = this;
  222. self.$request({
  223. url: self.$api.mch.setting,
  224. }).then(info => {
  225. if (info.code === 0) {
  226. self.is_service = info.data.setting.is_service;
  227. }
  228. })
  229. },
  230. loadShop() {
  231. const self = this;
  232. self.$showLoading();
  233. self.$request({
  234. url: self.$api.mch.detail,
  235. data: {
  236. id: self.mch_id
  237. }
  238. }).then(info => {
  239. self.$hideLoading();
  240. if (info.code === 0) {
  241. [self.detail, self.mch_setting] = [info.data.detail, info.data.mchSetting];
  242. uni.setNavigationBarTitle({
  243. title: self.detail.store.name,
  244. });
  245. }
  246. }).catch(info => {
  247. self.$hideLoading();
  248. })
  249. },
  250. addVisit() {
  251. const self = this;
  252. self.$request({
  253. url: self.$api.mch.visit,
  254. method: "POST",
  255. data: {
  256. mch_id: self.mch_id
  257. }
  258. }).then(info => {
  259. })
  260. },
  261. getGoods: function () {
  262. const self = this;
  263. self.$showLoading();
  264. self.$request({
  265. url: self.$api.mch.goods,
  266. data: {
  267. page: 1,
  268. mch_id: self.mch_id,
  269. sort: self.sort,
  270. sort_type: self.sort_type,
  271. mch_status: 2,
  272. cat_id: self.cat_id,
  273. }
  274. }).then(info => {
  275. self.$hideLoading();
  276. if (info.code === 0) {
  277. self.goods_list = info.data.list;
  278. }
  279. }).catch(info => {
  280. self.$hideLoading();
  281. })
  282. },
  283. //TODO
  284. changeStyle: function (sort) {
  285. let old_sort = this.sort;
  286. if (old_sort === 3 && sort === 3) {
  287. this.sort_type = this.sort_type ? 0 : 1;
  288. }
  289. this.reset = true;
  290. [this.sort, this.goods_list, this.page, this.args, this.cat_id, this.goods_list] = [sort, [], 1, false, 0,[]];
  291. this.getGoods();
  292. },
  293. tabChange: function (e) {
  294. this.reset = true;
  295. [this.sort, this.tab, this.page, this.args, this.cat_id, this.goods_list] = [e, e, 1, false, 0, []];
  296. this.getGoods();
  297. },
  298. //KfModel
  299. copyInfo() {
  300. this.$utils.uniCopy({
  301. data: this.detail.wechat,
  302. success(){
  303. //#ifndef MP-WEIXIN
  304. uni.showToast({ title: '复制成功'});
  305. // #endif
  306. }
  307. });
  308. },
  309. callPhone() {
  310. uni.makePhoneCall({
  311. phoneNumber: this.detail.store.mobile
  312. })
  313. },
  314. openKfModal() {
  315. this.shopKf = true;
  316. },
  317. closeKfModal() {
  318. this.shopKf = false;
  319. },
  320. formatList: function (oldArray, addArray) {
  321. if (!addArray.length) {
  322. return odlArray;
  323. }
  324. let newList, list;
  325. let end = oldArray.pop();
  326. let start = addArray.shift();
  327. if (end.label === start.label) {
  328. end.goods_list = end.goods_list.concat(start.goods_list);
  329. list = end;
  330. } else {
  331. oldArray = oldArray.concat(end);
  332. list = start;
  333. }
  334. newList = oldArray.concat(list);
  335. newList = newList.concat(addArray);
  336. return newList;
  337. }
  338. }
  339. }
  340. </script>
  341. <style scoped lang="scss">
  342. .shop {
  343. width: 100%;
  344. .shop-head {
  345. height: #{200rpx};
  346. width: 100%;
  347. position: relative;
  348. .tt-bg {
  349. background: rgba(0, 0, 0, .3);
  350. height: 100%;
  351. width: 100%;
  352. position: absolute;
  353. top: 0;
  354. left: 0;
  355. }
  356. .black {
  357. height: 100%;
  358. width: 100%;
  359. }
  360. }
  361. .shop-pic {
  362. height: 100%;
  363. width: 100%;
  364. }
  365. .shop-summary {
  366. position: absolute;
  367. top: #{74rpx};
  368. left: 0;
  369. width: 100%;
  370. color: #FFFFFF;
  371. font-size: #{24rpx};
  372. .icon-pic {
  373. border-radius: #{8rpx};
  374. height: #{80rpx};
  375. width: #{80rpx};
  376. margin: 0 #{24rpx};
  377. display: block;
  378. }
  379. .shop-name {
  380. margin-bottom: #{20rpx};
  381. max-width: #{520rpx};
  382. }
  383. .shop-goods {
  384. font-size: #{24rpx};
  385. }
  386. .shop-goods text:first-child {
  387. margin-right: #{32rpx};
  388. }
  389. .kf {
  390. margin-right: #{50rpx};
  391. .icon-kf {
  392. height: #{40rpx};
  393. width: #{40rpx};
  394. margin-bottom: #{8rpx};
  395. background-image: url("./../image/shop-kf.png");
  396. background-repeat: no-repeat;
  397. background-size: 100% auto;
  398. }
  399. }
  400. }
  401. .shop-tab {
  402. height: #{77rpx};
  403. background: #ffffff;
  404. font-size: #{28rpx};
  405. color: #666666;
  406. border-radius: #{16rpx};
  407. position: relative;
  408. top: #{-18rpx};
  409. margin: 0 #{24rpx} #{-18rpx} #{24rpx};
  410. .shop-search {
  411. width: #{136rpx};
  412. height: #{40rpx};
  413. border-right: 1px solid #E2E2E2;
  414. }
  415. .shop-text-active {
  416. color: #ff4544;
  417. }
  418. .shop-tab-active {
  419. height: #{4rpx};
  420. width: #{30rpx};
  421. border-radius: #{2rpx};
  422. position: absolute;
  423. bottom: #{8rpx};
  424. }
  425. > view {
  426. height: 100%;
  427. }
  428. icon {
  429. height: #{48rpx};
  430. width: #{48rpx};
  431. display: block;
  432. background-size: 100% auto;
  433. background-repeat: no-repeat;
  434. }
  435. .active {
  436. border-bottom: #{1rpx} solid;
  437. }
  438. .icon-search {
  439. height: #{40rpx};
  440. width: #{40rpx};
  441. background-image: url("../image/search.png");
  442. }
  443. .icon-home {
  444. background-image: url("./../image/shop-home.png");
  445. }
  446. .icon-all {
  447. background-image: url("./../image/shop-all.png");
  448. }
  449. .icon-new {
  450. background-image: url("./../image/shop-new.png");
  451. }
  452. .icon-summary {
  453. background-image: url("./../image/shop-summary.png");
  454. }
  455. }
  456. .shop-home {
  457. /*height: #{80rpx};
  458. line-height: #{80rpx};*/
  459. line-height: 1;
  460. padding: #{32rpx} #{24rpx} #{28rpx - 18rpx} #{24rpx};
  461. width: 100%;
  462. font-size: #{28rpx};
  463. color: #353535;
  464. }
  465. .shop-all {
  466. /*height: #{88rpx};*/
  467. font-size: #{26rpx};
  468. line-height: 1;
  469. color: #353535;
  470. padding: #{32rpx} #{25rpx} #{32rpx - 14rpx} #{25rpx};
  471. .icon-cat {
  472. background-repeat: no-repeat;
  473. background-size: 100% 100%;
  474. height: #{20rpx};
  475. width: #{26rpx};
  476. margin-left: #{12rpx};
  477. background-image: url("./../image/shop-cat.png");
  478. }
  479. .active {
  480. color: #ff4544;
  481. }
  482. .icon-price-plus {
  483. background-repeat: no-repeat;
  484. background-size: 100% 100%;
  485. height: #{19rpx};
  486. width: #{12rpx};
  487. margin-left: #{12rpx};
  488. background-image: url("./../image/shop-price-plus.png");
  489. }
  490. .icon-price-less {
  491. background-repeat: no-repeat;
  492. background-size: 100% 100%;
  493. height: #{19rpx};
  494. width: #{12rpx};
  495. margin-left: #{12rpx};
  496. background-image: url("./../image/shop-price-less.png");
  497. }
  498. .icon-price-default {
  499. background-repeat: no-repeat;
  500. background-size: 100% 100%;
  501. height: #{19rpx};
  502. width: #{12rpx};
  503. margin-left: #{12rpx};
  504. background-image: url("../../../static/image/icon/price-sort-default.png");
  505. }
  506. }
  507. .shop-new {
  508. margin-top: #{40rpx};
  509. margin-bottom: #{24rpx};
  510. .line {
  511. height: #{1px};
  512. width: #{260rpx};
  513. margin: 0 #{28rpx};
  514. background: #cdcdcd;
  515. }
  516. .label {
  517. font-size: #{22rpx};
  518. color: #999999;
  519. }
  520. }
  521. }
  522. .act-modal {
  523. position: fixed;
  524. left: 0;
  525. top: 0;
  526. width: 100%;
  527. height: 100%;
  528. z-index: 2001;
  529. transition: 200ms;
  530. .show {
  531. visibility: visible;
  532. opacity: 1;
  533. -webkit-animation-name: fadeIn; /*动画名称*/
  534. -webkit-animation-duration: 0.25s; /*动画持续时间*/
  535. -webkit-animation-iteration-count: 1; /*动画次数*/
  536. -webkit-animation-delay: 0s; /*延迟时间*/
  537. }
  538. .act-modal-bg {
  539. background: rgba(0, 0, 0, 0.5);
  540. position: fixed;
  541. left: 0;
  542. top: 0;
  543. width: 100%;
  544. height: 100%;
  545. z-index: 1;
  546. }
  547. .act-modal-pic {
  548. background: rgba(0, 0, 0, 0.25);
  549. position: fixed;
  550. left: 0;
  551. top: 0;
  552. width: 100%;
  553. height: 100%;
  554. z-index: 1;
  555. }
  556. }
  557. .shop-model {
  558. position: relative;
  559. color: #353535;
  560. width: #{620rpx};
  561. background: #ffffff;
  562. border-radius: #{16rpx};
  563. text-align: center;
  564. > view:last-child {
  565. margin-bottom: #{16rpx};
  566. }
  567. .kf {
  568. margin: #{40rpx} 0;
  569. font-size: #{32rpx};
  570. }
  571. > image {
  572. position: absolute;
  573. right: #{27rpx};
  574. top: #{27rpx};
  575. width: #{35rpx};
  576. height: #{35rpx};
  577. }
  578. .shop-info {
  579. height: #{80rpx};
  580. width: #{360rpx};
  581. margin-bottom: #{24rpx};
  582. border: 1px solid #cdcdcd;
  583. border-radius: #{40rpx};
  584. color: #666666;
  585. font-size: #{28rpx};
  586. }
  587. .shop-info image {
  588. height: #{32rpx};
  589. width: #{32rpx};
  590. margin-right: #{16rpx};
  591. }
  592. }
  593. .shop-tab-1,
  594. .shop-tab-5 {
  595. margin-top: #{120rpx};
  596. }
  597. .shop-tab-1 .shop-tab,
  598. .shop-tab-5 .shop-tab {
  599. position: fixed;
  600. top: 0;
  601. left: 0;
  602. width: 100%;
  603. z-index: 10;
  604. }
  605. .shop-tab-2 {
  606. margin-top: #{95rpx};
  607. }
  608. .shop-tab-2 .shop-all {
  609. position: fixed;
  610. top: 0;
  611. left: 0;
  612. width: 100%;
  613. z-index: 10;
  614. border-bottom: #{1rpx} solid #e3e3e3;
  615. }
  616. .icon-default {
  617. background-color: #666666;
  618. }
  619. </style>