续之前微信小程序的部分代码

6.商城(category)

#index.js
import { request} from "../../request/index.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
Page({

  data: {
      //左侧的菜单数据
      leftMenuList:[],
      //右侧的商品数据
      rightContent:[],
      //被点击的左侧的菜单
      currentIndex:0,
      // 右侧内容的滚动条距离顶部的距离
      scrollTop:0
  },
  //接口的返回数据
  Cates:[],

  onLoad: function (options) {
    /*
    0 web中的本地存储和 小程序中的本地存储的区别
      1 写代码的方式不一样了 
      web: localStorage.setItem('key', data)  localStorage.getItem("key")
      小程序中: wx.setStorageSync('key', "data";(储存数据)  wx.getStorageSync('key');(获取数据)
      2 存的时候有没有做类型转换
      web: 不管存入的是什么类型的数据,最终都会先调用一下 toString(), 把数据变成字符串再存入进去
      小程序: 不需要进行类型转换 村什么类型就获取什么类型
    1 先判断一下本地存储有没有旧的数据
       {time:Data.now(),data:[...]}
    2 没有旧数据 直接发送新请求
    3 有旧数据 同时 旧数据也没有过期 就使用本地存储中的旧数据即可
    */
     // 1 获取本地存储中的数据 
     const Cates=wx.getStorageSync('cates');
     // 2 判断 
     if(!Cates){
       // 不存在 发送请求获取数据
      this.getCates();
     }
     else{
       //有旧的数据 定义过期时间 10s改为5分钟
       if(Date.now()-Cates.time>1000*10){
         //重新发送请求
         this.getCates();
       }else{
         //可以使用旧的数据
         this.Cates = Cates.data;
         let leftMenuList=this.Cates.map(v=>v.cat_name); 
         let rightContent=this.Cates[0].children;
         this.setData({
           leftMenuList,
           rightContent
         })
       }
     }
  },
  //获取分类数据
  async getCates(){
        // request({
        //   url:'/categories'
        // })
        // .then(res=>{
        //   //console.log(res);
        //   this.Cates=res.data.message;
        //   // 把接口的数据存入到本地存储中
        //   wx.setStorageSync('cates', {time:Date.now(),data:this.Cates});
        //   //构造左侧的大菜单数据
        //   let leftMenuList=this.Cates.map(v=>v.cat_name);
        //   //构造右侧的商品数据
        //   let rightContent=this.Cates[0].children;
        //   this.setData({
        //     leftMenuList,
        //     rightContent,

        //   })
        // })

        // 1 使用es7的 async await发送请求
        const res = await request({url:"/categories"});
        this.Cates = res.data.message;
        // 把接口数据存入到本地存储中
          wx.setStorageSync('cates', {time:Date.now(),data:this.Cates});
          //构造左侧的大菜单数据
          let leftMenuList=this.Cates.map(v=>v.cat_name);
          //构造右侧的商品数据
          let rightContent=this.Cates[0].children;
          this.setData({
            leftMenuList,
            rightContent,
          })
  },
  //左侧菜单的点击事件
  handleItemTap(e){
    /* 1 获取被点击的标题身上的索引
       2 给data中的currentIndex赋值
       3 根据不同的索引来渲染右侧的商品内容
    */
   const{index}=e.currentTarget.dataset;
   let rightContent=this.Cates[index].children;
   this.setData({
     currentIndex:index,
     rightContent,
    // 重新设置 右侧内容的scroll-view 标签与顶部的距离
    scrollTop:0
   })
  }
})


#index.json
{
  "usingComponents": {
    "searchinput":"../../components/searchinput/search input"
  },
  "navigationBarTitleText": "商品分类 " 
}

#index.wxml
<view class="cates">
	<searchinput></searchinput>
	<view class="cates_container">
		<!--左侧菜单 -->
		<scroll-view scroll-y class="left_menu">
			<view
			 class="menu_item {{index===currentIndex?'active':''}}"
			 wx:for="{{leftMenuList}}"
			 wx:key="*this"
			 bindtap="handleItemTap"
			 data-index="{{index}}"
			>
				{{item}}
			</view>

		</scroll-view>
		<!--右侧商品内容-->
		<scroll-view scroll-top="{{scrollTop}}" scroll-y class="right_content">
			<view
			 class="goods_group"
			 wx:for="{{rightContent}}"
			 wx:for-index="index1"
			 wx:for-item="item1"
			>
				<view class="goods_title">
					<text class="delimiter">/</text>
					<text class="title">{{item1.cat_name}}</text>
					<text class="delimiter">/</text>
				</view>
				<view class="goods_list">
					<navigator
					 wx:for="{{item1.children}}"
					 wx:for-index="index2"
					 wx:for-item="item2"
					 wx:key="cat_id"
					 url="/pages/goods_list/index?cid={{item2.cat_id}}"
					>
						<image mode="widthFix" src="{{item2.cat_icon}}"></image>
						<view class="goods_name">{{item2.cat_name}}</view>
					</navigator>
				</view>
			</view>
		</scroll-view>
	</view>
</view>
#index.less
pages{
  height: 100%;
}
.cates{
  height: 100%;
  .cates_container{
      /* less中使用calc的时候要注意 */
      height: ~'calc( 100vh - 90rpx)';
      display: flex;
      .left_menu{
          /* 子项 高度100% flex*/
          flex: 2;
         
          .menu_item{
              height: 80rpx;
              display: flex;
              justify-content: center;
              align-items: center;
              font-size: 30rpx;
          }
          .active{
              color:var(--themeColor); 
              border-left: 5rpx solid currentColor;
          }
      }
     .right_content{
         /* 子项 高度100% flex*/
          flex: 5;
          .goods_group{
              .goods_title{
                  height: 80rpx;
                  display: flex;
                  justify-content: center;
                  align-items: center;
                  .delimiter{
                      color:#ccc;
                      padding: 0 10rpx;
                  }
                  .title{}
              }
              .goods_list{
                  display: flex;
                  flex-wrap: wrap;
                  navigator{
                      width: 33.33%;
                      text-align: center;
                      iamge{
                          width: 50%;
                      }
                      .goods_name{

                      }
                  }
              }
          }           
     } 
  }
}

#index.wxss
pages {
  height: 100%;
}
.cates {
  height: 100%;
}
.cates .cates_container {
  /* less中使用calc的时候要注意 */
  height: calc( 100vh - 90rpx);
  display: flex;
}
.cates .cates_container .left_menu {
  /* 子项 高度100% flex*/
  flex: 2;
}
.cates .cates_container .left_menu .menu_item {
  height: 80rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 30rpx;
}
.cates .cates_container .left_menu .active {
  color: var(--themeColor);
  border-left: 5rpx solid currentColor;
}
.cates .cates_container .right_content {
  /* 子项 高度100% flex*/
  flex: 5;
}
.cates .cates_container .right_content .goods_group .goods_title {
  height: 80rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
.cates .cates_container .right_content .goods_group .goods_title .delimiter {
  color: #ccc;
  padding: 0 10rpx;
}
.cates .cates_container .right_content .goods_group .goods_list {
  display: flex;
  flex-wrap: wrap;
}
.cates .cates_container .right_content .goods_group .goods_list navigator {
  width: 33.33%;
  text-align: center;
}
.cates .cates_container .right_content .goods_group .goods_list navigator iamge {
  width: 50%;
}

7.商城列表(good_list)

#index.js
/*
1 用户上滑页面 滚动条触底 开始加载下一页数据
   1 找到滚动条触底事件 微信小程序官方文档寻找
   2 判断还有没有下一页数据
     1 获取到总页数 
        总页数 = Math.ceil(总条数 / 页容量 pagesize)
        总页数 = Math.ceil( 23/ 10)=3
     2 获取到当前页码 pagenum
     3 判断一下当前的页码是否大于等于 总页数 
        表示 没有下一页数据 
   3 假如没有下一页数据 弹出提示
   4 加入还有下一页数据 用来加载下一页数据
     1 当前的页码++
     2 重新发送请求
     3 数据请求回来 要对data中的数组 进行 拼接 而不是全部替换!!!!
2 下拉刷新页面
   1 出发下拉刷新事件 需要在页面的json文件中开启一个配置项
      找到触发下拉刷新的事件
   2 重置 数据 数组
   3 重置页码 设置为1 
   4 发送请求
   5 关闭下拉刷新窗口
*/
import { request} from "../../request/index.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
Page({

  /**
   * 页面的初始数据
   */
  data: {
    tabs:[
      {
        id:0,
        value:"商品",
        isActive:true
      },

    ],
    goodsList:[]

  },
  //接口要的参数
  QueryParams:{
    query:"",
    cid:"",
    pagenum:1,
    pagesize:10
  }, 
// 总页数
totalPages: 1,

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.QueryParams.cid=options.cid||"";
    this.QueryParams.query=options.query||"";
    this.getGoodsList();
  },
  //获取商品列表数据
    async  getGoodsList(){
    const data=await request({url:"/goods/search",data:this.QueryParams});
    const message=data.data
    const res=message.message
    //获取总条数
    const total=res.total;
    // 计算总页数 
    this.totalPages=Math.ceil(total/this.QueryParams.pagesize);
    // console.log(this.totalPages);
    this.setData({
      // 拼接数组
      goodsList:[...this.data.goodsList,...res.goods]
    })

    // 关闭下拉刷新窗口 如果没有调用下拉刷新窗口 直接关闭也不会报错
    wx.stopPullDownRefresh();
  },
  //标题点击事件 从子组件传递过来
  handleTabsItemChange(e){
    // 1 获取被点击的标题索引
    const {index}=e.detail;
    // 2 修改源数组
    let{tabs}=this.data;
    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
    // 3 赋值到data中
    this.setData({
      tabs
    })
  },
  // 页面上滑 滚动条触底事件
  onReachBottom(){
    if(this.QueryParams.pagenum>=this.totalPages){
      //没有下一页数据
      // console.log("没有下一页数据");
      wx.showToast({
        title: '没有下一页数据',
      });
    }
    else{
      //还有下一页
      // console.log("还有下一页");
      this.QueryParams.pagenum++;
      this.getGoodsList();
    }
    
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    // console.log("刷新");  
    // 1 重置数组
    this.setData({ 
      goodsList:[]
    })
    // 2 重置页码
    this.QueryParams.pagenum=1;
    // 3 发送请求
    this.getGoodsList();
  },



  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  }
})

