template4.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. <template>
  2. <view class="bg--w111-000" :class="tempArr.length?'':'h-screen'">
  3. <view class="fixed-lt w-full bg_mask z-900" :style="{ paddingTop: statusBarHeight + 'px',height: 106 + statusBarHeight + 'px'}">
  4. <view class="px-20 h-80 flex mt-12 text--w111-999">
  5. <view class="w-162 h-58 rd-30rpx bg--w111-f5f5f5 flex-center fs-32">
  6. <image class="w-32 h-32" src="@/static/img/drop_more.png" @tap="openDrower()"></image>
  7. <text class="text--w111-b3b3b3 px-16">|</text>
  8. <image class="w-32 h-32" src="@/static/img/cart_icon.png" @tap="goCart()"></image>
  9. </view>
  10. <view class="flex-1 h-58 rd-30rpx bg--w111-f5f5f5 ml-14 px-32 flex-y-center" @tap="goSearch">
  11. <text class="iconfont icon-ic_search fs-28"></text>
  12. <text class="fs-24 pl-18">请输入商品名称</text>
  13. </view>
  14. <!-- 胶囊占据的位置 -->
  15. <!-- #ifdef MP -->
  16. <view class="ml-12" :style="'width:'+getHeight.barWidth+'px'"></view>
  17. <!-- #endif -->
  18. </view>
  19. </view>
  20. <!-- #ifdef MP || APP-PLUS -->
  21. <view :style="{'height': statusBarHeight + 'px'}"></view>
  22. <view class="px-20 p-b-20">
  23. <!-- #endif -->
  24. <!-- #ifndef MP -->
  25. <view class="p-20">
  26. <!-- #endif -->
  27. <view class="rd-24rpx pro_card" v-for="(item,index) in tempArr" :key="index"
  28. @click="goDetail(item)">
  29. <easy-loadimage
  30. :image-src="item.image"
  31. :borderSrc="item.activity_frame.image"
  32. width="100%"
  33. height="710rpx"
  34. borderRadius="24rpx 24rpx 0 0"></easy-loadimage>
  35. <view class="rd-b-24rpx bg--w111-fff p-24">
  36. <view class="flex-between-center">
  37. <view class="acea-row row-bottom">
  38. <baseMoney :money="item.price" symbolSize="36" integerSize="52" decimalSize="36"
  39. weight></baseMoney>
  40. <view class="inline-block h-26 lh-28rpx rd-14rpx bg--w111-F7E9CD fs-22 ml-8 mb-10" v-if="item.vip_price && item.vip_price > 0">
  41. <text class="inline-block h-26 lh-28rpx svip_rd fs-18 bg--w111-484643 text--w111-FDDAA4 px-8">SVIP</text>
  42. <text class="px-8 SemiBold">¥{{item.vip_price}}</text>
  43. </view>
  44. </view>
  45. <view class="fs-24 lh-34rpx text--w111-999">{{item.sales}}人都在买</view>
  46. </view>
  47. <view class="flex-between-center mt-24">
  48. <view class="w-422 lh-40rpx fs-28 text--w111-333 fw-500 line2">{{item.store_name}}
  49. </view>
  50. <view class="flex" v-if="item.cart_button">
  51. <view class="w-88 h-64 rd-l-32rpx bg-primary-light flex-center"
  52. @click.stop="goCartDuo(item)" v-if="item.spec_type">
  53. <text class="iconfont icon-ic_ShoppingCart1 fs-40 text-primary-con"></text>
  54. </view>
  55. <view class="w-88 h-64 rd-l-32rpx bg-primary-light flex-center"
  56. @click.stop="goCartDan(item,index)" v-else>
  57. <text class="iconfont icon-ic_ShoppingCart1 fs-40 text-primary-con"></text>
  58. </view>
  59. <view class="w-112 h-64 rd-r-32rpx bg-color flex-center text--w111-fff fs-24">购买</view>
  60. </view>
  61. <view class="w-112 h-64 rd-32rpx bg-color flex-center text--w111-fff fs-24" v-else>购买</view>
  62. </view>
  63. </view>
  64. </view>
  65. <view class="mt-100rpx" v-if="!tempArr.length && !loading">
  66. <emptyPage title="暂无商品,去看点别的吧~" ></emptyPage>
  67. </view>
  68. <view :style="[conHeights]" class="55"></view>
  69. </view>
  70. <base-drawer mode="right"
  71. :visible="showFilterDrawer"
  72. background-color="transparent"
  73. mask maskClosable
  74. @close="closeDrawer">
  75. <view class="drawer_box bg--w111-fff h-full">
  76. <view :style="{height:fixedTop + 'px'}"></view>
  77. <view class="h-80 flex-center fs-34 fw-500 text--w111-333">筛选</view>
  78. <view class="list" :style="[listH]">
  79. <scroll-view scroll-y="true" style="height: 100%">
  80. <view v-if="level == 3">
  81. <view class="flex">
  82. <scroll-view scroll-x="true" class="white-nowrap vertical-middle w-full pl-20 pt-24 pb-24"
  83. show-scrollbar="false">
  84. <view class="inline-block mr-8" v-for="(item,index) in categoryList" :key="index"
  85. @click="tapNav(index,item)">
  86. <view class="flex-col flex-center">
  87. <view :class="index == navActive ? 'active_pic' : 'scroll_pic'">
  88. <image :src="item.pic" mode="aspectFill"></image>
  89. </view>
  90. <view class="w-120 h-40 flex-center fs-24 text--w111-333"
  91. :class="index == navActive ? 'active_cate_text' : ''">{{item.cate_name}}
  92. </view>
  93. </view>
  94. </view>
  95. </scroll-view>
  96. </view>
  97. <view v-for="(item,index) in categoryErList" :key="index">
  98. <view class="activity_box pt-24 pb-24 pl-32 pr-32"
  99. v-if="item.children && item.children.length">
  100. <view class="flex-between-center">
  101. <view class="fs-28 text--w111-333 fw-500">{{item.cate_name}}</view>
  102. <view class="fs-20 text--w111-999" v-if="item.children && item.children.length > 3"
  103. @tap="openShowMore(item)">
  104. <text>{{item.showMore ? '收起' : '展开'}}</text>
  105. <text class="iconfont fs-20" :class="item.showMore ? 'icon-ic_uparrow' : 'icon-ic_downarrow'"></text>
  106. </view>
  107. </view>
  108. <view class="grid-column-3 box_gap mt-24" v-show="item.showMore">
  109. <view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
  110. v-for="cate in item.children" :key="cate.id"
  111. :class="tid == cate.id ? 'cate_active' : ''" @tap="threeCateClick(cate)">
  112. {{cate.cate_name}}</view>
  113. </view>
  114. <view class="grid-column-3 box_gap mt-24" v-show="!item.showMore">
  115. <view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
  116. v-for="cate in sliceArr(item.children)" :key="cate.id"
  117. :class="tid == cate.id ? 'cate_active' : ''" @tap="threeCateClick(cate)">
  118. {{cate.cate_name}}</view>
  119. </view>
  120. </view>
  121. </view>
  122. </view>
  123. <view v-else>
  124. <view v-for="(item,index) in categoryList" :key="index">
  125. <view class="activity_box pt-24 pb-24 pl-32 pr-32">
  126. <view class="flex-between-center">
  127. <view class="fs-28 text--w111-333 fw-500">{{item.cate_name}}</view>
  128. <view class="fs-20 text--w111-999" v-if="item.children && item.children.length > 3"
  129. @tap="openShowMore(item)">
  130. <text>{{item.showMore ? '收起' : '展开'}}</text>
  131. <text class="iconfont fs-20" :class="item.showMore ? 'icon-ic_uparrow' : 'icon-ic_downarrow'"></text>
  132. </view>
  133. </view>
  134. <view v-if="item.children && item.children.length">
  135. <view class="grid-column-3 box_gap mt-24" v-show="item.showMore">
  136. <view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
  137. v-for="cate in item.children" :key="cate.id"
  138. :class="sid == cate.id ? 'cate_active' : ''" @tap="twoCateClick(cate)">
  139. {{cate.cate_name}}</view>
  140. </view>
  141. <view class="grid-column-3 box_gap mt-24" v-show="!item.showMore">
  142. <view class="h-56 rd-28rpx bg--w111-f5f5f5 flex-center fs-24 text--w111-333"
  143. v-for="cate in sliceArr(item.children)" :key="cate.id"
  144. :class="sid == cate.id ? 'cate_active' : ''" @tap="twoCateClick(cate)">
  145. {{cate.cate_name}}</view>
  146. </view>
  147. </view>
  148. </view>
  149. </view>
  150. </view>
  151. </scroll-view>
  152. </view>
  153. <view class="fixed-lb pb-safe bg--w111-fff w-full rd-b-40">
  154. <view class="px-32 flex-between-center h-112">
  155. <view class="w-296 h-72 rd-40rpx flex-center text-primary-con con_border bg--w111-fff"
  156. @click="reset">重置</view>
  157. <view class="w-296 h-72 rd-40rpx flex-center text--w111-fff bg-color" @tap="getList">
  158. 确定</view>
  159. </view>
  160. </view>
  161. </view>
  162. </base-drawer>
  163. <productWindow
  164. :attr="attr"
  165. :isShow='1'
  166. :iSplus='1'
  167. :iScart='1'
  168. :is_vip="is_vip"
  169. :type="2"
  170. @myevent="onMyEvent"
  171. @ChangeAttr="ChangeAttr"
  172. @ChangeCartNum="ChangeCartNumDuo"
  173. @attrVal="attrVal"
  174. @iptCartNum="iptCartNum"
  175. @goCat="goCatNum"
  176. @getImg="showImg"
  177. id='product-window' ></productWindow>
  178. <cusPreviewImg ref="cusPreviewImg" :list="skuArr" @changeSwitch="changeSwitch"></cusPreviewImg>
  179. </view>
  180. </view>
  181. </template>
  182. <script>
  183. let sysHeight = uni.getSystemInfoSync().statusBarHeight;
  184. import baseDrawer from '@/components/tui-drawer/tui-drawer.vue';
  185. import productWindow from '@/components/productWindow';
  186. import {
  187. getCategoryList,
  188. getProductslist,
  189. getAttr,
  190. postCartNum
  191. } from '@/api/store.js';
  192. import {goShopDetail} from '@/libs/order.js';
  193. import {toLogin} from '@/libs/login.js';
  194. import {mapState,mapGetters} from 'vuex';
  195. import skuSelect from '@/mixins/skuSelect.js';
  196. import emptyPage from '@/components/emptyPage.vue';
  197. import cusPreviewImg from '@/components/cusPreviewImg';
  198. export default {
  199. props: {
  200. level: {
  201. type: Number,
  202. default: 2
  203. },
  204. isFooter:{
  205. type:Boolean,
  206. default:false
  207. },
  208. pdHeight:{
  209. type:Number,
  210. default:0
  211. }
  212. },
  213. data() {
  214. return {
  215. statusBarHeight: sysHeight,
  216. showFilterDrawer: false,
  217. navActive: 0,
  218. categoryList: [],
  219. categoryErList: [],
  220. threeCateList: [],
  221. tempArr: [],
  222. loading: false,
  223. loadend: false,
  224. loadTitle: '加载更多',
  225. page: 1,
  226. limit: 10,
  227. cid: 0, //一级分类
  228. sid: 0, //二级分类
  229. tid: 0, //二级分类
  230. id: 0, //商品id
  231. storeName: '',
  232. tabClick: 0,
  233. attr: {
  234. cartAttr: false,
  235. productAttr: [],
  236. productSelect: {}
  237. },
  238. attrValue: '', //已选属性
  239. productValue: [],
  240. is_vip: 0, //是否是会员
  241. cart_num: 0,
  242. storeInfo: {},
  243. selectSku: {},
  244. skuArr: [],
  245. getHeight: this.$util.getWXStatusHeight()
  246. }
  247. },
  248. mixins: [skuSelect],
  249. components: {
  250. baseDrawer,
  251. productWindow,
  252. emptyPage,
  253. cusPreviewImg
  254. },
  255. computed: {
  256. fixedTop() {
  257. // #ifdef MP || APP-PLUS
  258. return uni.getSystemInfoSync().statusBarHeight
  259. // #endif
  260. // #ifdef H5
  261. return 20
  262. // #endif
  263. },
  264. ...mapGetters(['isLogin', 'uid', 'cartNum']),
  265. conHeights(){
  266. let H = `${this.pdHeight*2+104}rpx`
  267. let HZ = `calc(100% - env(safe-area-inset-bottom))`
  268. return{
  269. height: this.isFooter?H:HZ
  270. }
  271. },
  272. listH(){
  273. let H = `calc(100% - (${this.fixedTop + 96}px + env(safe-area-inset-bottom)))`
  274. return{
  275. height: H
  276. }
  277. }
  278. },
  279. watch:{
  280. cartNum(){
  281. this.getCartList(1);
  282. }
  283. },
  284. mounted() {
  285. this.getAllCategory();
  286. },
  287. methods: {
  288. // 商品详情接口;
  289. getAttrs(id) {
  290. let that = this;
  291. getAttr(id, 0).then(res => {
  292. // uni.hideLoading();
  293. that.$set(that.attr, 'productAttr', res.data.productAttr);
  294. that.$set(that, 'productValue', res.data.productValue);
  295. that.$set(that, 'is_vip', res.data.storeInfo.is_vip);
  296. that.$set(that, 'storeInfo', res.data.storeInfo);
  297. that.skuArr = [];
  298. for (let key in res.data.productValue) {
  299. let obj = res.data.productValue[key];
  300. that.skuArr.push(obj)
  301. }
  302. if (!that.skuArr.length) {
  303. that.skuArr = [{
  304. image: this.storeInfo.image,
  305. suk: this.storeInfo.store_name,
  306. price: this.storeInfo.price
  307. }];
  308. }
  309. this.$set(this, "selectSku", that.skuArr[0]);
  310. that.DefaultSelect();
  311. })
  312. },
  313. //点击sku图片打开轮播图
  314. showImg(index) {
  315. this.$refs.cusPreviewImg.open(this.selectSku.suk)
  316. },
  317. //滑动轮播图选择商品
  318. changeSwitch(e) {
  319. let productSelect = this.skuArr[e];
  320. this.$set(this, 'selectSku', productSelect);
  321. var skuList = productSelect.suk.split(',');
  322. skuList.forEach((i, index) => {
  323. this.$set(this.attr.productAttr[index], 'index', skuList[index]);
  324. })
  325. if (productSelect) {
  326. this.$set(this.attr.productSelect, 'image', productSelect.image);
  327. this.$set(this.attr.productSelect, 'price', productSelect.price);
  328. this.$set(this.attr.productSelect, 'stock', productSelect.stock);
  329. this.$set(this.attr.productSelect, 'unique', productSelect.unique);
  330. this.$set(this.attr.productSelect, 'cart_num', 1);
  331. this.$set(this.attr.productSelect, 'vip_price', productSelect.vip_price);
  332. this.$set(this, 'attrValue', productSelect.suk);
  333. this.$set(this, 'attrTxt', '已选择');
  334. }
  335. },
  336. getAllCategory() {
  337. let that = this;
  338. getCategoryList().then(res => {
  339. if (!res.data.length) return
  340. res.data.map(item=>{
  341. this.$set(item,'showMore',false);
  342. if(item.children && item.children.length){
  343. item.children.map(item1=>{
  344. this.$set(item1,'showMore',false);
  345. })
  346. }
  347. })
  348. let data = res.data;
  349. that.categoryTitle = data[0].cate_name;
  350. that.cid = data[0].id;
  351. that.sid = 0;
  352. that.tid = 0;
  353. that.navActive = 0;
  354. that.tabClick = 0;
  355. that.categoryList = data;
  356. that.categoryErList = res.data[0].children ? res.data[0].children : [];
  357. that.page = 1;
  358. that.loadend = false;
  359. that.tempArr = [];
  360. that.productslist();
  361. })
  362. },
  363. // 产品列表
  364. productslist() {
  365. let that = this;
  366. if (that.loadend) return;
  367. if (that.loading) return;
  368. that.loading = true;
  369. that.loadTitle = '';
  370. getProductslist({
  371. page: that.page,
  372. limit: that.limit,
  373. type: 1,
  374. cid: that.cid,
  375. sid: that.sid,
  376. tid: that.tid
  377. }).then(res => {
  378. let list = res.data,
  379. loadend = list.length < that.limit;
  380. that.tempArr = that.$util.SplitArray(list, that.tempArr);
  381. that.$set(that, 'tempArr', that.tempArr);
  382. that.loading = false;
  383. that.loadend = loadend;
  384. that.loadTitle = loadend ? "没有更多内容啦~" : "加载更多";
  385. that.page = that.page + 1;
  386. }).catch(err => {
  387. that.loading = false;
  388. that.loadTitle = '加载更多'
  389. });
  390. },
  391. tapNav(index, item) {
  392. let list = this.categoryList[index];
  393. this.navActive = index;
  394. this.categoryTitle = list.cate_name;
  395. this.categoryErList = item.children ? item.children : [];
  396. this.threeCateList = item.children[0].children ? item.children[0].children : [];
  397. this.tabClick = 0;
  398. this.tabLeft = 0;
  399. this.cid = list.id;
  400. this.sid = 0;
  401. this.tid = 0;
  402. },
  403. threeCateClick(item) {
  404. this.tid = item.id;
  405. },
  406. twoCateClick(item){
  407. this.sid = item.id;
  408. },
  409. openShowMore(item){
  410. item.showMore = !item.showMore;
  411. },
  412. getList() {
  413. this.page = 1;
  414. this.loadend = false;
  415. this.tempArr = [];
  416. this.productslist();
  417. this.showFilterDrawer = false;
  418. if(this.isFooter){
  419. this.$emit('toggleBar',true);
  420. }else{
  421. uni.showTabBar();
  422. }
  423. },
  424. reset() {
  425. this.cid = this.categoryList[0].id;
  426. this.sid = 0;
  427. this.tid = 0;
  428. this.navActive = 0;
  429. this.categoryErList = this.categoryList[0].children ? this.categoryList[0].children : [];
  430. },
  431. // 去详情页
  432. goDetail(item) {
  433. goShopDetail(item, this.uid).catch(res => {
  434. uni.navigateTo({
  435. url: `/pages/goods_details/index?id=${item.id}&fromType=1`
  436. });
  437. });
  438. },
  439. goSearch() {
  440. uni.navigateTo({
  441. url: '/pages/goods/goods_search/index'
  442. })
  443. },
  444. goCart(){
  445. uni.switchTab({
  446. url: '/pages/order_addcart/order_addcart'
  447. })
  448. },
  449. openDrower() {
  450. this.showFilterDrawer = true;
  451. if(this.isFooter){
  452. this.$emit('toggleBar',false);
  453. }else{
  454. uni.hideTabBar();
  455. }
  456. },
  457. closeDrawer() {
  458. this.showFilterDrawer = false;
  459. if(this.isFooter){
  460. this.$emit('toggleBar',true);
  461. }else{
  462. uni.showTabBar();
  463. }
  464. },
  465. sliceArr(arr){
  466. return arr.slice(0,3)
  467. }
  468. },
  469. }
  470. </script>
  471. <style lang="scss" scoped>
  472. .bg_mask {
  473. background: linear-gradient(180deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0) 100%);
  474. }
  475. .list{
  476. overflow: auto;
  477. }
  478. .z-900 {
  479. z-index: 900;
  480. }
  481. .pro_card~.pro_card {
  482. margin-top: 20rpx;
  483. }
  484. .drawer_box {
  485. width: 668rpx;
  486. border-radius: 40rpx 0 0 40rpx;
  487. overflow: auto;
  488. }
  489. .bg--w111-484643{
  490. background: linear-gradient(90deg, #484643 0%, #1F1B17 100%);
  491. }
  492. .text--w111-FDDAA4{
  493. color: #FDDAA4;
  494. }
  495. .svip_rd{
  496. border-radius: 14rpx 0 8rpx 14rpx;
  497. }
  498. .box_gap {
  499. grid-row-gap: 24rpx;
  500. grid-column-gap: 26rpx;
  501. }
  502. .con_border {
  503. border: 1px solid var(--view-theme);
  504. }
  505. .text-primary-con {
  506. color: var(--view-theme);
  507. }
  508. .bg-primary-light {
  509. background: var(--view-minorColorT);
  510. }
  511. .p-b-20 {
  512. padding-bottom: 20rpx !important;
  513. }
  514. .w-598 {
  515. width: 598rpx;
  516. }
  517. .active_pic {
  518. width: 104rpx;
  519. height: 104rpx;
  520. background-color: #fff;
  521. padding: 3rpx;
  522. border-radius: 50%;
  523. border: 3rpx solid var(--view-theme);
  524. image {
  525. width: 100%;
  526. height: 100%;
  527. border-radius: 50%;
  528. }
  529. }
  530. .scroll_pic {
  531. image {
  532. width: 92rpx;
  533. height: 92rpx;
  534. border-radius: 50%;
  535. }
  536. }
  537. .active_cate_text {
  538. background: linear-gradient(90deg, var(--view-gradient) 0, var(--view-theme) 100%);
  539. color: #fff;
  540. border-radius: 20rpx;
  541. margin-top: 8rpx;
  542. }
  543. .cate_active {
  544. color: var(--view-theme);
  545. background: var(--view-minorColorT);
  546. border: 1rpx solid var(--view-theme);
  547. }
  548. .rd-b-40{
  549. border-radius: 0 0 0 40rpx;
  550. }
  551. </style>