Explorar el Código

商品分享和骨架屏

viczhq hace 1 semana
padre
commit
bf636dbf95

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 19856 - 53011
package-lock.json


+ 7 - 0
project.private.config.json

@@ -10,6 +10,13 @@
10 10
     "miniprogram": {
11 11
       "list": [
12 12
         {
13
+          "name": "pages/memberSub/earningsOrder/index",
14
+          "pathName": "pages/memberSub/earningsOrder/index",
15
+          "query": "",
16
+          "launchMode": "default",
17
+          "scene": null
18
+        },
19
+        {
13 20
           "name": "pages/productManagement/index",
14 21
           "pathName": "pages/memberSub/storeManagement/index",
15 22
           "query": "",

+ 10 - 10
src/api/request.js

@@ -42,18 +42,18 @@ export default async (options = { method: 'GET', data: {} }) => {
42 42
       case 200:
43 43
         return data;
44 44
       case 400:
45
-        Taro.showToast({
46
-          title: '传参有误',
47
-          icon: 'none',
48
-          mask: true,
49
-        });
45
+        // Taro.showToast({
46
+        //   title: '传参有误',
47
+        //   icon: 'none',
48
+        //   mask: true,
49
+        // });
50 50
         throw new Error('传参有误');
51 51
       case 422:
52
-        Taro.showToast({
53
-          title: 'Validation Error',
54
-          icon: 'none',
55
-          mask: true,
56
-        });
52
+        // Taro.showToast({
53
+        //   title: 'Validation Error',
54
+        //   icon: 'none',
55
+        //   mask: true,
56
+        // });
57 57
         throw new Error('Validation Error');
58 58
       case 500:
59 59
         Taro.showToast({

+ 12 - 0
src/common/share.js

@@ -0,0 +1,12 @@
1
+const shareConfig = {
2
+    title: '默认分享标题',
3
+    path: '/pages/index/index',
4
+    imageUrl: '',
5
+  };
6
+  
7
+  export const setShareContent = (config) => {
8
+    Object.assign(shareConfig, config);
9
+  };
10
+  
11
+  export const getShareContent = () => shareConfig;
12
+  

+ 39 - 0
src/components/Skeleton/index.jsx

@@ -0,0 +1,39 @@
1
+import { View } from '@tarojs/components'
2
+import './index.less'
3
+
4
+const Skeleton = ({ isSkeletonShow }) => {
5
+  return (
6
+    <View className="skeleton" style={{ display: isSkeletonShow ? 'block' : 'none' }}>
7
+      {/* 轮播图占位 */}
8
+      <View className="skeleton-carousel"></View>
9
+
10
+      {/* 列表分类 */}
11
+      <View className="skeleton-category">
12
+        {[...Array(5)].map((_, index) => (
13
+          <View key={index} className="skeleton-category-item"></View>
14
+        ))}
15
+      </View>
16
+
17
+      {/* 运营区域 */}
18
+      <View className="skeleton-operation">
19
+        <View className="skeleton-operation-item"></View>
20
+        <View className="skeleton-operation-item"></View>
21
+      </View>
22
+
23
+      {/* 商品列表 */}
24
+      <View className="skeleton-product">
25
+        <View className="skeleton-product-image"></View>
26
+        <View className="skeleton-product-info">
27
+          <View className="skeleton-product-title"></View>
28
+          <View className="skeleton-product-price"></View>
29
+          <View className="skeleton-product-buttons">
30
+            <View className="skeleton-product-button"></View>
31
+            <View className="skeleton-product-button"></View>
32
+          </View>
33
+        </View>
34
+      </View>
35
+    </View>
36
+  )
37
+}
38
+
39
+export default Skeleton

+ 116 - 0
src/components/Skeleton/index.less

@@ -0,0 +1,116 @@
1
+@keyframes skeleton-fade {
2
+    0% {
3
+        background-color: #e0e0e0;
4
+    }
5
+
6
+    50% {
7
+        background-color: #f0f0f0;
8
+    }
9
+
10
+    100% {
11
+        background-color: #e0e0e0;
12
+    }
13
+}
14
+
15
+.skeleton {
16
+    padding: 16px;
17
+    margin-top: -360px;
18
+    position: relative;
19
+}
20
+
21
+.skeleton-carousel {
22
+    width: 100%;
23
+    height: 350px;
24
+    background-color: #e0e0e0;
25
+    border-radius: 10px;
26
+    margin-bottom: 16px;
27
+}
28
+
29
+.skeleton-category {
30
+    display: flex;
31
+    justify-content: space-between;
32
+    padding: 0 17px;
33
+    margin-bottom: 16px;
34
+    height: 160px;
35
+    align-items: center;
36
+}
37
+
38
+.skeleton-category-item {
39
+    width: 126px;
40
+    height: 126px;
41
+    background-color: #e0e0e0;
42
+    border-radius: 10px;
43
+}
44
+
45
+.skeleton-operation {
46
+    display: flex;
47
+    justify-content: space-between;
48
+    margin-bottom: 26px;
49
+    height: 200px;
50
+}
51
+
52
+.skeleton-operation-item {
53
+    width: calc(50% - 8px);
54
+    height: 200px;
55
+    background-color: #e0e0e0;
56
+    border-radius: 10px;
57
+}
58
+
59
+.skeleton-product {
60
+    display: flex;
61
+    margin-bottom: 16px;
62
+}
63
+
64
+.skeleton-product-image {
65
+    width: 260px;
66
+    height: 260px;
67
+    background-color: #e0e0e0;
68
+    border-radius: 10px;
69
+    margin-right: 16px;
70
+}
71
+
72
+.skeleton-product-info {
73
+    flex: 1;
74
+    display: flex;
75
+    flex-direction: column;
76
+    justify-content: space-between;
77
+}
78
+
79
+.skeleton-product-title {
80
+    width: 100%;
81
+    height: 20px;
82
+    background-color: #e0e0e0;
83
+    border-radius: 10px;
84
+    margin-bottom: 8px;
85
+}
86
+
87
+.skeleton-product-price {
88
+    width: 50%;
89
+    height: 20px;
90
+    background-color: #e0e0e0;
91
+    border-radius: 10px;
92
+    margin-bottom: 16px;
93
+}
94
+
95
+.skeleton-product-buttons {
96
+    display: flex;
97
+    justify-content: space-between;
98
+}
99
+
100
+.skeleton-product-button {
101
+    width: 200px;
102
+    height: 90px;
103
+    background-color: #e0e0e0;
104
+    border-radius: 10px;
105
+}
106
+
107
+.skeleton-carousel,
108
+.skeleton-category-item,
109
+.skeleton-operation-item,
110
+.skeleton-product-image,
111
+.skeleton-product-title,
112
+.skeleton-product-price,
113
+.skeleton-product-button {
114
+    animation: skeleton-fade 1.5s infinite ease-in-out;
115
+    background-size: 200px 100%;
116
+}

+ 16 - 3
src/components/index/CategoryList/index.jsx

@@ -1,13 +1,26 @@
1 1
 import { View, Image, Text } from "@tarojs/components";
2 2
 import "./index.less";
3
+import Taro from "@tarojs/taro";
3 4
 
4 5
 const CategoryList = (props) => {
5 6
   const { categoryList } = props; //分类列表引用
7
+  const handleCategoryClick = (jpath, type_jpath) => {
8
+    if (type_jpath == 2) {
9
+      return;
10
+    }
11
+    Taro.navigateTo({
12
+      url: jpath,
13
+    });
14
+  };
6 15
   return (
7 16
     <View className="category-wrap">
8 17
       <View className="category-list">
9
-        {categoryList.map(item => (
10
-          <View key={item.id} className="category-item">
18
+        {categoryList.map((item) => (
19
+          <View
20
+            onClick={() => handleCategoryClick(item.jpath, item.type_jpath)}
21
+            key={item.id}
22
+            className="category-item"
23
+          >
11 24
             <Image className="category-icon" src={item.img} mode="aspectFit" />
12 25
             <Text className="category-name">{item.name}</Text>
13 26
           </View>
@@ -17,4 +30,4 @@ const CategoryList = (props) => {
17 30
   );
18 31
 };
19 32
 
20
-export default CategoryList; 
33
+export default CategoryList;

+ 1 - 2
src/components/index/CategoryList/index.less

@@ -4,11 +4,10 @@
4 4
   .category-list {
5 5
     display: flex;
6 6
     flex-wrap: wrap;
7
-    // justify-content: space-between;
8 7
     background: #FFFFFF;
9 8
     border-radius: 20px;
10 9
     padding: 25px 17px 22px 17px;
11
-    gap: 50px;
10
+    gap: 0 50px;
12 11
     .category-item {
13 12
       width: 96px;
14 13
       display: flex;

+ 7 - 2
src/components/index/ProductList/index.jsx

@@ -6,6 +6,7 @@ import React, {
6 6
 } from "react";
7 7
 import { View, Text, Image, Button } from "@tarojs/components";
8 8
 import { AtCheckbox, AtActivityIndicator } from "taro-ui";
9
+import { setShareContent } from "../../../common/share";
9 10
 import Taro from "@tarojs/taro";
10 11
 import "./index.less";
11 12
 import joinStoreBg from "../../../images/index/jionStore.png";
@@ -88,8 +89,12 @@ const ProductList = forwardRef((props, ref) => {
88 89
   // 分享商品 
89 90
   const shareProduct = (product, e) => {
90 91
     e.stopPropagation(); // 防止事件穿透
91
-    // 调用父组件的回调函数,传递商品信息
92
-    props.onShareProduct && props.onShareProduct(product);
92
+    props.onShareProduct && props.onShareProduct();
93
+    setShareContent({
94
+      title: product.item_title,
95
+      path: `/pages/indexSub/productDetail/index?id=${product.id}&&isShare=${true}`,
96
+      imageUrl: product.image_url,
97
+    });
93 98
   };
94 99
   return (
95 100
     <View className="product-list-wrap">

+ 9 - 14
src/pages/index/index.jsx

@@ -3,7 +3,9 @@ import { Component } from "react";
3 3
 import { View, Image, Swiper, SwiperItem, Text } from "@tarojs/components";
4 4
 import { AtTabs } from "taro-ui";
5 5
 import { getHomeData, getProductList } from "../../service";
6
+import { getShareContent } from "../../common/share";
6 7
 import "./index.less";
8
+import Skeleton from "../../components/skeleton"; //骨架屏
7 9
 import SearchBar from "../../components/index/SearchBar"; //搜索框
8 10
 import CategoryList from "../../components/index/CategoryList"; //分类列表
9 11
 import OperationArea from "../../components/index/OperationArea"; //运营区域
@@ -11,7 +13,6 @@ import RecommendList from "../../components/index/RecommendList"; //邀请人推
11 13
 import ProductList from "../../components/index/ProductList"; //商品列表
12 14
 import myStoreIcon from "../../images/index/myStore.png";
13 15
 import backTopIcon from "../../images/index/back-top.png";
14
-
15 16
 export default class Index extends Component {
16 17
   state = {
17 18
     current: 0, // 添加当前选中的tab索引
@@ -21,7 +22,6 @@ export default class Index extends Component {
21 22
     page: 1, // 添加页码
22 23
     totalPages: 1, // 添加总页数
23 24
     loading: false, // 添加加载状态
24
-    shareInfo: {}, // 分享信息
25 25
   };
26 26
   // 获取首页数据
27 27
   getHomeData = async () => {
@@ -103,22 +103,15 @@ export default class Index extends Component {
103 103
   };
104 104
 
105 105
   // 分享商品
106
-  handleShareProduct = (product) => {
107
-    this.setState({ shareInfo: product }, () => {
108
-      Taro.showShareMenu({
109
-        withShareTicket: true,
110
-        menus: ["shareAppMessage"],
111
-      });
106
+  handleShareProduct = () => {
107
+    Taro.showShareMenu({
108
+      withShareTicket: true,
109
+      menus: ["shareAppMessage"],
112 110
     });
113 111
   };
114 112
   // 配置分享内容
115 113
   onShareAppMessage() {
116
-      let shareInfo = this.state.shareInfo;
117
-      return {
118
-        title: shareInfo.item_title,
119
-        path: `/pages/indexSub/productDetail/index?id=${shareInfo.id}&&isShare=${true}`,
120
-        imageUrl: shareInfo.image_url,
121
-      };
114
+    return getShareContent();
122 115
   }
123 116
   render() {
124 117
     const { homeData, productList, loading } = this.state;
@@ -180,6 +173,8 @@ export default class Index extends Component {
180 173
             </Swiper>
181 174
           </View>
182 175
         </View>
176
+        {/* 骨架屏 */}
177
+        <Skeleton isSkeletonShow={!homeData.banner&&!productList.length>0}/>
183 178
         {/* 分类列表组件 */}
184 179
         {homeData.icon && <CategoryList categoryList={homeData.icon} />}
185 180
         {/* 运营区域 */}

+ 1 - 1
src/pages/index/index.less

@@ -2,7 +2,7 @@
2 2
   background-color: #f9f9f9;
3 3
   min-height: 100vh;
4 4
   padding-bottom: 40px;
5
-
5
+  box-sizing: border-box;
6 6
   .header {
7 7
     width: 100%;
8 8
     position: relative;

+ 13 - 0
src/pages/indexSub/highCommission/index.jsx

@@ -4,6 +4,7 @@ import "./index.less";
4 4
 import seckillImg from "../../../images/seckill/seckillTop.png";
5 5
 import ProductList from "../../../components/index/ProductList";
6 6
 import { getRecommendProductList } from "../../../service";
7
+import { getShareContent } from "../../../common/share";
7 8
 export default class Index extends Component {
8 9
   state = {
9 10
     productList: [], //推荐商品列表
@@ -31,6 +32,17 @@ export default class Index extends Component {
31 32
       loading: false,
32 33
     }));
33 34
   };
35
+  // 分享商品
36
+  handleShareProduct = () => {
37
+      Taro.showShareMenu({
38
+        withShareTicket: true,
39
+        menus: ["shareAppMessage"],
40
+    });
41
+  };
42
+  // 配置分享内容
43
+  onShareAppMessage() {
44
+    return getShareContent();
45
+  }
34 46
   // 页面上拉触底
35 47
   onReachBottom = () => {
36 48
     const { page, totalPages, loading } = this.state;
@@ -51,6 +63,7 @@ export default class Index extends Component {
51 63
             isSeckill={true}
52 64
             productList={this.state.productList}
53 65
             loading={this.state.loading}
66
+            handleShareProduct={this.handleShareProduct}
54 67
           />
55 68
         </View>
56 69
       </View>

+ 13 - 0
src/pages/indexSub/seckillIndex/index.jsx

@@ -4,6 +4,7 @@ import "./index.less";
4 4
 import seckillImg from "../../../images/seckill/seckillTop.png";
5 5
 import ProductList from "../../../components/index/ProductList";
6 6
 import { getRecommendProductList } from "../../../service";
7
+import { getShareContent } from "../../../common/share";
7 8
 export default class Index extends Component {
8 9
   state = {
9 10
     productList: [], //推荐商品列表
@@ -31,6 +32,17 @@ export default class Index extends Component {
31 32
       loading: false,
32 33
     }));
33 34
   };
35
+  // 分享商品
36
+  handleShareProduct = () => {
37
+    Taro.showShareMenu({
38
+      withShareTicket: true,
39
+      menus: ["shareAppMessage"],
40
+    });
41
+  };
42
+  // 配置分享内容
43
+  onShareAppMessage() {
44
+    return getShareContent();
45
+  }
34 46
   // 页面上拉触底
35 47
   onReachBottom = () => {
36 48
     const { page, totalPages, loading } = this.state;
@@ -51,6 +63,7 @@ export default class Index extends Component {
51 63
             isSeckill={true}
52 64
             productList={this.state.productList}
53 65
             loading={this.state.loading}
66
+            onShareProduct={this.handleShareProduct}
54 67
           />
55 68
         </View>
56 69
       </View>

+ 14 - 1
src/pages/memberSub/productClassify/index.jsx

@@ -9,6 +9,7 @@ import {
9 9
   addShopProduct,
10 10
   getAllTags,
11 11
 } from "../../../service";
12
+import { getShareContent } from "../../../common/share";
12 13
 export default class Index extends Component {
13 14
   state = {
14 15
     current: 0, // 当前选中的标签页索引
@@ -28,7 +29,7 @@ export default class Index extends Component {
28 29
       () => {
29 30
         Taro.pageScrollTo({
30 31
           scrollTop: 0,
31
-          duration: 300
32
+          duration: 300,
32 33
         });
33 34
         this.getBrowseShopProductList(true);
34 35
       }
@@ -89,6 +90,17 @@ export default class Index extends Component {
89 90
       }
90 91
     });
91 92
   };
93
+  // 分享商品
94
+  handleShareProduct = () => {
95
+    Taro.showShareMenu({
96
+      withShareTicket: true,
97
+      menus: ["shareAppMessage"],
98
+    });
99
+  };
100
+  // 配置分享内容
101
+  onShareAppMessage() {
102
+    return getShareContent();
103
+  }
92 104
   // 页面上拉触底
93 105
   onReachBottom = () => {
94 106
     const { page, totalPages, loading } = this.state;
@@ -113,6 +125,7 @@ export default class Index extends Component {
113 125
           loading={this.state.loading}
114 126
           productList={this.state.productList}
115 127
           isProductClassify={true}
128
+          onShareProduct={this.handleShareProduct}
116 129
           onAddProduct={(productId, index) =>
117 130
             this.onAddProduct(productId, index)
118 131
           }

+ 28 - 11
src/pages/memberSub/productManagement/index.jsx

@@ -7,8 +7,9 @@ import {
7 7
   getMyShopList,
8 8
   deleteShopProduct,
9 9
   updateProductSort,
10
-  getAllTags
10
+  getAllTags,
11 11
 } from "../../../service";
12
+import { getShareContent } from "../../../common/share";
12 13
 import ProductList from "../../../components/index/ProductList"; //商品列表
13 14
 import add from "../../../images/productManagement/add.png";
14 15
 import back from "../../../images/productManagement/back.png";
@@ -46,13 +47,16 @@ export default class Index extends Component {
46 47
   // 获取所有闲鱼tags
47 48
   getAllTags = async () => {
48 49
     const res = await getAllTags();
49
-    const arr = Object.values(res).map(item => item.name);
50
-    this.setState({
51
-      options: arr,
52
-    },()=>{
53
-      this.getMyShopList(true);
54
-    });
55
-  }
50
+    const arr = Object.values(res).map((item) => item.name);
51
+    this.setState(
52
+      {
53
+        options: arr,
54
+      },
55
+      () => {
56
+        this.getMyShopList(true);
57
+      }
58
+    );
59
+  };
56 60
   // 获取商品列表
57 61
   getMyShopList = async (isDelete) => {
58 62
     const { page } = this.state;
@@ -83,10 +87,10 @@ export default class Index extends Component {
83 87
   // 商品下拉选项
84 88
   handleSelectOption = (e) => {
85 89
     const selectedOption = this.state.options[e.detail.value];
86
-    this.setState({ selectedOption, page: 1, isNoMore: false },()=>{
90
+    this.setState({ selectedOption, page: 1, isNoMore: false }, () => {
87 91
       Taro.pageScrollTo({
88 92
         scrollTop: 0,
89
-        duration: 300
93
+        duration: 300,
90 94
       });
91 95
       this.getMyShopList(true);
92 96
     });
@@ -131,7 +135,8 @@ export default class Index extends Component {
131 135
       goods_ids: this.state.selectedProducts,
132 136
     });
133 137
     if (res.success == true) {
134
-      this.setState((prevState) => ({
138
+      this.setState(
139
+        (prevState) => ({
135 140
           productList: prevState.productList.filter(
136 141
             (item) => !this.state.selectedProducts.includes(item.id)
137 142
           ),
@@ -199,6 +204,17 @@ export default class Index extends Component {
199 204
       });
200 205
     }
201 206
   };
207
+  // 分享商品
208
+  handleShareProduct = () => {
209
+    Taro.showShareMenu({
210
+      withShareTicket: true,
211
+      menus: ["shareAppMessage"],
212
+    });
213
+  };
214
+  // 配置分享内容
215
+  onShareAppMessage() {
216
+    return getShareContent();
217
+  }
202 218
   // 页面上拉触底
203 219
   onReachBottom = () => {
204 220
     const { page, totalPages, loading } = this.state;
@@ -262,6 +278,7 @@ export default class Index extends Component {
262 278
                     loading={this.state.loading}
263 279
                     onDeleteProductSelect={this.onDeleteProductSelect}
264 280
                     isNoMore={this.state.isNoMore}
281
+                    onShareProduct={this.handleShareProduct}
265 282
                   />
266 283
                 )}
267 284
               </View>