#index.json
{
  "usingComponents": {
    "searchinput":"../../components/searchinput/search input",
    "Tabs":"../../components/Tabs/Tabs"
  },
  "navigationBarTitleText": "商品列表 " ,
  "enablePullDownRefresh": true,
  "backgroundTextStyle": "dark",
  "backgroundColor": "#ffd68f"
}

#index.wxml

<searchinput></searchinput>
<!-- 监听事件 -->
<Tabs tabs="{{tabs}}" bindtabsItemChange="handleTabsItemChange" >
<block wx:if="{{tabs[0].isActive}}" >
<view class="first_tab" >
<navigator class="goods_item"
wx:for="{{goodsList}}"
wx:key="goods_id"
url="/pages/goos_detail/index?goods_id={{item.goods_id}}"
>

<!-- 左侧 图片容器 -->
<view class="goods_img_wrap">
<image mode="widthFix" src="{{item.goods_small_logo?item.goods_small_logo:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F00%2F86%2F05%2F58dac1dd00b60_610.jpg&refer=http%3A%2F%2Fpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1646973396&t=5e4d0a94808567e7e968e4a2bb755c17'}}"></image>
</view>
<!-- 右侧 商品容器 -->
<view class="goods_info_wrap">
<view class="goods_name">{{item.goods_name}}</view>
<view class="goods_price">¥{{item.goods_price}}</view>
</view>


</navigator>
</view>
</block>

</Tabs> 

#index.less
.first_tab{    
    display: flex;  
    flex-direction: row;   
    flex-wrap: wrap;
    background-color: #ffd68f;
        .goods_item{
            display: flex;     
            flex-wrap: wrap;
            padding: 20rpx;
            border-top:  10rpx solid #fff;
            border-bottom: 10rpx solid #fff;
            border-left:  10rpx solid #fff;;
            width: 50%;
             .goods_img_wrap{  
                 padding-left: 0rpx;
                 align-content: center;
                 justify-content: center;
                 width: 100%;
                 image{
                     width:100%;
                 }
             } 
             .goods_info_wrap{   
                 align-content: center;       
                 justify-content: flex-start;
                 .goods_name{
                     display: -webkit-box;
                     word-break: break-all;
                     text-overflow: ellipsis;
                     overflow: hidden;
                     -webkit-box-orient: vertical;
                     -webkit-line-clamp:1;/*设置 需要显示的行数*/
     
                 }
                 .goods_price{
                    padding-left: 0rpx;
                  
                 } 
             }
         }
    

}  

#index.wxss

.first_tab {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  background-color: #ffd68f;
}
.first_tab .goods_item {
  display: flex;
  flex-wrap: wrap;
  padding: 20rpx;
  border: 30rpx solid #fff;
  border-radius: 15%;
  width: 50%;
  
}
.first_tab .goods_item .goods_img_wrap {
  padding-left: 0rpx;
  align-content: center;
  justify-content: center;
  width: 100%;
}
.first_tab .goods_item .goods_img_wrap image {
  width: 100%;
}
.first_tab .goods_item .goods_info_wrap {
  color: black;
  align-content: center;
  justify-content: flex-start;
}
.first_tab .goods_item .goods_info_wrap .goods_name {
  display: -webkit-box;
  word-break: break-all;
  text-overflow: ellipsis;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  /*设置 需要显示的行数*/
}
.first_tab .goods_item .goods_info_wrap .goods_price {
  padding-left: 0rpx;
}

8.商城详情(good_detail)

#index.js
/*
1 发送请求获取数据
2 点击轮播图 预览大图
  1 给轮播图绑定点击事件
  2 调用小程序的api previewImage
3 点击 加入购物车
 1 绑定点击事件 
 2 获取缓存中的购物车数据 数组格式
 3 先判断 当前的商品是否已经存在于 购物车
 4 已经存在修改商品数据 执行购物车数量++ 重新把购物车数组填充回缓存中
 5 不存在于购物车的数组中 直接给购物车数组添加一个新的元素 县原武带上购买数量属性 num 重新把购物车数组 填充回缓存中
 6 弹出提示
4 商品收藏
 1 页面onshow的时候 加载缓存中的商品收藏数据
 2 判断商品是不是被收藏
    1 是 改变图标
    1 不是 不改变图标
 3 点击商品收藏按钮
  1 判断商品是否存在于缓存数组中
  2 已经存在 把该商品删除
  3 没有存在 把商品添加到收藏数组中 存入缓存中即可
*/

import { request} from "../../request/index.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
Page({

  /**
   * 页面的初始数据
   */
  data: {
    goodsObj:{},
    // 商品是否被收藏
    isCollect:false

  },
  // 商品对象
  GoodsInfo:{}, 

  /**
   * 生命周期函数--监听页面加载
   */
  onShow: function () {
    let pages=getCurrentPages();
    let currentPages=pages[pages.length-1];
    let options=currentPages.options;
    const{goods_id}=options;
    this.getGoodsDetail(goods_id);

  },
  // 获取商品详情数据
  async getGoodsDetail(goods_id){
    const data=await request({url:"/goods/detail",data:{goods_id}});
    const message=data.data;
    const goodsObj=message.message;
    this.GoodsInfo=goodsObj;
        // 1 获取缓存中的商品收藏的数组
        let collect=wx.getStorageSync('collect')||[];
        // 2 判断当前商品是否被收藏
        let isCollect = collect.some(v=>v.goods_id == this.GoodsInfo.goods_id);
    this.setData({
      goodsObj:{
        goods_name:goodsObj.goods_name,
        goods_price:goodsObj.goods_price,
        // iphone部分手机 不识别webp图片格式
        // 最好找到后台 让他进行修改
        // 临时自己改 确保后台存在 1.webp=>1.jpg
        goods_introduce:goodsObj.goods_introduce.replace(/\.webp/g,'.jpg'),
        pics:goodsObj.pics
      },
      isCollect
    })
  },
  // 点击轮播图 放大预览
   handlePrevewImage(e){
     // 1 先构造要预览的图片数组
     const urls=this.GoodsInfo.pics.map(v=>v.pics_mid);
     // 2 接受传递过来的图片url
     const current=e.currentTarget.dataset.url;
     wx.previewImage({
       current,
       urls,
     });
   },
   handleCartAdd(){
     // 1 获取缓存中购物车数组
     let cart=wx.getStorageSync('cart')||[];
     
     let index=cart.findIndex(v=>v.goods_id===this. GoodsInfo.goods_id);
     if(index===-1){
       // 不存在 第一次添加
       this.GoodsInfo.num=1;
       this.GoodsInfo.checked=true;
       cart.push(this.GoodsInfo);
     }
     else{
       // 4 已经存在购物车数据 执行 num++
       cart[index].num++;
     }
     // 5 把购物车重新添加回缓存中
     wx.setStorageSync("cart",cart);
     // 6 弹窗提示
     wx.showToast({
       title: '加入成功',
       icon:'success',
       //true 防止用户疯狂点击按钮
       mask:true
     });

   },
   // 点击商品收藏图标
   handleCollect(){
     let isCollect=false;
     // 1 获取缓存中的商品收藏数组
     let collect=wx.getStorageSync('collect')||[];
     // 2 判断该商品是否被收藏
     let index=collect.findIndex(v=>v.goods_id===this.GoodsInfo.goods_id);
     // 3 当index!=-1 表示已经收藏
     if(index!==-1){
       // 能找到 能收藏过了 在数组中删除该商品
       collect.splice(index,1);
       isCollect=false;
       wx.showToast({
         title: '取消成功',
         icon:'success',
         mask:true
       });
     }else{
       // 没有收藏
       collect.push(this.GoodsInfo);
       isCollect=true;
       wx.showToast({
        title: '收藏成功',
        icon:'success',
        mask:true
      });
     }
     // 4 把数组存入到缓存中
     wx.setStorageSync('collect', collect);
     // 5 修改data 中的属性 isCollect
     this.setData({
       isCollect
     })
   }

})

#index.json

{
  "usingComponents": {},
  "navigationBarTitleText": "商品详情" 
}


#index.wxml

