index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. <template>
  2. <view class="collection-count" :style="viewColor">
  3. <view class="navTabBox">
  4. <view class="longTab">
  5. <view class="tab-item" v-for="(item,index) in tabList" :key="index" :class="{'on':index == tabIndex-1}" @click="bindTab(index)"><text>{{item.title}}</text></view>
  6. </view>
  7. <view v-if="collectProductList.length && tabIndex == 1" class="list_header acea-row">
  8. <view class="total">共<text>{{total}}</text>件商品</view>
  9. <view class="text" @click.stop="handleEdit">{{isEdit ? '完成' : '编辑'}}</view>
  10. </view>
  11. </view>
  12. <block v-if="tabIndex == 1">
  13. <view class='collectionGoods' v-if="collectProductList.length">
  14. <view class='item acea-row row-between-wrapper' v-for="(item,index) in collectProductList" :key="index" v-if="item.spu" @tap.stop="goDetail(item.spu)">
  15. <view class="left acea-row row-between-wrapper">
  16. <view v-if="isEdit" class="checkbox" @click.stop="collectCheck(item,index)">
  17. <text v-if="!item.check" class="iconfont icon-weixuanzhong"></text>
  18. <text v-else class="iconfont icon-xuanzhong1"></text>
  19. </view>
  20. <view class='pictrue' >
  21. <easy-loadimage mode="widthFix" :image-src="item.spu.image"></easy-loadimage>
  22. <view v-if="item.spu.product_type==0 && item.spu.status!==1" class="off">已下架</view>
  23. <view v-else-if="item.spu.product_type>0 && item.spu.status==0" class="off end-off">活动<br/>结束</view>
  24. </view>
  25. </view>
  26. <view class='text acea-row row-column-between' :class="isEdit ? 'edit' : ''">
  27. <view class='name' :class="{saleOff : item.spu.status!=1}">
  28. <view class="name_text">
  29. <text v-if="item.spu.product_type != 0" :class="'font_bg-red type'+item.spu.product_type">{{item.spu.product_type == 1 ? "秒杀" : item.spu.product_type == 2 ? "预售" : item.spu.product_type == 3 ? "助力" : item.spu.product_type == 4 ? "拼团" : ""}}</text>
  30. {{item.spu.store_name}}
  31. </view>
  32. </view>
  33. <view class='acea-row row-between-wrapper'>
  34. <view class='money' :class="{saleOff : item.spu.status!=1}"><text>¥</text>{{item.spu.price}}</view>
  35. </view>
  36. </view>
  37. </view>
  38. <view class='loadingicon acea-row row-center-wrapper'>
  39. <text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>{{loadTitle}}
  40. </view>
  41. </view>
  42. <view class='footer acea-row row-between-wrapper' v-if="isEdit && collectProductList.length>0">
  43. <view>
  44. <view class="allcheckbox" @click.stop="checkboxAllChange">
  45. <text v-if="!isAllSelect" class="iconfont icon-weixuanzhong"></text>
  46. <text v-else class="iconfont icon-xuanzhong1"></text>
  47. 全选
  48. </view>
  49. </view>
  50. <view class='acea-row row-between-wrapper'>
  51. <view class='button acea-row row-middle' style="margin-right: 20rpx;">
  52. <form @submit="subCollect" report-submit='true'>
  53. <button class='bnt collect_btn' formType="submit">取消收藏</button>
  54. </form>
  55. </view>
  56. </view>
  57. </view>
  58. </block>
  59. <block v-else>
  60. <view v-if="storeList.length>0" class="user_store_attention" :style="viewColor">
  61. <view class="item" v-for="(item,index) in storeList" :key="index" :style="{ 'background-image': `url(${domain}/static/diy/store_bg${keyColor}.png)`}">
  62. <view class="store_header" @click="goStore(item)">
  63. <image :src="item.merchant.mer_avatar" mode=""></image>
  64. <view class="info">
  65. <view class="line1">
  66. <text class="name line1">{{item.merchant.mer_name}}</text>
  67. <text v-if="item.merchant.type_name" class="font-bg-red ml8">{{item.merchant.type_name}}</text>
  68. <text v-else-if="item.merchant.is_trader" class="font-bg-red ml8">自营</text>
  69. </view>
  70. <view class="btn" @click.stop="bindDetele(item,index)">取消关注</view>
  71. </view>
  72. </view>
  73. <view class="store-closed" v-if="item.merchant.is_del == 1 || item.merchant.mer_state == 0 || item.merchant.status == 0">
  74. <image class="closed" :src="domain+'/static/images/store-closed.png'"></image>
  75. <view class="closed-text">店铺已关闭,去看看别的店铺吧</view>
  76. </view>
  77. <view class="store_recommend" v-else-if="item.merchant && item.merchant.showProduct.length>0">
  78. <block v-for="(itemn,indexn) in item.merchant.showProduct" :key="indexn" v-if="indexn < 3">
  79. <navigator :url="'/pages/goods_details/index?id='+itemn.product_id"
  80. hover-class="none" class="list">
  81. <view class="picture">
  82. <easy-loadimage mode="widthFix" :image-src="itemn.image"></easy-loadimage>
  83. <view v-if="itemn.border_pic" :style="{ backgroundImage: `url(${itemn.border_pic})` }" class="border-picture"></view>
  84. </view>
  85. </navigator>
  86. </block>
  87. </view>
  88. </view>
  89. </view>
  90. </block>
  91. <view class='noCommodity' v-if="(!collectProductList.length && tabIndex == 1) || (!storeList.length && tabIndex == 2)">
  92. <view class='pictrue'>
  93. <image :src="`${domain}/static/images/noCart.png`"></image>
  94. <view>{{tabIndex == 1 ? '暂无商品' : '暂无店铺'}},去添加点什么吧</view>
  95. </view>
  96. </view>
  97. </view>
  98. </template>
  99. <script>
  100. // +----------------------------------------------------------------------
  101. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  102. // +----------------------------------------------------------------------
  103. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  104. // +----------------------------------------------------------------------
  105. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  106. // +----------------------------------------------------------------------
  107. // | Author: CRMEB Team <admin@crmeb.com>
  108. // +----------------------------------------------------------------------
  109. import { getCollectUserList, getProductHot, userCollectDel, collectDel, getMerchantLst } from '@/api/store.js';
  110. import { goShopDetail } from '@/libs/order.js'
  111. import {initiateAssistApi} from '@/api/activity.js'
  112. import { mapGetters } from "vuex";
  113. import { configMap } from '@/utils';
  114. import { HTTP_REQUEST_URL } from '@/config/app';
  115. import easyLoadimage from '@/components/easy-loadimage/easy-loadimage.vue';
  116. import { toLogin } from '@/libs/login.js';
  117. export default {
  118. components: {
  119. easyLoadimage,
  120. },
  121. data() {
  122. return {
  123. hostProduct: [],
  124. loadTitle: '加载更多',
  125. loading: false,
  126. loadend: false,
  127. collectProductList: [],
  128. checkedArr: [],
  129. limit: 10,
  130. page: 1,
  131. hotScroll:false,
  132. hotPage:1,
  133. hotLimit:10,
  134. domain: HTTP_REQUEST_URL,
  135. storeList:[],
  136. isScroll:true,
  137. storePage: 1,
  138. storeLimit: 10,
  139. total: 0,
  140. isEdit: false,
  141. isAllSelect: false,
  142. tabIndex:1,
  143. tabList:[
  144. {
  145. title:'商品'
  146. },
  147. {
  148. title:'店铺'
  149. }
  150. ],
  151. };
  152. },
  153. computed: configMap({recommend_switch:0,hide_mer_status:0},mapGetters(['isLogin','viewColor','keyColor'])),
  154. onLoad(options) {
  155. this.tabIndex = options.tab || 1
  156. if (this.isLogin) {
  157. this.get_user_collect_product();
  158. this.getList();
  159. } else {
  160. toLogin()
  161. }
  162. },
  163. /**
  164. * 页面上拉触底事件的处理函数
  165. */
  166. methods: {
  167. handleEdit(){
  168. this.isEdit = !this.isEdit;
  169. },
  170. goStore(item){
  171. if(this.hide_mer_status != 1){
  172. uni.navigateTo({
  173. url:`/pages/store/home/index?id=${item.merchant.mer_id}`
  174. })
  175. }
  176. },
  177. goDetail(item){
  178. goShopDetail(item, this.uid).then(res => {
  179. if (this.isLogin) {
  180. initiateAssistApi(item.activity_id).then(res => {
  181. let id = res.data.product_assist_set_id;
  182. uni.hideLoading();
  183. uni.navigateTo({
  184. url: '/pages/activity/assist_detail/index?id=' + id
  185. });
  186. }).catch((err) => {
  187. uni.showToast({
  188. title: err,
  189. icon: 'none'
  190. })
  191. });
  192. } else {
  193. toLogin()
  194. }
  195. })
  196. },
  197. bindTab(index){
  198. this.tabIndex = index+1
  199. },
  200. // 取消关注
  201. bindDetele(item,index){
  202. userCollectDel({
  203. type:10,
  204. type_id:[item.type_id]
  205. }).then(res=>{
  206. uni.showToast({
  207. title:'已取消',
  208. icon:'none'
  209. })
  210. this.storeList.splice(index,1)
  211. })
  212. },
  213. getList(){
  214. if(!this.isScroll) return
  215. getMerchantLst({
  216. page:this.storePage,
  217. limit:this.storeLimit
  218. }).then(res=>{
  219. this.isScroll = res.data.list.length>=this.limit
  220. this.storeList = this.storeList.concat(res.data.list)
  221. this.storePage+=1
  222. })
  223. },
  224. /**
  225. * 获取收藏产品
  226. */
  227. get_user_collect_product: function() {
  228. let that = this;
  229. if (that.loading) return;
  230. if (that.loadend) return;
  231. that.loading = true;
  232. that.loadTitle = "";
  233. getCollectUserList({
  234. page: that.page,
  235. limit: that.limit
  236. }).then(res => {
  237. that.total = res.data.count;
  238. let collectProductList = res.data.list;
  239. let loadend = collectProductList.length < that.limit;
  240. collectProductList.forEach((item,index)=>{
  241. if(!item.check){
  242. that.$set(item,'check',false)
  243. }
  244. })
  245. that.collectProductList = that.$util.SplitArray(collectProductList, that.collectProductList);
  246. that.$set(that, 'collectProductList', that.collectProductList);
  247. that.loadend = loadend;
  248. that.loadTitle = loadend ? '我也是有底线的' : '加载更多';
  249. that.page = that.page + 1;
  250. that.loading = false;
  251. }).catch(err => {
  252. that.loading = false;
  253. that.loadTitle = "加载更多";
  254. });
  255. },
  256. /**
  257. * 取消收藏
  258. */
  259. subCollect: function() {
  260. let that = this;
  261. userCollectDel({
  262. type:1,
  263. type_id: that.getSelectGoods()
  264. }).then(res => {
  265. return that.$util.Tips({
  266. title: '取消收藏成功',
  267. icon: 'success'
  268. }, function() {
  269. that.reloadData()
  270. });
  271. }).catch(err => {
  272. return that.$util.Tips({
  273. title: err,
  274. });
  275. });;
  276. },
  277. reloadData() {
  278. this.checkedArr.forEach((itm, idx) => {
  279. this.collectProductList = this.collectProductList.filter(item => item!=itm);
  280. })
  281. this.total-=this.checkedArr.length;
  282. },
  283. collectCheck(item) {
  284. item.check = !item.check
  285. this.cartAllCheck('goodsCheck')
  286. },
  287. // 全选
  288. checkboxAllChange() {
  289. this.isAllSelect = !this.isAllSelect
  290. this.cartAllCheck('allCheck')
  291. },
  292. // 全选判断
  293. cartAllCheck(type) {
  294. let allArr = [];
  295. this.collectProductList.forEach((el, index) => {
  296. if(type == 'goodsCheck'){
  297. if(el.check){
  298. allArr.push(el)
  299. }
  300. }else{
  301. el.check = this.isAllSelect
  302. if (el.check) allArr.push(el)
  303. }
  304. })
  305. this.checkedArr = allArr;
  306. // 全选
  307. this.isAllSelect = allArr.length == this.collectProductList.length ? true : false
  308. },
  309. // 获取选中的商品
  310. getSelectGoods() {
  311. let arr = []
  312. this.collectProductList.forEach((el, index) => {
  313. if(el.check){
  314. arr.push(el.type_id)
  315. }
  316. })
  317. return arr;
  318. },
  319. },
  320. onReachBottom() {
  321. this.tabIndex == 1 ? this.get_user_collect_product() : this.getList()
  322. },
  323. // 滚动监听
  324. onPageScroll(e) {
  325. // 传入scrollTop值并触发所有easy-loadimage组件下的滚动监听事件
  326. uni.$emit('scroll');
  327. }
  328. }
  329. </script>
  330. <style scoped lang="scss">
  331. .navTabBox{
  332. height: 166rpx;
  333. position: fixed;
  334. top: 0;
  335. left: 0;
  336. width: 100%;
  337. z-index: 10;
  338. }
  339. .longTab{
  340. background: #fff;
  341. display: flex;
  342. text-align: center;
  343. }
  344. .tab-item{
  345. width: 50%;
  346. display: inline-block;
  347. line-height: 90rpx;
  348. color: #666666;
  349. font-size: 30rpx;
  350. text{
  351. position: relative;
  352. display: inline-block;
  353. }
  354. }
  355. .tab-item.on{
  356. color: var(--view-theme);
  357. font-weight: bold;
  358. text{
  359. &:after{
  360. content: "";
  361. display: inline-block;
  362. width: 90%;
  363. height: 3rpx;
  364. background-color: var(--view-theme);
  365. position: absolute;
  366. left: 5%;
  367. bottom: 0;
  368. }
  369. }
  370. }
  371. .list_header{
  372. justify-content: space-between;
  373. padding: 0 30rpx;
  374. height: 76rpx;
  375. line-height: 76rpx;
  376. color: #666666;
  377. font-size: 26rpx;
  378. background: #f5f5f5;
  379. .total{
  380. text{
  381. color: var(--view-theme);
  382. }
  383. }
  384. .text{
  385. color: var(--view-theme);
  386. }
  387. }
  388. .collectionGoods {
  389. background-color: #fff;
  390. margin-top: 166rpx;
  391. }
  392. .font_bg-red {
  393. background-color: var(--view-theme);
  394. border: 1px solid var(--view-theme);
  395. &.type2{
  396. background-color: #FD6523;
  397. border: 1px solid #FD6523;
  398. }
  399. }
  400. .collectionGoods .item {
  401. margin-left: 30rpx;
  402. padding: 25rpx 30rpx 30rpx 0;
  403. border-bottom: 1px solid #eee;
  404. .checkbox{
  405. margin-right: 30rpx;
  406. .iconfont{
  407. font-size: 38rpx;
  408. color: #999999;
  409. &.icon-xuanzhong1{
  410. color: var(--view-theme);
  411. }
  412. }
  413. }
  414. }
  415. .collectionGoods .item .pictrue {
  416. width: 160rpx;
  417. height: 160rpx;
  418. position: relative;
  419. .off{
  420. width: 80rpx;
  421. height: 80rpx;
  422. background: rgba(0,0,0,.5);
  423. color: #ffffff;
  424. font-size: 20rpx;
  425. display: flex;
  426. align-items: center;
  427. justify-content: center;
  428. border-radius: 100%;
  429. position: absolute;
  430. top: 50%;
  431. left: 50%;
  432. margin: -40rpx 0 0 -40rpx;
  433. &.end-off{
  434. width: 90rpx;
  435. height: 90rpx;
  436. margin: -45rpx 0 0 -45rpx;
  437. &::after{
  438. content: "";
  439. width: 76rpx;
  440. height: 76rpx;
  441. border: 2rpx dashed #ffffff;
  442. border-radius: 100%;
  443. position: absolute;
  444. top: 6rpx;
  445. left: 6rpx;
  446. }
  447. }
  448. }
  449. }
  450. /deep/.collectionGoods .item .pictrue image,
  451. /deep/.collectionGoods .item .easy-loadimage, .collectionGoods .item uni-image{
  452. width: 100%;
  453. height: 100%;
  454. border-radius: 10rpx;
  455. }
  456. .collectionGoods .item .text {
  457. width: 500rpx;
  458. height: 160rpx;
  459. font-size: 28rpx;
  460. color: #282828;
  461. &.edit{
  462. width: 430rpx;
  463. }
  464. }
  465. .collectionGoods .item .text .name {
  466. width: 100%;
  467. display: flex;
  468. align-items: center;
  469. font-size: 28rpx;
  470. &.saleOff{
  471. color: #CCCCCC;
  472. }
  473. }
  474. .collectionGoods .item .name_text{
  475. display: inline-block;
  476. max-width: 480rpx;
  477. overflow:hidden;
  478. text-overflow: ellipsis;
  479. display: -webkit-box;
  480. -webkit-line-clamp: 2;
  481. -webkit-box-orient: vertical;
  482. font-size: 28rpx;
  483. }
  484. .collectionGoods .item .text .money {
  485. font-size: 30rpx;
  486. font-weight: bold;
  487. color: var(--view-priceColor);
  488. text{
  489. font-size: 20rpx;
  490. }
  491. &.saleOff{
  492. color: #CCCCCC;
  493. }
  494. }
  495. .collectionGoods .item .text .delete {
  496. display: flex;
  497. align-items: center;
  498. justify-content: center;
  499. font-size: 26rpx;
  500. color: #282828;
  501. width: 144rpx;
  502. height: 46rpx;
  503. border: 1px solid #bbb;
  504. border-radius: 24rpx;
  505. text-align: center;
  506. }
  507. .noCommodity {
  508. padding-top: 1rpx;
  509. border-top: 0;
  510. min-height: 90vh;
  511. margin-top: 90rpx;
  512. }
  513. .noCommodity .pictrue{
  514. text-align: center;
  515. padding: 0;
  516. margin: 78rpx auto 26rpx auto;
  517. }
  518. .collection-count .footer {
  519. z-index: 99;
  520. width: 100%;
  521. height: 100rpx;
  522. height: calc(100rpx+ constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
  523. height: calc(100rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
  524. background-color: #ffffff;
  525. position: fixed;
  526. padding: 0 20rpx;
  527. box-sizing: border-box;
  528. border-top: 1px solid #eee;
  529. bottom: var(--window-bottom);
  530. }
  531. .area-edit{
  532. justify-content: center;
  533. .area-item{
  534. width: 50%;
  535. text-align: center;
  536. position: relative;
  537. align-items: center;
  538. color: #333333;
  539. .text{
  540. position: relative;
  541. top: -1px;
  542. }
  543. .iconfont{
  544. color: #333333;
  545. }
  546. &:nth-child(1){
  547. &::after{
  548. content: '';
  549. display: inline-block;
  550. width: 2rpx;
  551. height: 42rpx;
  552. background: #CCCCCC;
  553. position: absolute;
  554. top: 0;
  555. right: 0;
  556. }
  557. }
  558. }
  559. }
  560. .collection-count .footer .checkAll {
  561. font-size: 28rpx;
  562. color: #282828;
  563. margin-left: 16rpx;
  564. }
  565. .allcheckbox .iconfont{
  566. margin-right: 11px;
  567. font-size: 40rpx;
  568. color: #cccccc;
  569. }
  570. .allcheckbox .icon-xuanzhong1{
  571. color: var(--view-theme);
  572. }
  573. .collection-count .footer .button .bnt {
  574. font-size: 28rpx;
  575. border-radius: 50rpx;
  576. width: 160rpx;
  577. height: 60rpx;
  578. text-align: center;
  579. line-height: 60rpx;
  580. color: var(--view-theme);
  581. border: 2rpx solid var(--view-theme);
  582. }
  583. .user_store_attention{
  584. padding: 20rpx;
  585. margin-top: 90rpx;
  586. .item{
  587. background-color: #ffffff;
  588. background-size: 100%;
  589. background-repeat: no-repeat;
  590. border-radius: 16rpx;
  591. padding: 0 20rpx;
  592. margin-bottom: 20rpx;
  593. }
  594. .store_header{
  595. position: relative;
  596. display: flex;
  597. padding: 30rpx 10rpx;
  598. align-items: center;
  599. image{
  600. width: 88rpx;
  601. height: 88rpx;
  602. border-radius: 50%;
  603. }
  604. .info{
  605. flex: 1;
  606. display: flex;
  607. flex-direction: column;
  608. justify-content: space-between;
  609. margin-left: 20rpx;
  610. position: relative;
  611. .name{
  612. width: 410rpx;
  613. font-weight: bold;
  614. }
  615. .des{
  616. color: #666666;
  617. font-size: 22rpx;
  618. }
  619. .btn{
  620. display: flex;
  621. align-items: center;
  622. justify-content: center;
  623. position: absolute;
  624. right: 0;
  625. top: 50%;
  626. width:150rpx;
  627. height:50rpx;
  628. transform: translateY(-50%);
  629. border:1px solid #BBBBBB;
  630. border-radius:25rpx;
  631. font-size: 26rpx;
  632. }
  633. }
  634. }
  635. .store-closed{
  636. text-align: center;
  637. padding-bottom: 30rpx;
  638. .closed{
  639. width: 300rpx;
  640. height: 170rpx;
  641. }
  642. .closed-text{
  643. color: #999999;
  644. font-size: 26rpx;
  645. margin-top: 20rpx;
  646. }
  647. }
  648. .store_recommend{
  649. display: flex;
  650. padding-bottom: 30rpx;
  651. .list{
  652. width: 210rpx;
  653. .picture,/deep/image,/deep/.easy-loadimage,uni-image{
  654. width: 210rpx;
  655. height: 210rpx;
  656. border-radius: 10rpx;
  657. position: relative;
  658. }
  659. .border-picture {
  660. position: absolute;
  661. top: 0;
  662. left: 0;
  663. width: 100%;
  664. height: 100%;
  665. border-radius: 16rpx 16rpx 0 0;
  666. background: center/cover no-repeat;
  667. }
  668. margin-right: 20rpx;
  669. &:last-child{
  670. margin-right: 0;
  671. }
  672. .price{
  673. text-align: center;
  674. color: var(--view-priceColor);
  675. font-size: 24rpx;
  676. margin-top: 10rpx;
  677. font-weight: bold;
  678. }
  679. }
  680. }
  681. }
  682. </style>