quick-shop.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. <template>
  2. <app-layout>
  3. <view class="app-quick-shop dir-left-nowrap">
  4. <view class="app-left" :style="{height: `calc(100% - 136rpx - ${tabbarbool ? botHeight : 0}rpx)`}">
  5. <scroll-view scroll-y class="app-quick-scroll">
  6. <view class="app-text" v-for="(item, index) in classification" :class="{'app-active-bk': activeIndex === index}" :key="index">
  7. <app-form-id @click="active(item,index)">
  8. <text class="app-text-text">{{item.name}}</text>
  9. </app-form-id>
  10. </view>
  11. </scroll-view>
  12. <view class="app-cart">
  13. <view class="app-icon image-no-rep image-cover" @click="pushSelectProduct()">
  14. <app-jump-button form url="/pages/cart/cart">
  15. <text class="app-active-num"
  16. :style="{'background-color': getTheme.background}"
  17. v-if="activeNum !== '0' || activeNum === 0"
  18. >{{activeNum}}</text>
  19. </app-jump-button>
  20. </view>
  21. </view>
  22. </view>
  23. <view class="app-right" :style="{height: `calc(100% - ${tabbarbool ? botHeight : 0}rpx)`}">
  24. <text class="app-active-name">{{activeName}}</text>
  25. <scroll-view scroll-y class="app-scroll-right"
  26. :style="{height: `calc(100% - 102rpx)`}"
  27. :scroll-top="scrollTop" @scrolltolower="scrolltolower" >
  28. <view class="app-request">
  29. <view class="app-item-item" v-for="(item, index) in list" :key="index" >
  30. <app-form-id >
  31. <view class="app-item dir-left-nowrap cross-top" >
  32. <image class="app-image" lazy-load :src="item.cover_pic" @click.stop="jumpGo(item)"></image>
  33. <view class="out-dialog" v-if="item.goods_num === 0 && appSetting.is_show_stock === 1 ">
  34. <image :src="appSetting.is_use_stock == '1' ? appImg.plugins_out : appSetting.sell_out_pic"></image>
  35. </view>
  36. <view class="app-content dir-top-nowrap main-left">
  37. <view class="app-top" @click.stop="jumpGo(item)">
  38. {{item.name}}
  39. </view>
  40. <view class="app-volume">
  41. 销量 {{item.virtual_sales}}
  42. </view>
  43. <view class="dir-top-nowrap" style="padding: 10rpx 0;">
  44. <view v-if="item.is_level === 1">
  45. <app-member-price :theme="getTheme" :price="item.level_price"></app-member-price>
  46. </view>
  47. <app-sup-vip :is_vip_card_user="item.vip_card_appoint.is_vip_card_user" margin="4rpx 0 0" v-if="item.vip_card_appoint.discount" :discount="item.vip_card_appoint.discount"></app-sup-vip>
  48. <view class="app-bottom dir-left-nowrap main-between">
  49. <view>
  50. <view class="app-price" :style="{'color': getTheme.color}">
  51. <text class="app-symbol">¥</text>
  52. {{item.price}}
  53. </view>
  54. <view class="origin-price" v-if="isListUnderlinePrice == 1">
  55. ¥{{item.original_price}}
  56. </view>
  57. </view>
  58. <app-add-subtract :item="item" v-if="item.use_attr === 0 && item.goods_num > 0" :theme="getTheme" @changeNum="changeNum" @subtract="subtract" @add="add" :total_num="item.total_num" ></app-add-subtract>
  59. <view class="app-button" v-if="item.use_attr === 1 && item.goods_num > 0">
  60. <view @click="specification(item)" class="but" :style="{'background-color': getTheme.background}">选规格</view>
  61. </view>
  62. <view
  63. v-if="item.use_attr === 1 && item.total_num !== 0"
  64. :style="{'color': getTheme.color}"
  65. class="app-num"
  66. >
  67. {{item.total_num}}
  68. </view>
  69. </view>
  70. </view>
  71. </view>
  72. </view>
  73. </app-form-id>
  74. </view>
  75. </view>
  76. </scroll-view>
  77. </view>
  78. <u-attr
  79. v-if="item.use_attr === 1"
  80. v-model="show"
  81. :goods="item"
  82. :checked="checked"
  83. :theme="getTheme"
  84. @check="onAttr"
  85. @cart="selectNumber"
  86. ></u-attr>
  87. </view>
  88. </app-layout>
  89. </template>
  90. <script>
  91. import { mapState, mapGetters } from 'vuex';
  92. import appAddSubtract from './components/app-add-subtract/app-add-subtract.vue';
  93. import appAttr from '../../components/page-component/app-attr/app-attr.vue';
  94. import uAttr from '../../components/page-component/goods/u-attr.vue';
  95. export default {
  96. name: 'quick-shop',
  97. components: {
  98. 'app-add-subtract': appAddSubtract,
  99. 'app-attr': appAttr,
  100. uAttr
  101. },
  102. computed: {
  103. ...mapState({
  104. tabBarNavs: state => state.mallConfig.navbar.navs,
  105. appSetting: state => state.mallConfig.mall.setting,
  106. appImg: state => state.mallConfig.__wxapp_img.mall,
  107. isListUnderlinePrice: state => state.mallConfig.mall.setting.is_list_underline_price,
  108. platform: function(state) {
  109. return state.gConfig.systemInfo.platform;
  110. }
  111. }),
  112. ...mapGetters('iPhoneX',{
  113. botHeight: 'getBotHeight',
  114. }),
  115. ...mapGetters('mallConfig',{
  116. getTheme: 'getTheme',
  117. getVideo: 'getVideo'
  118. })
  119. },
  120. data() {
  121. return {
  122. activeNum: '',
  123. classification: [],
  124. activeIndex: 0,
  125. activeName: '',
  126. list: [],
  127. coverPic: '',
  128. spec: true,
  129. goodsNum: 0,
  130. item: {
  131. use_attr: 0
  132. },
  133. selectAttr: {},
  134. checked: null,
  135. show: false,
  136. page: 1,
  137. over: false,
  138. tabbarbool: false,
  139. currentRoute: this.$platDiff.route(),
  140. activeId: '0',
  141. scrollTop: 0,
  142. old: {
  143. scrollTop: 0
  144. }
  145. }
  146. },
  147. methods: {
  148. onAttr({item}) {
  149. this.checked = item;
  150. },
  151. request() {
  152. this.$request({
  153. url: `${this.$api.quick.goods_list}&page=${this.page}&cat_id=${this.activeId}is_sell_well=0 `,
  154. }).then(res => {
  155. if (res.code === 0) {
  156. if (res.data.list.length > 0) {
  157. this.list = [...this.list, ...res.data.list];
  158. } else {
  159. this.over = true;
  160. }
  161. }
  162. });
  163. },
  164. active(item, index) {
  165. this.scrollTop = 1;
  166. this.$nextTick(() => {
  167. this.scrollTop = 0
  168. });
  169. this.activeIndex = index;
  170. this.activeName = item.name;
  171. this.activeId = item.id;
  172. this.over = false;
  173. this.page = 1;
  174. this.pushSelectProduct().then(() => {
  175. this.$request({
  176. url: `${this.$api.quick.goods_list}&page=${this.page}&cat_id=${item.id}is_sell_well=0 `,
  177. }).then(res => {
  178. this.list = res.data.list;
  179. });
  180. });
  181. },
  182. specification(item) {
  183. this.checked = null;
  184. this.item = item;
  185. this.show = true;
  186. },
  187. selectNumber(checked, number) {
  188. for (let i = 0; i < this.list.length; i++) {
  189. if (this.list[i].id === checked.goods_id) {
  190. this.list[i].total_num += number;
  191. this.activeNum = Number(this.activeNum) + Number(number);
  192. }
  193. }
  194. },
  195. async pushSelectProduct() {
  196. let list = [];
  197. for (let key in this.selectAttr) {
  198. list.push(this.selectAttr[key]);
  199. }
  200. this.$request({
  201. url: this.$api.quick.cart,
  202. method: 'post',
  203. data: {
  204. list: JSON.stringify(list),
  205. }
  206. })
  207. },
  208. add(item) {
  209. for (let i = 0; i < this.list.length; i++) {
  210. if (this.list[i].id === item.id) {
  211. this.list[i].total_num += 1;
  212. this.activeNum = Number(this.activeNum) + 1;
  213. this.selectAttr[item.attr[0].id] = {
  214. attr: item.attr[0].id,
  215. num: this.list[i].total_num,
  216. goods_id: item.id,
  217. };
  218. }
  219. }
  220. },
  221. subtract(item) {
  222. for (let i = 0; i < this.list.length; i++) {
  223. if (this.list[i].id === item.id) {
  224. this.list[i].total_num -= 1;
  225. this.activeNum = Number(this.activeNum) - 1;
  226. this.selectAttr[item.attr[0].id] = {
  227. attr: item.attr[0].id,
  228. num: this.list[i].total_num,
  229. goods_id: item.id,
  230. };
  231. }
  232. }
  233. },
  234. changeNum(item, data) {
  235. for (let i = 0; i < this.list.length; i++) {
  236. if (this.list[i].id === item.id) {
  237. this.activeNum = Number(this.activeNum) - this.list[i].total_num;
  238. this.activeNum = Number(this.activeNum) + data;
  239. this.list[i].total_num = data;
  240. this.selectAttr[item.attr[0].id] = {
  241. attr: item.attr[0].id,
  242. num: this.list[i].total_num,
  243. goods_id: item.id,
  244. };
  245. }
  246. }
  247. },
  248. jumpGo(data) {
  249. // #ifndef MP-BAIDU
  250. if (data.video_url && this.getVideo == 1) {
  251. // #ifdef MP
  252. uni.navigateTo({
  253. url: `/pages/goods/video?goods_id=${data.id}`
  254. });
  255. // #endif
  256. // #ifdef H5
  257. uni.navigateTo({
  258. url: `/pages/goods/goods?id=${data.id}`
  259. });
  260. // #endif
  261. } else {
  262. uni.navigateTo({
  263. url: `/pages/goods/goods?id=${data.id}`
  264. });
  265. }
  266. // #endif
  267. // #ifdef MP-BAIDU
  268. uni.navigateTo({
  269. url: `/pages/goods/goods?id=${data.id}`
  270. });
  271. // #endif
  272. },
  273. scrolltolower() {
  274. if (!this.over) {
  275. this.page++;
  276. this.request();
  277. }
  278. },
  279. b() {
  280. let currentRoute = this.currentRoute;
  281. for (let i = 0; i < this.tabBarNavs.length; i++) {
  282. if(currentRoute.includes(this.tabBarNavs[i].url.split('?')[0])) {
  283. return this.tabbarbool = true;
  284. }
  285. }
  286. return this.tabbarbool = false;
  287. },
  288. },
  289. onLoad() { this.$commonLoad.onload();
  290. this.$request({
  291. url: this.$api.quick.index
  292. }).then(response => {
  293. this.activeNum = `${response.data.count}`;
  294. let {name, id} = response.data.cats_list[this.activeIndex];
  295. this.activeName = name;
  296. this.activeId = id;
  297. this.classification = response.data.cats_list;
  298. this.$request({
  299. url: this.$api.quick.index,
  300. }).then(response => {
  301. this.activeNum = `${response.data.count}`;
  302. });
  303. this.$request({
  304. url: `${this.$api.quick.goods_list}&page=${this.page}&cat_id=${id}is_sell_well=0 `,
  305. }).then(response => {
  306. this.list = response.data.list;
  307. })
  308. })
  309. },
  310. onHide() {
  311. this.pushSelectProduct();
  312. },
  313. onUnload() {
  314. this.pushSelectProduct();
  315. },
  316. // #ifdef MP
  317. onShareAppMessage() {
  318. return this.$shareAppMessage({
  319. path: '/pages/quick-shop/quick-shop',
  320. title: this.$children[0].navigationBarTitle,
  321. });
  322. },
  323. // #endif
  324. watch: {
  325. tabBarNavs: {
  326. handler: function() {
  327. this.b();
  328. },
  329. immediate: true,
  330. }
  331. }
  332. }
  333. </script>
  334. <style scoped lang="scss">
  335. .app-quick-shop {
  336. position: absolute;
  337. height: 100%;
  338. width: $screen-width;
  339. .app-left {
  340. width: #{160rpx};
  341. .app-quick-scroll {
  342. width: 100%;
  343. height: 100%;
  344. background-color: #f3f3f3;
  345. .app-text {
  346. background-color: #f3f3f3;
  347. width: 100%;
  348. height: #{104rpx};
  349. line-height: #{104rpx};
  350. font-size: #{26rpx};
  351. color: #353535;
  352. .app-text-text {
  353. text-align: center;
  354. word-break: break-all;
  355. text-overflow: ellipsis;
  356. display: -webkit-box;
  357. -webkit-box-orient: vertical;
  358. -webkit-line-clamp: 1;
  359. overflow: hidden;
  360. }
  361. }
  362. .app-active-bk {
  363. background-color:white;
  364. }
  365. }
  366. .app-cart {
  367. width: #{160rpx};
  368. height: #{136rpx};
  369. background-color: #f3f3f3;
  370. .app-icon {
  371. width: #{96rpx};
  372. height: #{96rpx};
  373. margin: 0 #{32rpx} #{40rpx} #{32rpx};
  374. border-radius: 50%;
  375. box-shadow: #{0.1rpx} #{0.1rpx} #{5rpx} rgba(0,0,0,0.1);
  376. background-image: url("./image/cart-big.png");
  377. position: relative;
  378. }
  379. .app-active-num {
  380. position: absolute;
  381. top: #{26rpx};
  382. right: #{10rpx};
  383. border-radius: #{12rpx};
  384. font-size: #{18rpx};
  385. height: #{24rpx};
  386. line-height: #{24rpx};
  387. color: #FFFFFF;
  388. padding: 0 #{8rpx};
  389. }
  390. }
  391. }
  392. .app-right {
  393. width: calc(100% - #{160rpx});
  394. background-color: #ffffff;
  395. .app-active-name {
  396. display: inline-block;
  397. width: 100%;
  398. padding-top: #{40rpx};
  399. padding-bottom: #{36rpx};
  400. font-size: #{26rpx};
  401. color: #8c8c8c;
  402. padding-left: #{22rpx};
  403. }
  404. .app-scroll-right {
  405. .app-request {
  406. padding-top: #{1rpx};
  407. }
  408. .app-item-item {
  409. width: calc(100% - #{22rpx});
  410. margin-left: #{22rpx};
  411. margin-top: #{23rpx};
  412. }
  413. }
  414. .app-item {
  415. width: calc(100% - #{22rpx});
  416. border-bottom: #{1rpx} solid #e2e2e2;
  417. position: relative;
  418. .out-dialog {
  419. width: #{152rpx};
  420. height: #{152rpx};
  421. position: absolute;
  422. top: 0;
  423. left: 0;
  424. z-index: 10;
  425. background-color: rgba(0,0,0,.5);
  426. image {
  427. width: #{152rpx};
  428. height: #{152rpx};
  429. }
  430. }
  431. .app-image {
  432. height: #{152rpx};
  433. width: #{152rpx};
  434. margin-right: #{20rpx};
  435. }
  436. .app-content {
  437. width: calc(100% - #{192rpx} );
  438. min-height: #{152rpx};
  439. background-color: white;
  440. .app-top {
  441. width: 100%;
  442. padding-top: #{10rpx};
  443. font-size: #{28rpx};
  444. color: #353535;
  445. word-break: break-all;
  446. text-overflow: ellipsis;
  447. display: -webkit-box;
  448. -webkit-box-orient: vertical;
  449. -webkit-line-clamp: 2;
  450. overflow: hidden;
  451. }
  452. .app-volume {
  453. font-size: #{22rpx};
  454. color: #666666;
  455. margin-bottom: 2rpx;
  456. }
  457. .app-bottom {
  458. width: 100%;
  459. padding-bottom: #{16rpx};
  460. position: relative;
  461. .app-button {
  462. height: #{44rpx};
  463. }
  464. /deep/ button {
  465. text-align: center;
  466. width: #{104rpx};
  467. line-height: #{44rpx};
  468. }
  469. .app-price {
  470. font-size: #{28rpx};
  471. .app-symbol {
  472. font-size: #{18rpx};
  473. }
  474. }
  475. .app-num {
  476. position: absolute;
  477. background-color: white;
  478. border: #{1rpx} solid;
  479. border-radius: #{12rpx};
  480. height: #{24rpx};
  481. padding: 0 #{6rpx};
  482. top: #{-14rpx};
  483. right: #{15rpx};
  484. font-size: #{18rpx};
  485. line-height: #{24rpx};
  486. }
  487. }
  488. }
  489. }
  490. }
  491. }
  492. .but {
  493. height: #{44upx};
  494. line-height: #{44upx};
  495. padding: #{0 16upx};
  496. border-radius: #{22upx};
  497. font-size: #{24upx};
  498. color: #ffffff;
  499. }
  500. .origin-price {
  501. font-size: 21upx;
  502. color: #999999;
  503. text-decoration:line-through;
  504. }
  505. </style>