<view class="detail_swiper">
<swiper autoplay circular indicator-dots>
<swiper-item 
wx:for="{{goodsObj.pics}}"
wx:key="pics_id"
bindtap="handlePrevewImage"
data-url="{{item.pics_mid}}">
<image mode="widthFix" src="{{item.pics_mid}}"></image>
</swiper-item>
</swiper>
</view>

<view class="goods_price">¥{{goodsObj.goods_price}}</view>
<view class="goods_name_row">
<view class="goods_name">{{goodsObj.goods_name}}</view>
<view class="goods_collect"bindtap="handleCollect">
<text class="iconfont {{isCollect?'icon-icon_shoucang_mian':'icon-icon_shoucang_xian'}} "></text> 
<view class="collect_text">收藏</view>
</view> 
</view>

<view class="goods_info">
<view class="goods_info_title">图文详情</view>
<view class="goods_info_content">
<!-- 富文本 -->
<!-- {{goodsObj.goods_introduce}} -->
<rich-text nodes="{{goodsObj.goods_introduce}}"></rich-text>
</view>
</view>


<view class="btm_tool">
  <view class="tool_item">
<view class="iconfont icon-kefu"></view>
<view>客服</view>
<button open-type="contact"></button>
</view>
<view class="tool_item">
<view class="iconfont icon-fenxiang"></view>
<view>分享</view>
<button open-type="share"></button>
</view>
<navigator url="/pages/cart/index" open-type="switchTab" class="tool_item">
<view class="iconfont icon-gouwuche"></view>
<view>购物车</view>
</navigator>
<view class="tool_item btn_cart " bindtap="handleCartAdd">
加入购物车
</view>
<view class="tool_item btn_buy">
立即购买
</view>
</view>

    
#index.less
page{
    padding-bottom: 110rpx;
}
.detail_swiper{
    swiper{
        height: 100vw;
        text-align: center;
        image{
            width: 60%;
        }

    }
} 
.goods_price{
    padding:15rpx;
    font-size: 32rpx;
    font-weight: 600;
    color: var(--themeColor);
}
.goods_name_row{
    border-top: 5rpx solid #dedede;
    border-bottom: 5rpx solid #dedede;
    padding: 10rpx 0 ;
    display:flex;
    .goods_name{
        flex: 5;
        color: black;
        font-size: 30rpx;
        padding: 0 10rpx;

        display: -webkit-box;
        overflow: hidden;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
    }
    .goods_collect{
        flex: 1;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        border-left: 1rpx solid #000;
        .iconfont{}
        .icon-icon_shoucang_mian{
            color: orangered;
          } 
        .collect_text{}
    }
}
.goods_info{
    .goods_info_title{
        font-size: 32rpx;
        color: var(--themeColor);
        font-weight: 600;
        padding: 20rpx;
    }
    .goods_info_content{}
}


.btm_tool{
    border-top: 1px solid #ccc;
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 110rpx;
    background-color: #fff;
    display: flex;
    font-size: 24rpx;
    .tool_item{
        flex: 1;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        font-size: 24rpx;
        position: relative;
        button{
            position: absolute;
            top:0;
            left: 0;
            width: 0;
            height: 0;
            opacity: 0;
        }
    } 
    .btn_cart{
        flex: 2;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        background-color: #ffa500;
        color: #fff;
        font-size: 30rpx;
        font-weight: 600;
    }
    .btn_buy{
        flex: 2;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        background-color: #eb4450;
        color: #fff;
        font-size: 30rpx;
        font-weight: 600;
    }
}

9.购物车(cart)

#js
/*
1 获取用户的收货地址
  1 绑定点击事件 
  2 调用小程序内置 api 获取用户的收货地址 wx.chooseAddress
2 获取 用户 对小程序 所授予 获取地址的权限状态 scope
   1 假设 用户点击获取收货地址的提示框 确定
      scope值 true 直接调用 获取收货地址
   2 假设 用户 从来没有调用过收货地址的api
      scope undefined 直接调用 获取收获地址 
   3 假设用户 点击 获取收货地址的提示框 取消 
      scope值 flase
      1 诱导用户 自己打开 授权设置·页面(wx.openSetting) 当用户重新给予获取 地址权限的时候 
      2 获取收货地址
   4 把获取到的收货地址存入到本子存储中
2 页面加载完毕 
  0 onLoad onShow
  1 获取本地存储中的地址数据
  2 把数据设置给data中的一个变量
3 onShow 
   0 回到了商品详情页面第一次添加商品的时候 手动添加商品
     1 num=1 
     2 checked=true
   1 获取缓存中的购物车数组
   2 把购物车数据 填充到data中
4 全选的实现 数据的展示
  1 onshow 获取缓存中的购物车数组
  2 根据购物车中的商品数据 所有的商品都被选中 checked=true 全选则被选中
5 总价格和总数量
  1 都需要商品被选中 我们才拿它来计算
  2 获取购物车数组
  3 遍历
  4 判断商品是否被选中1
  5 总价格+=商品的单价 * 商品的数量
  6 总数量 +=商品的数量
  7 把计算后的价格和数量设置回data中即可
6 商品的选中
  1 绑定change事件
  2 获取到被修改的商品对象
  3 商品对象的选中状态
  4 重现填充回data中和缓存中
  5 重现计算全选 总价格 总数量
7 全选和反选
  1 全选复选框绑定事件 change
  2 获取data中的全选变量 allChecked
  3 直接取反 allChecked=!allChecked
  4 遍历购物车数组 让里面商品 选中状态跟随 allChecked 改变而改变
  5 把购物车数组 和allChecked 重新设置回data 把购物车重新设置回缓存中
8 商品的数量的编辑
  1 “+” “-” 按钮 绑定同一个点击事件 区分的关键 自定义属性
  1 “+” “-”
  2 “-” “-1”
  2 传递被点击的商品id goods_id
  3 获取data中的购物车数组 来获取需要被修改的商品对象
  4 直接修改商品对象的数量 num
  当购物车数量=1 同时数量点击 “-” 弹窗提示 询问用户 是否删除
  1 确定 直接执行删除
  2 取消  什么都不做
  5 把cart数组 重新设置回缓存中 和data中 this.setCart ;                                                                                                                                                                                        
9 点击结算
 1 判断有没有收到收货地址信息
 2 判单用户有没有选购商品
 3 经过以上的验证 跳转到支付页面
*/
import { getSetting,chooseAddress,openSetting,showModal,showToast  } from"../../utils/asyncWx.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
Page({
  data:{
    address:{},
    cart:[],
    allChecked:false,
    totalPrice:0,
    totalNum:0
  },
  onShow(){
    // 1 获取缓存中的收货地址信息
    const address=wx.getStorageSync('address');
    // 1 获取缓存中的购物车数据
    const cart=wx.getStorageSync('cart')|| [];
    this.setData({address});
    this.setCart(cart); 

  },
      // 点击收货地址 
  async handleChooseAddress(){
    try{
    // 1 获取 权限状态
    const res1 = await getSetting();
    const scopeAddress = res1.authSetting["scope.address"];
    // 2 判断权限状态
    if(scopeAddress ===false){
      await openSetting();
    }
     
      // 4 调用获取收货地址的api 
      const address =await chooseAddress();
 
      // 5 存入到缓存中
      wx.setStorageSync('address', address);
    }
    catch(error){
      console.log(error);
    }
  },
  // 商品的选中
  handleItemChange(e){
    // 1 获取被修改的商品的id
    const goods_id=e.currentTarget.dataset.id;
    // 2 获取购物车数组
    let {cart}=this.data;
    // 3 找到被修改的商品对象
    let index=cart.findIndex(v=>v.goods_id);
    // 4 选中状态取反
    cart[index].checked=!cart[index].checked;
    this.setCart(cart);

  },
  // 设置购物车状态的同时 重新计算 底部工具栏的数据 全选 总价格 购买的数量
  setCart(cart){


    let allChecked=true;
    // 1  总价格 总数量
    let totalPrice=0;
    let totalNum=0;
    cart.forEach(v=>{
      if(v.checked){
        totalPrice+=v.num * v.goods_price;
        totalNum+=v.num;
      }else{
        allChecked=false;
      }
    })
      // 判断数组是否为空
    allChecked = cart.length != 0 ? allChecked : false;
    this.setData({
      cart,
      totalPrice,
      totalNum,
      allChecked
    });
    wx.setStorageSync('cart', cart);
  },
  //商品全选功能
  handleItemAllCheck(){
    // 1 获取data中的数据
    let {cart,allChecked}=this.data;
    // 2 修改值
    allChecked=!allChecked;
    // 3 循环修改cart数组 中的商品选中状态
    cart.forEach(v=>v.checked=allChecked);
    // 4 把修改后的值 填充回data或者缓存中
    this.setCart(cart);
  },
  // 商品数量编辑
 async handleItemNumEdit(e){
    // 1 获取传递过来的参数
    const{operation,id}=e.currentTarget.dataset;
    // 2 获取购物车数组
    let{cart}=this.data;
    // 3 找到需要修改的商品的索引
    const index=cart.findIndex(v=>v.goods_id===id);
    // 判断是否要执行删除 
    if(cart[index].num===1&&operation===-1){
      // 4.1 弹窗提示
      const res=await showModal({content:"是否删除"});
      if (res.confirm) {
        cart.splice(index,1);
        this.setCart(cart);
      }
    }else{
    // 4 进行修改数量
    cart[index].num+=operation;
    // 5 设置回缓存和data中
    this.setCart(cart);
    }
  },
  async handlePay(){
    // 1 判断收货地址
    const{address,totalNum}=this.data;
    if(!address.userName){
      await showToast({title:"您还没有选择收货地址"});
      return;
    }
    // 2 判断用户有没有选中商品
    if(totalNum===0){
      await showToast({title:"您未选中商品"});
      return;
    }
    // 3 跳转到支付页面
    wx.navigateTo({
      url: '/pages/pay/index',
    })
  }
  })


