1
0

quick-shop.vue 17 KB

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