#json
{
  "usingComponents": {},
  "navigationBarTitleText": "购物车"
}

#.wxml
<!-- 收货地址 -->
<view class="revice_address_row">
<!-- 当收货地址 不存在 按钮显示 对象 空对象 bool类型也是true -->
<view class="address_btn" wx:if="{{!address.userName}}" >
<button bindtap="handleChooseAddress" type="primary" plain>获取收货地址</button>
</view>
<!-- 当收货地址 存在详细信息就显示 -->
<view wx:else class="user_info_row">
<view class="user_info">
<view>{{address.userName}}</view>
<view>{{address.provinceName+address.cityName+address.countyName+address.detailInfo}}</view>
</view>
<view class="user_phone">{{address.telNumber}}</view>
</view>
</view>

<!-- 购物车内容 -->
<view class="cart_content">
<view class="cart_title">购物车</view>
<view class="cart_main">
<!-- 当cart数组 长度不为0 显示商品信息 -->
<block wx:if="{{cart.length!==0}}" >
  <view class="cart_item"
wx:for="{{cart}}"
wx:key="goods_id"
>
<!-- 复选框 -->
<view class="cart_chk_wrap">
<checkbox-group data-id="{{item.goods_id}}"  bindchange="handleItemChange">
<checkbox checked="{{item.checked}}" ></checkbox>
</checkbox-group>
</view>
<!-- 商品图片 -->
<navigator class="cart_image_wrap">
<image mode="widthFix" src="{{item.goods_small_logo}}"></image>
</navigator>
<!-- 商品信息 -->
<view class="cart_info_wrap">
<view class="goods_name">{{item.goods_name}}</view>
<view class="goods_price_wrap">
<view class="goods_price">¥{{item.goods_price}}</view>
<view class="cart_num_tool">
<view bindtap="handleItemNumEdit" data-id="{{item.goods_id}}" data-operation="{{-1}}" class="num_edit">-</view>
<view class="goods_num">{{item.num}}</view>
<view bindtap="handleItemNumEdit" data-id="{{item.goods_id}}" data-operation="{{1}}" class="num_edit">+</view>
</view>
</view>
</view>
</view>
</block>
<block wx:else>
<image mode="widthFix" src="https://img0.baidu.com/it/u=2567860002,4149073386&fm=253&fmt=auto&app=138&f=PNG?w=500&h=500"></image>
</block>
</view>
</view>

<!-- 底部工具栏 -->
<view class="footer_tool">
<!-- 全选 -->
<view class="all_chk_wrap">
<checkbox-group bindchange="handleItemAllCheck" >
<checkbox checked="{{allChecked}}" >全选</checkbox>
</checkbox-group>
</view>
<!-- 总价格 -->
<view class="total_price_wrap">
<view class="total_price">
合计:<text class="total_price_text">{{totalPrice}}</text>
</view>
<view>包含运费</view>
</view>
<!-- 结算 -->
<view class="order_pay_wrap" bindtap="handlePay" >
结算({{totalNum}})
</view>
</view>

#less
page{
    padding-bottom: 90rpx;
}

.revice_address_row{
    .address_btn{
        padding: 20rpx;
        button{
            width: 60%;
        }
    }
    .user_info_row{
        display: flex;
        .user_info{
            flex: 5;
        }
        .user_phone{
            flex: 3;
        }
    }
}

 .cart_content {
   .cart_title {
       padding: 20rpx;
       font-size: 36rpx;
       color: var(--themeColor);
       border-top: 1rpx solid currentColor; 
       border-bottom: 1rpx solid currentColor;

  }

   .cart_main {
     .cart_item {
         display: flex;
         padding: 10rpx;
         border-bottom: 1px solid #ccc
       .cart_chk_wrap {
           flex: 1;
           display: flex;
           justify-content: center;
           align-items: center;
        checkbox-group {
          checkbox {

          }
        }
      }

      .cart_image_wrap {
          flex: 2;
          display: flex;
          justify-content: center;
          align-items: center;
        image {
            width: 90%;

        }
      }

       .cart_info_wrap {
           flex: 4;   
           display: flex;
           flex-direction: column;    
           justify-content: space-around;   
         .goods_name {
             display: -webkit-box;
             overflow: hidden;
             -webkit-box-orient: vertical;
             -webkit-line-clamp: 2;
             color: #666;

        }

         .goods_price_wrap {
             display: flex;
             justify-content: space-between;
           .goods_price {
            font-size: 36rpx;
            color: rgba(248, 11, 11, 0.945);


          }

           .cart_num_tool {
               display: flex;
             .num_edit {
                 width: 55rpx;
                 height: 55rpx;
                 display: flex;
                 justify-content: center;
                 align-items: center;
                 border: 1rpx solid #666;

            }

             .goods_num {
                width: 55rpx;
                height: 55rpx;
                display: flex;
                justify-content: center;
                align-items: center;


            }
          }
        }
      }
    }
  }
}

.footer_tool {
  position: fixed;
  bottom: 0;
  left: 0; 
  width: 100%;
  height: 90rpx;
  background-color: #fff;
  display: flex;
.all_chk_wrap {
    flex: 2;
    display: flex;
    justify-content: center;
    align-items: center;
}

.total_price_wrap {
    flex: 5;
    padding-right: 15rpx;
    text-align: right;
  .total_price {
   .total_price_text {
     color: red;
     font-size: 32rpx;
     font-weight: 600;
     
 }
}

.order_pay_wrap {
  flex: 3;
  background-color: var(--themeColor);
  color: #fff;
  font-size: 32rpx;
  font-weight: 600;
  display: flex;
  justify-content: center;
  align-items: center;
}
}

#wxss
page{
  padding-bottom: 90rpx;
}
.revice_address_row .address_btn {
  padding: 20rpx;
}
.revice_address_row .address_btn button {
  width: 60%;
}
.revice_address_row .user_info_row {
  display: flex;
}
.revice_address_row .user_info_row .user_info {
  flex: 5;
}
.revice_address_row .user_info_row .user_phone {
  flex: 3;
}
.cart_content .cart_title {
  padding: 20rpx;
  font-size: 36rpx;
  color: var(--themeColor);
  border-top: 1rpx solid currentColor;
  border-bottom: 1rpx solid currentColor;
}
.cart_content .cart_main .cart_item {
  display: flex;
  padding: 10rpx;
  border-bottom: 1px solid #ccc;
}
.cart_content .cart_main .cart_item .cart_chk_wrap {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}
.cart_content .cart_main .cart_item .cart_image_wrap {
  flex: 2;
  display: flex;
  justify-content: center;
  align-items: center;
}
.cart_content .cart_main .cart_item .cart_image_wrap image {
  width: 90%;
}
.cart_content .cart_main .cart_item .cart_info_wrap {
  flex: 4;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_name {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  color: #666;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap {
  display: flex;
  justify-content: space-between;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap .goods_price {
  font-size: 36rpx;
  color: rgba(248, 11, 11, 0.945);
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap .cart_num_tool {
  display: flex;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap .cart_num_tool .num_edit {
  width: 55rpx;
  height: 55rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1rpx solid #666;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap .cart_num_tool .goods_num {
  width: 55rpx;
  height: 55rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
.footer_tool{
  position: fixed;
  bottom: 0;
  left: 0; 
  width: 100%;
  height: 90rpx;
  background-color: #fff;
  display: flex;
  border-top: 1px solid #ccc;
}
.footer_tool .all_chk_wrap {
  flex: 2;
  display: flex;
  justify-content: center;
  align-items: center;
}
.footer_tool .total_price_wrap{
  flex: 5;
  padding-right: 15rpx;
  text-align: right;
}
.footer_tool .total_price_wrap .total_price .total_price_text {
  color: red;
  font-size: 35rpx;
  font-weight: 600;
  
}
.footer_tool .order_pay_wrap {
  flex: 3;
  background-color: var(--themeColor);
  color: #fff;
  font-size: 32rpx;
  font-weight: 600;
  display: flex;
  justify-content: center;
  align-items: center;
}

10.商品收藏collect

#.js
// pages/collect/index.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    collect:[],
    tabs:[
      {
        id:0,
        value:"商品收藏",
        isActive:true
      },
      {
        id:1,
        value:"品牌收藏",
        isActive:false
      },
      {
        id:2,
        value:"店铺收藏",
        isActive:false
      },
      {
        id:3,
        value:"浏览足迹",
        isActive:false
      }
    ]

  },
onShow(){
  const collect=wx.getStorageSync('collect')||[];
  this.setData({
    collect
  });
},
  handleTabsItemChange(e){
    // 1 获取被点击的标题索引
    const {index}=e.detail;
    // 2 修改源数组
    let{tabs}=this.data;
    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
    // 3 赋值到data中
    this.setData({
      tabs
    })
  }
})

#.json
{
  "usingComponents": {
    "Tabs":"../../components/Tabs/Tabs"
  },
  "navigationBarTitleText": "商品收藏"
}

#wxml
<Tabs tabs="{{tabs}}" bindtabsItemChange="handleTabsItemChange" >
<view class="collect_main">
<view class="collect_title">
<text class="collect_tips active">全部</text>
<text class="collect_tips">正在热卖</text>
<text class="collect_tips">即将上线</text>
</view>
<view class="collect_content">
<navigator class="goods_item"
wx:for="{{collect}}"
wx:key="goods_id"
url="/pages/goos_detail/index?goods_id={{item.goods_id}}"
>
<!-- 左侧 图片容器 -->
<view class="goods_img_wrap">
<image mode="widthFix" src="{{item.goods_small_logo?item.goods_small_logo:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F00%2F86%2F05%2F58dac1dd00b60_610.jpg&refer=http%3A%2F%2Fpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1646973396&t=5e4d0a94808567e7e968e4a2bb755c17'}}"></image>
</view>
<!-- 右侧 商品容器 -->
<view class="goods_info_wrap">
<view class="goods_name">{{item.goods_name}}</view>
<view class="goods_price">{{item.goods_price}}</view>
</view>
</navigator>
</view>
</view>
</Tabs> 

#less
page{

    color: #000000;
}
.collect_main{
    background-color: #f3f4f6;
    .collect_title{
        padding: 30rpx;
        color: #000000;
        .collect_tips{
            padding: 15rpx;
            border: 1rpx solid #ccc;
            margin-left: 25rpx;
            background-color: #fff;
        }
        .active{
            color: var(--themeColor);
            border-color: currentColor;
        }
    }
    .collect_content{
        .goods_item{
            display: flex;
            border-bottom: 5rpx solid #ccc ;
            background-color: #fff;
            .goods_img_wrap{
                flex:2;
                display: flex; 
                justify-content: center;
                align-items: center;
                image{
                    width: 70%;
                }
            }
            .goods_info_wrap{
                flex: 3;
                display: flex;
                flex-direction: column;
                justify-content: space-around;
                .goods_name{
                    display: -webkit-box;
                    overflow: hidden; 
                    -webkit-backdrop-filter: vertical;
                    -webkit-line-clamp: 2;
                }
                .goods_price{
                    color:var(--themColor);
                    font-size: 32rpx;
                } 
            }
        }
    }
}

#wxss
page {
  color: #000000;
}
.collect_main {
  background-color: #f3f4f6;
}
.collect_main .collect_title {
  padding: 30rpx;
  color: #000000;
}
.collect_main .collect_title .collect_tips {
  padding: 15rpx;
  border: 1rpx solid #ccc;
  margin-left: 25rpx;
  background-color: #fff;
}
.collect_main .collect_title .active {
  color: var(--themeColor);
  border-color: currentColor;
}
.collect_main .collect_content .goods_item {
  display: flex;
  border-bottom: 5rpx solid #ccc;
  background-color: #fff;
}
.collect_main .collect_content .goods_item .goods_img_wrap {
  flex: 2;
  display: flex;
  justify-content: center;
  align-items: center;
}
.collect_main .collect_content .goods_item .goods_img_wrap image {
  width: 70%;
}
.collect_main .collect_content .goods_item .goods_info_wrap {
  flex: 3;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
.collect_main .collect_content .goods_item .goods_info_wrap .goods_name {
  display: -webkit-box;
  overflow: hidden;
  -webkit-backdrop-filter: vertical;
  -webkit-line-clamp: 2;
}
.collect_main .collect_content .goods_item .goods_info_wrap .goods_price {
  color: var(--themColor);
  font-size: 32rpx;
}

11.订单查询order

#.js
/*
1 页面被打开的时候 onshow 
   0 onshow 不同于onload 无法在形参上接受 options参数 
     onshow 判断缓存中有没有token
       1 没有 直接跳转授权页面
       2 有 直接往下进行
   1 获取url上的参数type
   2 根据type 去发送请求获取订单数据
   3 渲染页面
2 点击不同的标题 重新发送请求来获取和渲染数据
*/

import { request} from "../../request/index.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
Page({

  /**
   * 页面的初始数据
   */
  data: {
    orders:[],
    tabs:[
      {
        id:0,
        value:"全部",
        isActive:true
      },
      {
        id:1,
        value:"待付款",
        isActive:false
      },
      {
        id:2,
        value:"代发货",
        isActive:false
      },
      {
        id:3,
        value:"退款/退货",
        isActive:false
      }
    ]

  },
  onShow(options){
    const token = wx.getStorageSync('token');
    if(!token){
      wx.navigateTo({
        url: '/pages/auth/index'
      });
      return;
    }
    // 1 获取当前的小程序的页面栈-数组 长度最大是10页面
    let pages=getCurrentPages();
    // 2 数组中 索引最大的页面就是当前页面
    let currentPages=pages[pages.length-1];
    // 3 获取url上的type参数
    const {type}=currentPages.options;
    // 4 激活选中页面标题 当type=1 index=0
    this.changeTitleByIndex(type-1); 
    this.getOrders(type); 
  },
  // 获取订单列表的方法
  async getOrders(type){
    const data=await request({url:"/my/orders/all",data:{type}});
    const message=data.data
    const res=message.message
    console.log(res); 
    this.setData({
      orders:res.orders.map(v=>({...v,create_time_cn:(new Date(v.create_time*1000).toLocaleString())}))
    }) 
  },
  // 根据标题索引来激活选中 标题数组
  changeTitleByIndex(index){
     // 2 修改源数组
     let{tabs}=this.data;
     tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
     // 3 赋值到data中
     this.setData({
       tabs
     })
  },
  handleTabsItemChange(e){
    // 1 获取被点击的标题索引
    const {index}=e.detail;
   this.changeTitleByIndex(index);
   // 2 重新发送请求 type=1 index=0
   this.getOrders(index+1);
  },
})


#.json
{
  "usingComponents": {
    "Tabs":"../../components/Tabs/Tabs"
  },
  "navigationBarTitleText": "订单查询"
}

#.wxml

<Tabs tabs="{{tabs}}" bindtabsItemChange="handleTabsItemChange" >
<view class="order_main">
<view
wx:for="{{orders}}"
wx:key="order_id"
class="order_item">
<view class="order_no_row">
<view class="order_no_text">订单编号</view>
<view class="order_no_value">{{item.order_number}}</view>
</view>
<view class="order_price_row">
<view class="order_price_text">订单价格</view>
<view class="order_price_value">{{item.order_price}}</view>
</view>
<view class="order_time_row">
<view class="order_time_text">订单日期</view>
<view class="order_time_value">{{item.create_time_cn}}</view>
</view>
</view>
</view>
</Tabs> 

#.less

.order_main {
  .order_item {
    padding: 20rpx;
    border-bottom: 1px solid #ccc;
    .order_no_row {
      display: flex;
      padding: 10rpx;
      justify-content: space-between;
      .order_no_text {

      }

      .order_no_value {

      }
    }

    .order_price_row {
      display: flex;
      padding: 10rpx;
      justify-content: space-between;
      .order_price_text {

      }

      .order_price_value {

      }
    }

    .order_time_row {
      display: flex;
      padding: 10rpx;
      justify-content: space-between;
    .order_time_text {

    }

    .order_time_value {

    }

    }


  }
}

#wxss
.order_main .order_item {
  padding: 20rpx;
  border-bottom: 1px solid #ccc;
}
.order_main .order_item .order_no_row {
  display: flex;
  padding: 10rpx;
  justify-content: space-between;
}
.order_main .order_item .order_price_row {
  display: flex;
  padding: 10rpx;
  justify-content: space-between;
}
.order_main .order_item .order_time_row {
  display: flex;
  padding: 10rpx;
  justify-content: space-between;
}

12.商品支付(pay)

#js
/*
1 页面加载的时候
  1 从缓存中获取购物车数据 渲染到页面中
     这些数据 checked=true
2 微信支付
  1 哪些人 哪些账号 可以实现微信支付
    1 企业账号
    2 企业账号的小程序后台中 必须给开发者 添加上白名单
       1 一个 appid 可以同时绑定多个开发者
       2 这些开发者可以公用这个appid 和他的 开发权限
3 支付按钮 
  1 先判断缓存中有没有 token
  2 没有就跳转到授权页面 进行获取token
  3 有token 正常运行
  4 创建订单 获取订单编号
  5 已经完成了微信支付 
  6 手动删除缓存中 已基本被选中了的商品
  7 删除后的购物车数据
  8 再跳转页面

*/
import { getSetting,chooseAddress,openSetting,showModal,showToast,requestPayment  } from"../../utils/asyncWx.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
import {  } from "../../request/index.js";
Page({
  data:{
    address:{},
    cart:[],
    totalPrice:0,
    totalNum:0
  },
  onShow(){
    // 1 获取缓存中的收货地址信息
    const address=wx.getStorageSync('address');
    // 1 获取缓存中的购物车数据
    let cart=wx.getStorageSync('cart')|| [];
    // 过滤后的购物车数组
    cart=cart.filter(v=>v.checked);
    this.setData({address});
      // 1  总价格 总数量
      let totalPrice=0;
      let totalNum=0;
      cart.forEach(v=>{
          totalPrice+=v.num * v.goods_price;
          totalNum+=v.num;
      })
      this.setData({
        cart,
        totalPrice,
        totalNum,
        address
      });
  },
  // 点击支付
  async handleOrderPay(){
    try {
      
    // 1 判断缓存中有没有token
    const token=wx.getStorageInfoSync("token");
    // 2 判断
    if(token){
      wx.navigateTo({
        url: '/pages/auth/index',
      });
      return;
    }
    console.log("不存在token"); 
    // 3 创建订单
    // 3.1 准备 请求头参数
    // const  = { Authorizaation: token };
    // 3.2 准备 请求体参数
    const order_price = this.data.totalPrice;
    const consignee_addr = this.data.address.all;
    const cart=this.data.cart;
    let goods=[];
    cart.forEach(v=>goods.push({
      goods_id:v.goods_id,
      goods_number:v.num,
      goods_price:v.goods_price
    }))
    const orderParams={order_price,consignee_addr,goods};
    // 4 准备发送请求 创建订单 获取订单编号
    const {order_number}=await request({url:"/my/orders/create",method:"POST",data:orderParams,});
    // 5 发起 预支付接口
    const {pay} = await  request({url:"/my/orders/create",method:"POST",data:orderParams,data:{order_number}});
    // 6 发起微信支付
    await requestPayment(pay);
    // 7 查询后台 订单状态
    const res=await request({url:"/my/orders/chkOrder",method:"POST",data:orderParams,data:{order_number}});
    await showToast({title:"支付成功"})
    // 手动删除缓存中 已经支付了的商品
    let newCart=wx.getStorageSync("cart");
    newCart=newCart.filter(v=>!v.checked);
    wx.getStorageSync('cart',newCart);
    // 8 支付成功了 跳转到订单页面
    wx.navigateTo({
      url: '/pages/order/index',
    });
    } catch (error) {
      await showToast({title:"支付成功"})
      console.log(error);
    }
  }
  })

#.json
{
  "usingComponents": {},
  "navigationBarTitleText": "商品支付"
}

#.wxml
<!-- 收货地址 -->
<view class="revice_address_row">
<!-- 当收货地址 存在详细信息就显示 -->
<view class="user_info_row">
<view class="user_info">
<view>{{address.userName}}</view>
<view>{{address.provinceName+address.cityName+address.countyName+address.detailInfo}}</view>
</view>
<view class="user_phone">{{address.telNumber}}</view>
</view>
</view>

<!-- 购物车内容 -->
<view class="cart_content">
<view class="cart_title">购物车</view>
<view class="cart_main">
<!-- 当cart数组 长度不为0 显示商品信息 -->
  <view class="cart_item"
wx:for="{{cart}}"
wx:key="goods_id"
>

<!-- 商品图片 -->
<navigator class="cart_image_wrap">
<image mode="widthFix" src="{{item.goods_small_logo}}"></image>
</navigator>
<!-- 商品信息 -->
<view class="cart_info_wrap">
<view class="goods_name">{{item.goods_name}}</view>
<view class="goods_price_wrap">
<view class="goods_price">¥{{item.goods_price}}</view>
<view class="cart_num_tool">
<view class="goods_num">x{{item.num}}</view>
</view>
</view>
</view>
</view>
</view>
</view>

<!-- 底部工具栏 -->
<view class="footer_tool">
<!-- 总价格 -->
<view class="total_price_wrap">
<view class="total_price">
合计:<text class="total_price_text">{{totalPrice}}</text>
</view>
<view>包含运费</view>
</view>
<!-- 支付 -->
<view class="order_pay_wrap" bindtap="handleOrderPay" >
支付({{totalNum}})
</view>
</view> 

#.wxss
page{
  padding-bottom: 90rpx;
}
.revice_address_row .user_info_row {
  display: flex;
}
.revice_address_row .user_info_row .user_info {
  flex: 5;
}
.revice_address_row .user_info_row .user_phone {
  flex: 3;
}
.cart_content .cart_title {
  padding: 20rpx;
  font-size: 36rpx;
  color: var(--themeColor);
  border-top: 1rpx solid currentColor;
  border-bottom: 1rpx solid currentColor;
}
.cart_content .cart_main .cart_item {
  display: flex;
  padding: 10rpx;
  border-bottom: 1px solid #ccc;
}

.cart_content .cart_main .cart_item .cart_image_wrap {
  flex: 2;
  display: flex;
  justify-content: center;
  align-items: center;
}
.cart_content .cart_main .cart_item .cart_image_wrap image {
  width: 90%;
}
.cart_content .cart_main .cart_item .cart_info_wrap {
  flex: 4;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_name {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  color: #666;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap {
  display: flex;
  justify-content: space-between;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap .goods_price {
  font-size: 36rpx;
  color: rgba(248, 11, 11, 0.945);
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap .cart_num_tool {
  display: flex;
}
.cart_content .cart_main .cart_item .cart_info_wrap .goods_price_wrap .cart_num_tool .goods_num {
  width: 55rpx;
  height: 55rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
.footer_tool{
  position: fixed;
  bottom: 0;
  left: 0; 
  width: 100%;
  height: 90rpx;
  background-color: #fff;
  display: flex;
  border-top: 1px solid #ccc;
}

.footer_tool .total_price_wrap{
  flex: 5;
  padding-right: 15rpx;
  text-align: right;
}
.footer_tool .total_price_wrap .total_price .total_price_text {
  color: red;
  font-size: 35rpx;
  font-weight: 600;
  
}
.footer_tool .order_pay_wrap {
  flex: 3;
  background-color: var(--themeColor);
  color: #fff;
  font-size: 32rpx;
  font-weight: 600;
  display: flex;
  justify-content: center;
  align-items: center;
}

13.搜索中心

#.js
/*
1 输入框绑定 值改变事件 inp事件
   1 获取到输入框的值 
   2 合法性判断
   3 检验通过 把输入框的值 发送到后台
   4 返回的数据打印到页面
*/
import { request} from "../../request/index.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
Page({
  data: {
    goods:[],
    //取消按钮  是否显示
   isFocus:false,
   // 输入框的值
   inpValue:""
  },  
  TimeId:-1,
  // 输入框的值改变 就会触发事件
  handleInput(e){
    // 1 获取输入框的值
    const {value}=e.detail;
    // 2 检测合法性
    if(!value.trim()){
      this.setData({
        goods:[],
        isFocus:false
      })
      // 值不合法
      return;
    }   
      //准备发送请求获取数据
      this.setData({
        isFocus:true
      })
    // 3 准备发送请求获取数据
    clearTimeout(this.TimeId);
      this.TimeId = setTimeout(()=>{
        this.qsearch(value);
      },1000);
  },
  // 发送请求获取搜索建议
  async qsearch(query){
    const data=await request({url:"/goods/search",data:{query}});
    const message=data.data
    const goods=message.message
    const res=goods.goods
    console.log(res);
    this.setData({
      goods:res,  
    })
  },
  //点击取消按钮
  handleCancel(){
    this.setData({
      inpValue:"",
      isFocus:false,
      goods:[]
    })
  }
  })

#.json
{
  "usingComponents": {},
  "navigationBarTitleText": "搜索中心"
}

#.wxml
<view class="search_row">
<input value="{{inpValue}}" placeholder="请输入您要搜索的商品" bindinput="handleInput"></input>
<button bindtap="handleCancel" hidden="{{!isFocus}}">取消</button>
</view>
<view class="search_content">
<navigator  url="/pages/goos_detail/index?goods_id={{item.goods_id}}" class="search_item"
wx:for="{{goods}}"
wx:key="goods_id">
{{item.goods_name}}
</navigator>
</view> 

#.less
page{
    background-color: #dedede;
    padding: 20rpx;
}
.search_row{
    height: 75rpx;
    display: flex;
    input{
        background-color: #fff;
        flex: 1;
        height: 100%;
        padding-left: 100rpx;
    }
    button{
        width: 100rpx;
        height: 100%;
        font-size: 30rpx;
        padding: 0;
        margin: 0 10rpx;
        display: flex;
        justify-content: center;
        align-items: center;
    }
}

.search_content{
    margin-top: 30rpx;
    .search_item{
        background-color: #fff;
        font-size: 30rpx;
        padding: 15rpx 10rpx;
        border-bottom: 1rpx solid #ccc;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
}

#.wxss

page {
  background-color: #dedede;
  padding: 20rpx;
}
.search_row {
  height: 75rpx;
  display: flex;
}
.search_row input {
  background-color: #fff;
  flex: 1;
  height: 100%;
  padding-left: 100rpx;
}
.search_row button {
  width: 100rpx;
  height: 100%;
  font-size: 30rpx;
  padding: 0;
  margin: 0 10rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}
.search_content {
  margin-top: 30rpx;
}
.search_content .search_item {
  background-color: #fff;
  font-size: 30rpx;
  padding: 15rpx 10rpx;
  border-bottom: 1rpx solid #ccc;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

14.支付授权(auth)

#.js
import { request} from "../../request/index.js";
import regeneratorRuntime from '../../lib/runtime/runtime';
import { login} from "../../utils/asyncWx.js";
Page({
  // 获取用户信息
async  handleGetUserInfo(e){
   try {
      //console.log(e);
    // 1 获取用户信息
    const {encryptedData,rawData,iv,signature}=e.detail;
    // 2 获取小程序 登录成功  后的code值
    const {code}=await login();
    const loginParams={encryptedData,rawData,iv,signature,code};
   // console.log(code);
   // 3 发送请求 获取token值
   const token = await request ({url:"/users/wxlogin",data:loginParams,method:"post"});
  // console.log(res);
  // 4 把token 存入缓存中,同时跳转回上一个页面
  wx.setStorageSync("token", 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjIzLCJpYXQiOjE1NjQ3MzAwNzksImV4cCI6MTAwMTU2NDczMDA3OH0.YPt-XeLnjV-_1ITaXGY2FhxmCe4NvXuRnRB8OMCfnPo');
  wx-wx.navigateBack({
    delta: 1
  }); 
   } catch (error) {
     console.log(error);
   }
  }
})

#.json
{
  "usingComponents": {},
  "navigationBarTitleText": "支付授权"
}

#.wxml

<button type="primary" plain open-type="getUserInfo" bindgetuserinfo="handleGetUserInfo">
获取授权
</button>

#.wxss
button{
  margin-top: 40rpx;
  width: 70%;
}

15.个人中心(user)

#.js
// pages/user/index.js
Page({
  data: {
    userinfo:{},
    // 被收藏的商品数量
    collectNums:0
  },
  onShow(){
    const userinfo=wx.getStorageSync('userinfo');
    const collect=wx.getStorageSync('collect')||[];
    this.setData({userinfo,collectNums:collect.length})
  }
})

#.json
{
  "usingComponents": {},
  "navigationBarTitleText": "个人中心"
}

#.wxml

<view class="user_info_wrap">
<view wx:if="{{userinfo.avatarUrl}}" class="user_img_wrap">
<image class="user_bg" src="{{userinfo.avatarUrl}}"></image>
<view class="user_info">
<image class="user_icon" src="{{userinfo.avatarUrl}}"></image>
<view class="user_name">{{userinfo.nickName}}</view>
</view>
</view>
<view wx:else class="user_btn">
<navigator url="/pages/login/index" >登录</navigator>
</view>
</view>
<view class="user_content">

<view class="user_main">
<!-- 历史足迹 -->
<view class="history_wrap">
<navigator>
<view class="his_num">0</view>
<view class="his_name">收藏的店铺</view>
</navigator>
<navigator url="/pages/collect/index">
<view class="his_num">{{collectNums}}</view>
<view class="his_name">收藏的商品</view>
</navigator>
<navigator>
<view class="his_num">0</view>
<view class="his_name">关注的商品</view>
</navigator>
<navigator>
<view class="his_num">0</view>
<view class="his_name">我的足迹</view>
</navigator>
</view>
<!-- 我的订单 -->
<view class="orders_wrap">
<view class="orders_title">我的订单</view>
<view class="order_content">
<navigator url="/pages/order/index?type=1">
<view class="iconfont icon-dingdan"></view>
<view class="order_name">全部订单</view>
</navigator>
<navigator url="/pages/order/index?type=2">
<view class="iconfont icon-daifukuan"></view>
<view class="order_name">待付款</view>
</navigator>
<navigator url="/pages/order/index?type=3">
<view class="iconfont icon-daishouhuo"></view>
<view class="order_name">待收货</view>
</navigator>
<navigator>
<view class="iconfont icon-tuikuan"></view>
<view class="order_name">退款/退货</view>
</navigator>
</view>
</view>
<!-- 收货地址管理 -->
<view class="address_wrap">
收货地址管理
</view>
<!-- 应用信息相关 -->
<view class="app_info_wrap">
<view class="app_info_item app.info_contact">
<text>联系客服</text>
<text>1001011</text>
</view>
<navigator url="/pages/feedback/index" class="app_info_item">意见反馈</navigator>
<view class="app_info_item">关于我们</view>
</view>
<!-- 推荐 -->
<view class="recommond_wrap">把应用推荐给其他人 </view>
</view>
</view>

#.less
page{
    background-color: rgb(241, 241, 241);
}
.user_info_wrap{
    height: 45vh;
    overflow: hidden;
    background-color: var(--themeColor);
    .user_img_wrap{
        position: relative;
        .user_bg{
            height:60vh;
            // 高斯模糊
            filter: blur(10rpx);
        }
        .user_info{
            position: absolute;
            left: 50%;
            transform: translate(-50%);
            top: 30%;
            text-align: center;
        }
        .user_icon{
            width: 200rpx;
            height: 200rpx;
            border-radius: 50%;
        }
        .user_name{
            color: #fff;
            margin-top: 40rpx;
        }
    }
    .user_btn{
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        top:20%;
        border: 1rpx solid greenyellow;
        color: greenyellow;
        font-size: 38rpx;
        padding: 30rpx;
        border-radius: 10rpx;
    }
}


.user_content{
    position: relative;
    .user_main{
        color: #666;
        padding: 15rpx;
        position: absolute;
        width: 90%;
        left: 50%;
        transform: translateX(-50%);
        top:-40rpx;

        .history_wrap{
            background-color: #fff;
            display: flex;
            navigator{
                flex: 1;
                text-align: center;
                padding: 10rpx 0;
                .his_num{
                    color: var(--themeColor);
                }
                .his_name{}
            }
        } 
        .orders_wrap{
            background-color: #fff;
            margin-top: 30rpx;
            .orders_title{
                padding: 20rpx;
                border-bottom: 1rpx solid #ccc;
            }
            .order_content{
                display: flex;
                navigator{
                    padding: 15rpx 0;
                    flex: 1;
                    text-align: center;
                    .iconfont{
                        color: var(--themeColor);
                    }
                    .order_name{}
                }
            }
        }
        .address_wrap{
            margin-top: 30rpx;
            background-color: #fff;
            padding: 20rpx;
        }
        .app_info_wrap{
            margin-top: 30rpx;
            background-color: #fff; 

            .app_info_item{                
                border-bottom: 1rpx solid #000;
                padding: 20rpx;
            }
            .app.info_contact{
                display: flex;
                justify-content: space-between;
            }
        }
        .recommond_wrap{
            margin-top: 30rpx;
            background-color: #fff;
            padding: 20rpx;
        }
    }
}
#.wxss
page {
  background-color: #f1f1f1;
}
.user_info_wrap {
  height: 45vh;
  overflow: hidden;
  background-color: var(--themeColor);
}
.user_info_wrap .user_img_wrap {
  position: relative;
}
.user_info_wrap .user_img_wrap .user_bg {
  height: 60vh;
  filter: blur(10rpx);
}
.user_info_wrap .user_img_wrap .user_info {
  position: absolute;
  left: 50%;
  transform: translate(-50%);
  top: 30%;
  text-align: center;
}
.user_info_wrap .user_img_wrap .user_icon {
  width: 200rpx;
  height: 200rpx;
  border-radius: 50%;
}
.user_info_wrap .user_img_wrap .user_name {
  color: #fff;
  margin-top: 40rpx;
}
.user_info_wrap .user_btn {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 20%;
  border: 1rpx solid greenyellow;
  color: greenyellow;
  font-size: 38rpx;
  padding: 30rpx;
  border-radius: 10rpx;
}
.user_content {
  position: relative;
}
.user_content .user_main {
  color: #666;
  padding: 15rpx;
  position: absolute;
  width: 90%;
  left: 50%;
  transform: translateX(-50%);
  top: -40rpx;
}
.user_content .user_main .history_wrap {
  background-color: #fff;
  display: flex;
}
.user_content .user_main .history_wrap navigator {
  flex: 1;
  text-align: center;
  padding: 10rpx 0;
  font-size: 30rpx;
}
.user_content .user_main .history_wrap navigator .his_num {
  color: var(--themeColor);
}
.user_content .user_main .orders_wrap {
  background-color: #fff;
  margin-top: 30rpx;
}
.user_content .user_main .orders_wrap .orders_title {
  padding: 20rpx;
  border-bottom: 1rpx solid #ccc;
}
.user_content .user_main .orders_wrap .order_content {
  display: flex;
}
.user_content .user_main .orders_wrap .order_content navigator {
  padding: 15rpx 0;
  flex: 1;
  text-align: center;
}
.user_content .user_main .orders_wrap .order_content navigator .iconfont {
  color: var(--themeColor);
}
.user_content .user_main .address_wrap {
  margin-top: 30rpx;
  background-color: #fff;
  padding: 20rpx;
}
.user_content .user_main .app_info_wrap {
  margin-top: 30rpx;
  background-color: #fff;
}
.user_content .user_main .app_info_wrap .app_info_item {
  border-bottom: 1rpx solid #000;
  padding: 20rpx;
}
.user_content .user_main .app_info_wrap .app.info_contact {
  display: flex;
  justify-content: space-between;
}
.user_content .user_main .recommond_wrap {
  margin-top: 30rpx;
  background-color: #fff;
  padding: 20rpx;
}

16.登录(login)

#.js
// pages/login/index.js
Page({
  handleGetUserInfo(e){
    // console.log(e);
    const{userInfo}=e.detail;
    wx.setStorageSync('userinfo', userInfo)
    wx.navigateBack({
      delta: 1,
    })
  }
})

#.json
{
  "usingComponents": {},
  "navigationBarTitleText": "登录"
}
#.wxml

<button type="primary" plain open-type="getUserInfo" bindgetuserinfo="handleGetUserInfo" > 登录 </button>

#.wxss
button{
  margin-top: 40rpx;
  width: 70%;
}

17.意见反馈(feedback)

#.js
/*
1 点击“+”触发tap点击事件
  1 调小程序内置的 选择图片的api
  2 获取到图片的路径数组
  3 把图片路径存到data变量中 
  4 页面就可以根据图片数组进行循环显示 自定义组件
1 点击 自定义图片 组件
  1 获取被点击的元素的索引
  2 获取data中的图片数组
  3 根据索引 数组中删除对应的元素
  4 把数组重新设置回data中
3 点击“提交”
  1 获取文本域的内容
     1 data中定义变量 类似 输入框的获取
     2 文本域 绑定输入事件 事件触发的时候 把输入框的值 存入到变量中
  2 对这些内容 合法性验证
  3 验证通过 用户选择的图片 上传到专门的图片服务器 返回图片外网的链接
      1 遍历图片数组
      2 挨个上传
      3 自己再维护图片数组 存放图片上传后的外网的链接
  4 文本域 和外网的图片的路径 一起提交到服务器(前端的模拟 不会发送到后台)
  5 清空当前页面
  6 返回上一页
*/
Page({
  data: {
    tabs:[

    ],
      // 被选中的图片路径 数组
      chooseImgs:[],
      // 文本域的内容
      textVal:""
  },
  // 外网的图片的路径数组 
  UpLoadImgs:[],
  handleTabsItemChange(e){
    // 1 获取被点击的标题索引
    const {index}=e.detail;
    // 2 修改源数组
    let{tabs}=this.data;
    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);
    // 3 赋值到data中
    this.setData({
      tabs
    })
  },  
  // 点击“+”选择图片
  handleChooseImg(){
    // 2 调用小程序内置的选择图片api
    wx.chooseImage({
      // 同时选中图片的数量
      count: 9,
      // 图片的格式 原图 压缩
      sizeType:['original', 'compressed']	,
      // 图片的来源 相册 照相机
      sourceType:['album', 'camera'],
      success:(result)=>{
        this.setData({
          // 图片数组 进行拼接
          chooseImgs:[...this.data.chooseImgs,...result.tempFilePaths]
        })
      }

    })

  },
  // 点击自定义图片组件
  handleRemoveImg(e){
    // 2 获取被点击的事件索引
    const{index}=e.currentTarget.dataset;
    // 3 获取data中的图片数组
    let{chooseImgs}=this.data;
    // 4 删除元素
    chooseImgs.splice(index,1);
    this.setData({
      chooseImgs
    })

  },
  // 文本域的输入事件
  handleTextInput(e) {
    this.setData({
      textVal: e.detail.value
    })
  },
  // 提交按钮的点击
  handleFormSumbit(){
    // 1 获取文本域的内容
    const{textVal,chooseImgs}=this.data;
    // 2 合法性的验证
    if(!textVal.trim()){
      // 不合法
      wx.showToast({
        title: '输入不合法',
        icon:"none",
        mask:true
      });
      return;
    }
    // 3 准备上传图片到专门的服务器
    // 上传文件的api 不支持 多个文件同时上传 (可以遍历数组 一个一个上传)
    // 显示正在等待的图片
    wx.showLoading({
      title: '正在上传中',
      mask:true
    })
    // 判断有没有需要上传的数组
    if(chooseImgs.length!=0){
    chooseImgs.forEach((v,i)=>{
      wx.uploadFile({
        // 图片要上传到哪里
        url: 'https://media.mogu.com/image/scale?appKey=15m&w=500&h=500&quality=100',
        // 被上传的文件的路径
        filePath: v,
        // 上传的文件的名称 后台来获取文件  file
        name: "image",
        // 顺带的文本信息
        formData: {},
        success: (result) => {
          console.log(result);
          let url=JSON.parse (result.data);
          this.UpLoadImgs.push(url);
          // 所有的图片都上传完毕了才触发
          if(i==chooseImgs.length-1){
            //
            console.log("把文本内容和外网图片数组提交到后台");
            // 页面提交成功
            // 重置页面 
            this.setData({
              textVal:"",
              chooseImage:[]
            })
            //返回上一个页面
            wx.navigateBack({
              delta: 1,
            })
          }
        }
      });
    })
  }else{
    console.log("只是提交了文本");
    wx.navigateBack({
      delta: 1,      
    })
    wx.showToast({
      title: '提交成功!',  // 标题
      icon: 'success',   // 图标类型,默认success
      duration: 1000   // 提示窗停留时间,默认1500ms
  })
  }
  }
})

#.json

{
  "usingComponents": {
    "Tabs":"../../components/Tabs/Tabs",
    "UpImg":"../../components/UpImg/UpImg"
  },
  "navigationBarTitleText": "意见反馈"
}

#.wxml

<Tabs tabs="{{tabs}}" bindtabsItemChange="handleTabsItemChange" style="background-color: white;" >
<view class="fb_main">
<view class="fb_title">问题的种类</view>
<view class="fb_tips"> 
<text>功能建议</text>
<text>购买遇到问题</text>
<text>性能问题</text>
<text>其他</text>
</view>
<view class="fb_content">
<textarea value="{{textVal}}" bindinput="handleTextInput" placeholder="请描述一下你的问题" ></textarea>
<view class="fb_tool">
<button bindtap="handleChooseImg">+</button>
<view class="up_img_item"
wx:for="{{chooseImgs}}"
wx:key="*this"
bindtap="handleRemoveImg"
data-index="{{index}}"
>
<UpImg src="{{item}}"></UpImg></view>
</view>
</view>
<view class="form_btn_wrap">
<button bindtap="handleFormSumbit" type="warn">
<icon type="success_no_circle" color="white" size="15" ></icon>
提交
</button>
</view>
</view>
</Tabs> 

#.less
page{
    background-color: #dedede;
}
.fb_main {
    padding: 20rpx;
    color: #666;
    .fb_title {
  
    }
  
    .fb_tips {
        display: flex;
        flex-wrap: wrap;
      text {
          width: 30%;
          padding: 10rpx;
          text-align: center;
          font-size: 30rpx;
          background-color: #fff;
          margin: 10rpx;
  
      }
    }
  
    .fb_content {
        background-color: #fff;
        padding: 10rpx;
        margin-top: 40rpx;
        textarea{
            padding: 10rpx;
        }
        .fb_tool{
            display: flex;
            flex-wrap: wrap;
            padding-bottom: 10rpx;
            button{
                margin: 0;
                width: 120rpx;
                height: 120rpx;
                font-size: 80rpx;
                padding: 0;
                display: flex;
                justify-content: center;
                align-items: center;
                margin-left: 20rpx;
                color: #ccc;
              
            }
            .up_img_item{
                margin-top: 20rpx;
                margin-left: 20rpx;
            }
        }
  
    }
  
    .form_btn_wrap {
        margin-top: 20rpx;
        display: flex;
        justify-content: flex-end;
        button{
            margin: 0;
            width: 30%;

        }
  
    }
  }

#wxss

page {
  background-color: #dedede;
}

.fb_main {
  padding: 20rpx;
  color: #666;
}
.fb_main .fb_tips {
  display: flex;
  flex-wrap: wrap;
}
.fb_main .fb_tips text {
  width: 30%;
  padding: 10rpx;
  text-align: center;
  font-size: 30rpx;
  background-color: #fff;
  margin: 10rpx;
}
.fb_main .fb_content {
  background-color: #fff;
  padding: 10rpx;
  margin-top: 40rpx;
}
.fb_main .fb_content textarea {
  padding: 10rpx;
}
.fb_main .fb_content .fb_tool {
  display: flex;
  flex-wrap: wrap;
  padding-bottom: 10rpx;
}
.fb_main .fb_content .fb_tool button {
  margin: 0;
  width: 120rpx;
  height: 120rpx;
  font-size: 80rpx;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-left: 20rpx;
  color: #ccc;
}
.fb_main .fb_content .fb_tool .up_img_item {
  margin-top: 20rpx;
  margin-left: 20rpx;
}
.fb_main .form_btn_wrap {
  margin-top: 20rpx;
  display: flex;
  justify-content: flex-end;
}
.fb_main .form_btn_wrap button {
  margin: 0;
  width: 30%;
}

18.request

#.js

// 同步发送异步代码的次数
let ajaxTimes=0;
export const request=(params)=>{
  // 判断 url中是否带有/my/ 请求的是私有路径 带上header token
  let header={ ...params,header};
  if(params.url.includes("/my/")){
    // 拼接header 带上 token
    header["Authorization"]=wx.getStorageSync('token');
  }
  ajaxTimes++;
  //显示加载中 效果 
  wx.showLoading({
    title: '加载中',
    mask:true
  });
  //定义公共的url
  const baseUrl="https://api-hmugo-web.itheima.net/api/public/v1"
  return new Promise((resolve,reject)=>{
    wx.request({
      ...params,
      header:header,
      url:baseUrl+params.url,
      success:(result)=>{
        resolve(result);
      },
      fail:(err)=>{
        reject(err);
      },
      complete:()=>{
        ajaxTimes--;
        if(ajaxTimes===0){
          //关闭正在等待的图标
          wx.hideLoading();  
        }
      }
    });
  })
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值