微信小程序仿网易严选(附精选源码32套,涵盖商城团购等)

news2024/11/23 13:23:07

商城主要实现的功能

  • 首页、专题、分类、购物车、我的
  • 小程序授权登陆获取用户信息
  • 首页包含品牌制造页、品牌制造详情页面、新品首发页面、人气推荐页面、各分类列表
  • 商品详情页面,包含常见问题、大家都在看商品列表、加入购物车、收藏商品、立即购买、下订单、选择收货地址
  • 搜索功能,包含历史记录、热门搜索、搜索后列表展示、模糊搜索提示
  • 商品列表部分包含综合、价格高低进行排序
  • 专题功能,包含专题详情、专题推荐列表
  • 分类,包含左边大分类和右边详细分类
  • 购物车,包含商品单选全选、左滑删除商品、下订单等功能
  • 地址管理,包含新建地址和导入微信地址,地址编辑、左滑删除、设置默认地址
  • 我的页,包含我的收藏、地址管理、意见反馈

此项目仅供学习参考

项目预览- 首页

在这里插入图片描述

项目预览- 专题

在这里插入图片描述

项目预览- 分类

在这里插入图片描述
在这里插入图片描述

项目预览- 购物车

在这里插入图片描述
在这里插入图片描述

项目运行修改成自己的信息

    var userInfo = {"openId":"oQmbb4sNZdxaUQZ0sfYgvtOP2S7c","nickName":"何玉硕","gender":1,"language":"zh_CN","city":"Changping","province":"Beijing","country":"China","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTIbWFEIJj8IpGeHM7dGic1aTFZALjWcMm9ltWfFiaQfVRYticWBfgGfzXWMt2EkJWiaicPtftHAlWxUibxQ/132","watermark":{"timestamp":1535513485,"appid":"wx601ce71bde7b9add"}};
      var openId = userInfo.openId;
      wx.setStorageSync("userInfo", userInfo);
      wx.setStorageSync("openId", openId);

前言

一直打算自己写接口,写一个上线的小程序,数据方面总是无从下手,无意中发现一个网友爬取的网易严选商城的一些数据大概一共有 20 张左右的表,算是相当详细了(对其中部分表的字段和部分数据进行了修改,)平时写项目大部分用的 vue,所以直接选择了 mpvue 开发,后端一开始打算用 php 但是学了半个月感觉需要学的东西太多,短时间里写不出这个线上小程序,最后决定用 node 来开发提供接口。

部分代码说明

请求封装

const host = 'https://www.heyuhsuo.xyz/heyushuo';
export {
  host
}
//请求封装
function request(url, method, data, header = {}) {
  wx.showLoading({
    title: '加载中' //数据请求前loading
  })
  return new Promise((resolve, reject) => {
    wx.request({
      url: host + url, //仅为示例,并非真实的接口地址
      method: method,
      data: data,
      header: {
        'content-type': 'application/json' // 默认值
      },
      success: function (res) {
        wx.hideLoading();
        resolve(res.data)
      },
      fail: function (error) {
        wx.hideLoading();
        reject(false)
      },
      complete: function () {
        wx.hideLoading();
      }
    })
  })
}
export function get(url, data) {
  return request(url, 'GET', data)
}
export function post(url, data) {
  return request(url, 'POST', data)
}

用户是否登录 未登录跳转到登录页面

export function toLogin() {
  const userInfo = wx.getStorageSync('userInfo');
  if (!userInfo) {
    wx.navigateTo({
      url: "/pages/login/main"
    });
  } else {
    return true;
  }
}

export function login() {
  const userInfo = wx.getStorageSync('userInfo');
  if (userInfo) {
    return userInfo;
  }
}
export function getStorageOpenid() {
  const openId = wx.getStorageSync("openId");
  if (openId) {
    return openId;
  } else {
    return ''
  }
}

首页code

<template>
  <div class="index">
    <div class="search">
      <div @click="toMappage">{{cityName}}</div>
      <div @click="toSearch">
        <input type="text" placeholder="搜索商品">
        <span class="icon"></span>
      </div>
    </div>
    <div class="swiper">
      <swiper class="swiper-container" indicator-dots="true" autoplay="true" interval="3000" circular="true" duration="500">
        <block v-for="(item, index) in banner " :key="index">
          <swiper-item class="swiper-item">
            <image :src="item.image_url" class="slide-image" />
          </swiper-item>
        </block>
      </swiper>
    </div>
    <div class="channel">
      <div @click="categoryList(item.id)" v-for="(item, index) in channel" :key="index">
        <img :src="item.icon_url" alt="">
        <p>{{item.name}}</p>
      </div>
    </div>
    <div class="brand">
      <div @click="tobrandList" class="head">
        品牌制造商直供
      </div>
      <div class="content">
        <div @click="branddetail(item.id)" v-for="(item, index) in brandList" :key="index">
          <div>
            <p>{{item.name}}</p>
            <p>{{item.floor_price}}元起</p>
          </div>
          <img :src="item.new_pic_url" alt="">
        </div>
      </div>
    </div>
    <div class="newgoods">
      <div @click="goodsList('new')" class="newgoods-top">
        <div class="top">
          <p>新品首发</p>
          <p>查看全部</p>
        </div>
      </div>
      <div class="list">
        <ul>
          <scroll-view class="scroll-view" :scroll-x="true">
            <li @click="goodsDetail(item.id)" v-for="(item, index) in newGoods" :key="index">
              <img :src="item.list_pic_url" alt="">
              <p>{{item.name}}</p>
              <p>{{item.goods_brief}}</p>
              <p>¥{{item.retail_price}}</p>
            </li>
          </scroll-view>
        </ul>
      </div>
    </div>
    <div class="newgoods hotgoods">
      <div @click="goodsList('hot')" class="newgoods-top">
        <div class="top">
          <p>人气推荐
            <span></span> 好物精选</p>
          <p>查看全部</p>
        </div>
      </div>
      <div class="list">
        <ul>
          <scroll-view class="scroll-view" :scroll-x="true">
            <li @click="goodsDetail(item.id)" v-for="(item, index) in hotGoods" :key="index">
              <img :src="item.list_pic_url" alt="">
              <p>{{item.name}}</p>
              <p>{{item.goods_brief}}</p>
              <p>¥{{item.retail_price}}</p>
            </li>
          </scroll-view>
        </ul>
      </div>
    </div>
    <div class="topicList">
      <div @click="totopic" class="topicList-top">
        专题精选
        <span class="icon"></span>
      </div>
      <div class="list">
        <ul>
          <scroll-view class="scroll-view" :scroll-x="true">
            <li @click="topicdetail(item.id)" v-for="(item, index) in topicList" :key="index">
              <img :src="item.item_pic_url" alt="">
              <div class="btom">
                <div>
                  <p>{{item.title}}</p>
                  <p>{{item.subtitle}}</p>
                </div>
                <div>
                  {{item.price_info}}元起
                </div>
              </div>
            </li>
          </scroll-view>
        </ul>
      </div>
    </div>
    <div class="newcategory">
      <div class="list" v-for="(item, index) in newCategoryList" :key="index">
        <div class="head">{{item.name}}好物</div>
        <div class="sublist">
          <div @click="goodsDetail(subitem.id)" v-for="(subitem, subindex) in item.goodsList" :key="subindex">
            <img :src="subitem.list_pic_url" alt="">
            <p>{{subitem.name}}</p>
            <p>¥{{subitem.retail_price}}</p>
          </div>
          <div @click="categoryList(item.id)">
            <div class="last">
              <p>{{item.name}}好物</p>
              <span class="icon"></span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import amapFile from "../../utils/amap-wx";
import { get } from "../../utils";
import { mapState, mapMutations } from "vuex";
export default {
  onLoad() {
    this.getCityName();
  },
  onShow() {
    if (wx.getStorageSync("cityName")) {
      this.cityName = wx.getStorageSync("cityName");
      wx.removeStorageSync("cityName");
    }
  },
  computed: {
    ...mapState(["cityName"])
  },
  mounted() {
    this.getData();
  },
  data() {
    return {
      banner: [],
      channel: [],
      brandList: [],
      newGoods: [],
      hotGoods: [],
      topicList: [],
      newCategoryList: []
    };
  },
  components: {},
  methods: {
    ...mapMutations(["update"]),
    toMappage() {
      var _this = this;
      // 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope
      wx.getSetting({
        success(res) {
          //如果没有同意授权,打开设置
          if (!res.authSetting["scope.userLocation"]) {
            wx.openSetting({
              success: res => {
                _this.getCityName();
              }
            });
          } else {
            wx.navigateTo({
              url: "/pages/mappage/main"
            });
          }
        }
      });
    },
    getCityName() {
      var _this = this;
      var myAmapFun = new amapFile.AMapWX({
        key: "e545e7f79a643f23aef187add14e4548"
      });
      myAmapFun.getRegeo({
        success: function(data) {
          //成功回调
          console.log(data);
          // data[0].regeocodeData.formatted_address
          _this.cityName = data[0].regeocodeData.formatted_address;
          _this.update({ cityName: data[0].regeocodeData.formatted_address });
        },
        fail: function(info) {
          //失败回调
          console.log(info);
          //如果用户拒绝授权
          // 默认为北京
          _this.cityName = "北京市";
          _this.update({ cityName: "北京市" });
        }
      });
    },
    toSearch() {
      wx.navigateTo({
        url: "/pages/search/main"
      });
    },
    async getData() {
      const data = await get("/index/index");
      this.banner = data.banner;
      this.channel = data.channel;
      this.brandList = data.brandList;
      this.newGoods = data.newGoods;
      this.hotGoods = data.hotGoods;
      this.topicList = data.topicList;
      this.newCategoryList = data.newCategoryList;
    },
    goodsDetail(id) {
      wx.navigateTo({
        url: "/pages/goods/main?id=" + id
      });
    },
    categoryList(id) {
      wx.navigateTo({
        url: "/pages/categorylist/main?id=" + id
      });
    },
    goodsList(info) {
      if (info == "hot") {
        wx.navigateTo({
          url: "/pages/newgoods/main?isHot=" + 1
        });
      } else {
        wx.navigateTo({
          url: "/pages/newgoods/main?isNew=" + 1
        });
      }
    },
    topicdetail(id) {
      wx.navigateTo({
        url: "/pages/topicdetail/main?id=" + id
      });
    },
    totopic() {
      wx.navigateTo({
        url: "/pages/topic/main"
      });
    },
    tobrandList() {
      wx.navigateTo({
        url: "/pages/brandlist/main"
      });
    },
    branddetail(id) {
      wx.navigateTo({
        url: "/pages/branddetail/main?id=" + id
      });
    }
  },
  created() {}
};
</script>

<style lang='scss' scoped>
@import "./style.scss";
</style>

搜索功能页

<template>
  <div class="search">
    <div class="head">
      <div>
        <img src="http://nos.netease.com/mailpub/hxm/yanxuan-wap/p/20150730/style/img/icon-normal/search2-2fb94833aa.png" alt="">
        <input type="text" confirm-type="search" focus="true" v-model="words" @focus="inputFocus" @input="tipsearch" @confirm="searchWords"
          placeholder="商品搜索">
        <!-- <input name="input" class="keywrod" focus="true" value="{{keyword}}" confirm-type="search" bindinput="inputChange" bindfocus="inputFocus" bindconfirm="onKeywordConfirm" confirm-type="search" placeholder="{{defaultKeyword.keyword}}" /> -->
        <img @click="clearInput" class="del" src="http://nos.netease.com/mailpub/hxm/yanxuan-wap/p/20150730/style/img/icon-normal/clearIpt-f71b83e3c2.png"
          alt="">
      </div>
      <div @click="cancel">取消</div>
    </div>
    <div class="searchtips" v-if="words">
      <div @click="searchWords" v-if="tipsData.length!=0" :data-value="item.name" v-for="(item,index) in tipsData" :key="index">
        {{ item.name }}
      </div>
      <div v-if="tipsData.length==0" class="nogoods">
        数据库暂无此类商品...
      </div>
    </div>
    <div class="history" v-if="historyData.length!=0">
      <div class="t">
        <div>历史记录</div>
        <div @click="clearHistory">

        </div>
      </div>
      <div class="cont">
        <div @click="searchWords" :data-value="item.keyword" v-for="(item,index) in historyData" :key="index">
          {{item.keyword}}
        </div>
      </div>
    </div>
    <div class="history hotsearch">
      <div class="t">
        <div>热门搜索</div>
      </div>
      <div class="cont">
        <div @click="searchWords" v-for="(item,index) in hotData" :data-value="item.keyword" :class="{active:0==index}" :key="index">
          {{item.keyword}}
        </div>
      </div>
    </div>
    <!--商品列表  -->
    <div v-if="listData.length!=0" class="goodsList">
      <div class="sortnav">
        <div @click="changeTab(0)" :class="[0==nowIndex ?'active':'']">综合</div>
        <div @click="changeTab(1)" class="price" :class="[1==nowIndex ?'active':'', order =='desc'? 'desc':'asc']">价格</div>
        <div @click="changeTab(2)" :class="[2==nowIndex ?'active':'']">分类</div>
      </div>
      <div class="sortlist">
        <div @click="goodsDetail(item.id)" v-for="(item, index) in listData" :key="index" :class="[(listData.length)%2==0?'active':'none']"
          class="item">
          <img :src="item.list_pic_url" alt="">
          <p class="name">{{item.name}}</p>
          <p class="price">¥{{item.retail_price}}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import {
    post,
    get
  } from "../../utils";
  export default {
    onLoad() {
      this.initData();
    },
    created() {},
    mounted() {
      this.openid = wx.getStorageSync("openid") || "";
      this.getHotData();
    },
    data() {
      return {
        nowIndex: 0,
        words: "",
        historyData: [],
        hotData: [],
        tipsData: [],
        listData: [],
        openid: "",
        order: "",
        isHot: "",
        isNew: ""
      };
    },
    components: {},
    methods: {
      initData() {
        this.nowIndex = 0
        this.words = ""
        this.historyData = []
        this.hotData = []
        this.tipsData = []
        this.listData = []
        this.openid = ""
        this.order = ""
        this.isHot = ""
        this.isNew = ""
      },
      goodsDetail(id) {
        wx.navigateTo({
          url: "/pages/goods/main?id=" + id
        });
      },
      cancel() {
        wx.navigateBack({
          delta: 1 //返回的页面数,如果 delta 大于现有页面数,则返回到首页,
        });
      },
      clearInput() {
        this.words = "";
        this.listData = [];
        this.tipsData = [];
      },
      inputFocus() {
        //商品清空
        this.listData = [];
        //展示搜索提示信息
        this.tipsearch();
      },
      async getlistData() {
        //获取商品列表
        const data = await get("/search/helperaction", {
          keyword: this.words,
          order: this.order
        });
        this.listData = data.keywords;
        this.tipsData = [];
      },
      changeTab(index) {
        this.nowIndex = index;
        if (index == 1) {
          this.order = this.order == "asc" ? "desc" : "asc";
        } else {
          this.order = "";
        }
        this.getlistData();
      },
      async clearHistory() {
        const data = await post("/search/clearhistoryAction", {
          openId: this.openid
        });
        console.log(data);
        if (data) {
          this.historyData = [];
        }
      },
      async searchWords(e) {
        var vaule = e.currentTarget.dataset.value;
        this.words = vaule || this.words;
        const data = await post("/search/addhistoryaction", {
          openId: this.openid,
          keyword: vaule || this.words
        });
        console.log(data);
        //获取历史数据
        this.getHotData();
        //获取商品列表
        this.getlistData();
      },
      async getHotData(first) {
        const data = await get("/search/indexaction?openId=" + this.openid);
        this.hotData = data.hotKeywordList;
        this.historyData = data.historyData;
      },
      async tipsearch(e) {
        const data = await get("/search/helperaction", {
          keyword: this.words
        });
        this.tipsData = data.keywords;
      },
      topicDetail(id) {
        wx.navigateTo({
          url: "/pages/topicdetail/main?id=" + id
        });
      }
    },
    computed: {}
  };

</script>
<style lang='scss' scoped>
  @import "./style";

</style>

分类页面

<template>
  <div class="category">
    <div class="search" @click="tosearch">
      <div class="ser">
        <span class="icon"></span>
        <span>商品搜索,共239款好物</span>
      </div>

    </div>
    <div class="content">
      <scroll-view class="left" scroll-y="true">
        <div class="iconText" @click="selectitem(item.id,index)" v-for="(item, index) in listData" :class="[index==nowIndex?'active':'']" :key="index">
          {{item.name}}
        </div>
      </scroll-view>
      <scroll-view class="right" scroll-y="true">
        <div class="banner">
          <img :src="detailData.banner_url" alt="">
        </div>
        <div class="title">
          <span></span>
          <span>{{detailData.name}}分类</span>
          <span></span>
        </div>
        <div class="bottom">
          <div @click="categoryList(item.id)" v-for="(item,index) in detailData.subList" :key="index" class="item">
            <img :src="item.wap_banner_url" alt="">
            <span>{{item.name}}</span>
          </div>
        </div>
      </scroll-view>
    </div>
  </div>
</template>

<script>
import { get } from "../../utils";
export default {
  created() {},
  mounted() {
    //获取列表数据
    this.getListData();
    //获取默认右侧数据
    this.selectitem(this.id, this.nowIndex);
  },
  data() {
    return {
      id: "1005000",
      nowIndex: 0,
      listData: [],
      detailData: {}
    };
  },
  components: {},
  methods: {
    tosearch() {
      wx.navigateTo({ url: "/pages/search/main" });
    },
    async selectitem(id, index) {
      this.nowIndex = index;
      const data = await get("/category/currentaction", {
        id: id
      });
      this.detailData = data.data.currentOne;
    },
    async getListData() {
      const data = await get("/category/indexaction");
      this.listData = data.categoryList;
    },
    categoryList(id) {
      console.log("tiaozhuan");

      wx.navigateTo({
        url: "../categorylist/main?id=" + id
      });
    }
  },
  computed: {}
};
</script>
<style lang='scss' scoped>
@import "./style";
</style>

购物车页面

<template>
  <div class="cart">
    <div class="top">
      <div>30天无忧退货</div>
      <div>48小时快速退款</div>
      <div>满88元免邮费</div>
    </div>
    <div class="cartlist">
      <!--  -->
      <div class="item" @touchstart="startMove" @touchmove="deleteGoods" @touchend="endMove" :data-index="index" v-for="(item,index) in listData"
        :key="index">
        <div class="con" :style="item.textStyle">
          <div class="left">
            <div class="icon" @click="changeColor(index,item.goods_id)" :class="[ Listids[index] ? 'active' : '',{active:allcheck}]"></div>
            <div class="img">
              <img :src="item.list_pic_url" alt="">
            </div>
            <div class="info">
              <p>{{item.goods_name}}</p>
              <p>¥{{item.retail_price}}</p>
            </div>
          </div>
          <div class="right">
            <div class="num">
              x{{item.number}}
            </div>
          </div>
        </div>

        <div @click="delGoods(item.id,index)" class="delete" :style="item.textStyle1">
          <div>
            删除
          </div>
        </div>

      </div>
    </div>
    <div v-if="false" class="nogoods">
      <img src="http://nos.netease.com/mailpub/hxm/yanxuan-wap/p/20150730/style/img/icon-normal/noCart-a8fe3f12e5.png" alt="">
    </div>
    <div class="fixed">
      <div @click="allCheck" :class="{active:allcheck}" class="left">
        全选({{isCheckedNumber}})
      </div>
      <div class="right">
        <div>
          ¥{{allPrise}}
        </div>
        <div @click="orderDown">下单</div>
      </div>
    </div>
  </div>
</template>

<script>
  import {
    get,
    post,
    login,
    getStorageOpenid
  } from "../../utils";
  export default {
    onShow() {
      this.openId = getStorageOpenid();
      this.getListData();
    },
    created() {},
    data() {
      return {
        openId: "",
        allcheck: false,
        listData: [],
        Listids: [],
        userInfo: {},
        tranX: 0,
        tranX1: 0,
        startX: "",
        startY: "",
        moveX: "",
        moveY: "",
        moveEndX: "",
        moveEndY: "",
        X: 0,
        Y: ""
      };
    },
    components: {},
    methods: {
      initTextStyle() {
        //滑动之前先初始化数据
        for (var i = 0; i < this.listData.length; i++) {
          this.listData[i].textStyle = "";
          this.listData[i].textStyle1 = "";
        }
      },
      startMove(e) {
        this.initTextStyle();
        this.startX = e.touches[0].pageX;
        this.startY = e.touches[0].pageY;
      },
      deleteGoods(e) {
        //滑动之前先初始化样式数据
        this.initTextStyle();
        var index = e.currentTarget.dataset.index;
        console.log(index);
        if (this.X <= -100) {
          this.flag = true;
        }
        if (!this.flag) {
          this.moveX = e.touches[0].pageX;
          this.moveY = e.touches[0].pageY;
          this.X = this.moveX - this.startX;
          this.Y = this.moveX - this.startY;
          this.listData[index].textStyle = `transform:translateX(${this.tranX}rpx);`;
          if (this.X >= 100) {
            this.X = 0;
          }
          this.tranX = this.X;
          if (this.X <= -100) {
            this.X = -100;
          }
          this.tranX1 = this.X;
          this.listData[index].textStyle1 = `transform:translateX(${this.tranX1}rpx);`;
        } else {
          this.moveX = e.touches[0].pageX;
          this.moveY = e.touches[0].pageY;
          this.X = this.moveX - this.startX;
          this.Y = this.moveX - this.startY;

          this.tranX = this.X - 100;
          this.listData[index].textStyle = `transform:translateX(${this.tranX}rpx);`;
          // transform:'translateX(' + tranX + 'rpx)'
          console.log("heyushuo");

          console.log(this.listData[index].textStyle);

          if (this.X + -100 > -100) {
            this.flag = false;
          }
          this.tranX1 = -100;
          this.listData[index].textStyle1 = `transform:translateX(-100rpx);`;
          console.log(this.listData[index].textStyle1);
          // this.listData = this.listData;
        }
        // if (Math.abs(this.X) > Math.abs(this.Y) && this.X > 20) {
        //   this.scrollflag = false;
        // } else if (Math.abs(this.X) > Math.abs(this.Y) && this.X < 20) {
        //   console.log("right 2 left");
        // }
      },
      endMove(e) {
        var index = e.currentTarget.dataset.index;
        if (this.X > -50) {
          this.tranX1 = 0;
          this.tranX = 0;
          this.listData[index].textStyle = `transform:translateX(${this.tranX}rpx);`;
          this.listData[index].textStyle1 = `transform:translateX(${this.tranX1}rpx);`;
        } else if (this.X <= -50) {
          this.tranX1 = -100;
          this.tranX = -100;
          this.listData[index].textStyle = `transform:translateX(${this.tranX}rpx);`;
          this.listData[index].textStyle1 = `transform:translateX(${this.tranX1}rpx);`;
        }
      },
      async orderDown() {
        if (this.Listids.length == 0) {
          wx.showToast({
            title: "请选择商品",
            icon: "none",
            duration: 1500
          });
          return false;
        }
        // 去掉数组中空的false的
        var newgoodsid = [];
        for (let i = 0; i < this.Listids.length; i++) {
          const element = this.Listids[i];
          if (element) {
            newgoodsid.push(element);
          }
        }
        var goodsId = newgoodsid.join(",");
        const data = await post("/order/submitAction", {
          goodsId: goodsId,
          openId: this.openId,
          allPrise: this.allPrise
        });
        if (data) {
          wx.navigateTo({
            url: "/pages/order/main"
          });
        }
      },
      async delGoods(id, index) {
        var _this = this;
        wx.showModal({
          title: "",
          content: "是否要删除该商品",
          success: function (res) {
            if (res.confirm) {

              _this.Listids.splice(index, 1);
              const data = get("/cart/deleteAction", {
                id: id
              }).then(() => {
                _this.getListData();
              });
            } else if (res.cancel) {
              console.log("用户点击取消");
              //滑动之前先初始化样式数据
              _this.initTextStyle();
            }
          }
        });
      },
      async getListData() {
        const data = await get("/cart/cartList", {
          openId: this.openId
        });
        for (var i = 0; i < data.data.length; i++) {
          data.data[i].textStyle = "";
          data.data[i].textStyle1 = "";
        }
        this.listData = data.data;
      },
      allCheck() {
        //先清空
        this.Listids = [];
        if (this.allcheck) {
          this.allcheck = false;
        } else {
          console.log("选择全部");

          this.allcheck = true;
          //循环遍历所有的商品id
          for (let i = 0; i < this.listData.length; i++) {
            const element = this.listData[i];
            this.Listids.push(element.goods_id);
          }
        }
      },
      change(e) {},
      changeColor(index, id) {
        if (this.Listids[index]) {
          this.$set(this.Listids, index, false);
        } else {
          this.$set(this.Listids, index, id);
        }
      }
    },
    computed: {
      isCheckedNumber() {
        let number = 0;
        for (let i = 0; i < this.Listids.length; i++) {
          if (this.Listids[i]) {
            number++;
          }
        }
        if (number == this.listData.length && number != 0) {
          this.allcheck = true;
        } else {
          this.allcheck = false;
        }
        return number;
      },
      allPrise() {
        var Prise = 0;
        for (let i = 0; i < this.Listids.length; i++) {
          if (this.Listids[i]) {
            Prise = Prise + this.listData[i].retail_price * this.listData[i].number;
          }
        }
        return Prise;
      }
    }
  };

</script>
<style lang='scss' scoped>
  @import "./style";

</style>

技术站

前端:小程序、mpvue、async、await

后端:Node、koa2、mysql、knex.js 操作数据库,可视化工具使用的 Navicat

运行方法

npm install 下载依赖
npm run dev  运行项目
这里部分项目的接口都可以访问了,但是登录接口不可以,只有本地搭建一套才可以使用登录接口
因为你用的自己的Appi打开微信开发者工具,无法调用我这边的登录,我后台默认是自己的Appid

喜欢的希望大家点个赞,点个关注,鼓励一下,谢谢大家的支持!!!

源码获取关注VX公众号「码农园区」,回复 【uniapp源码】

最后

精选32套源码目录:

IT之家小程序版客户端(使用 Mpvue 开发,兼容 Web)ithome-lite-master.zip

mpvue 仿网易严选mpvue-shop-master.zip

mpvue-音乐播放器mpvue-music-master.zip

mpvue性能测试与体验miniweibo-master.zip

mpvue改造的日历.zip

mpvue框架仿滴滴出行didi-master.zip

mpVue高仿美团小程序教程mpvue-meituan-master.zip

uni APP自动更新并安装.vue

uni-app nvue沉浸式状态栏(线性渐变色).vue

uni-app 二维码生成器分享wxqrcode.zip

uni-app 侧边导航分类,适合商品分类页面uni-app-left-navigation-master.zip

uni-app 自定义底部导航栏uni-app-bottom-navigation-master.zip

uni-app全局变量的几种实现方式.zip

uni-app的markdown富文本编辑器插件uniapp-markdown-master.zip

uni-app自定义导航栏title-custom.zip

uniapp聊天实例,支持图片,语音,表情.zip

uniapp选择器,包含一级,二级级联,三级级联uniapp-picker-master.zip

vue-mpvue-ChatRobot聊天机器人vue-mpvue-ChatRobot-master.zip

【小程序】CNode社区mpvue-cnode-master.zip

【插件、图表】7种图表漂亮丰富uniCharts.zip

一款播课类小程序, 基于 mpvue 构建mp-podcast-mpvue-master.zip

云档新版小程序端,基于mpvue开发cloud-doc-v2-master.zip

仿uc浏览器列表.vue

仿扎克新闻mpZAKER-master.zip

仿网易云UImusic播放器mpvue-music-master.zip

仿追书神器的小说阅读器小程序wx-book-master.zip

参照米家APP布局和样式,编写的一款智能家居小程序smart-home-master.zip

商城实例mpvue-xbyjShop-master.zip

基于 mpvue 实现豆瓣电影微信小程序mpvue-douban-master.zip

基于mpvue的优酷mpvue-youku-master.zip

校园助手示例SHUhelper-master.zip

类似mui中的chat(聊天窗口)实现uniapp-chat-master.zip

美团外卖(第三方)开源程序mpvue-master.zip

美食搜索mpvue-FG-master.zip

豆瓣平分mpvue-douban-pingfen-master.zip

顶部tabbar.vue

源码截图:
在这里插入图片描述

说明

如果本项目对您有帮助,欢迎 “点赞,关注” 支持一下 谢谢~

源码获取关注公众号「码农园区」,回复 【uniapp源码】
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1265911.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git删除临时分支

愿所有美好如期而遇 软件开发过程中&#xff0c;总有功能要添加进来&#xff0c;当我们有一个功能开发了一半的时候&#xff0c;产品经理说这个功能不需要了&#xff0c;尽管很无奈&#xff0c;但还是要删除&#xff0c;我开发到一半的分支如何删除呢&#xff1f; 所以需要使用…

unity学习笔记

一、Transform类 在Unity中&#xff0c;Transform 类是一种用于表示和操作游戏对象位置、旋转和缩放的类。每个游戏对象都有一个关联的 Transform 组件&#xff0c;该组件定义了对象在场景中的空间变换信息。 1.常见属性和方法 获取位置 相对与世界坐标系&#xff1a;Debug.…

利用sql语句来统计用户登录数据的实践

目录 1 基本数据情况2 统计每个用户每个月登录次数3 将日期按月显示在列上4 总结 1 基本数据情况 当需要对用户登录情况进行统计时&#xff0c;SQL是一个非常强大的工具。通过SQL&#xff0c;可以轻松地从数据库中提取和汇总数据&#xff0c;并以适合分析和报告的方式进行呈现…

详解Object.defineProperty()方法

Object.defineProperty是一个用于定义或修改对象属性的方法。它提供了一种更底层和灵活的方式来定义属性&#xff0c;可以设置属性的配置&#xff08;如可枚举性、可配置性、可写性等&#xff09;&#xff0c;并且可以定义属性的getter和setter函数。 语法&#xff1a; Objec…

C语言数据结构之顺序表(上)

前言&#xff1a; ⭐️此篇博文主要分享博主在学习C语言的数据结构之顺序表的知识点时写的笔记&#xff0c;若有错误&#xff0c;还请佬指出&#xff0c;一定感谢&#xff01;制作不易&#xff0c;若觉得内容不错可以点赞&#x1f44d;收藏❤️&#xff0c;这是对博主最大的认可…

电脑资料删除后如何恢复?3个简单方法轻松恢复文件!

“我平常喜欢在电脑上保存很多学习资料&#xff0c;但由于资料太多&#xff0c;在清理电脑时我可能会误删一些比较有用的资料。想问问大家电脑资料删除后还有机会恢复吗&#xff1f;应该怎么操作呢&#xff1f;” 在数字化时代&#xff0c;很多用户都会选择将重要的文件直接保存…

【算法刷题】Day8

文章目录 202. 快乐数解法&#xff1a; 11. 盛最多水的容器解法&#xff1a; 202. 快乐数 原题链接 拿到题&#xff0c;我们先看题干 把一个整数替换为每个位置上的数字平方和&#xff0c;有两种情况&#xff1a; 重复这个过程始终不到 1&#xff08;无限死循环&#xff09;结…

【计算机网络学习之路】序列化,反序列化和初识协议

文章目录 前言一. 序列化和反序列化1.自己实现2. JSON 二. 初识协议结束语 前言 本系列文章是计算机网络学习的笔记&#xff0c;欢迎大佬们阅读&#xff0c;纠错&#xff0c;分享相关知识。希望可以与你共同进步。 本篇博文讲解应用层的序列化和反序列化&#xff0c;还有见一…

笔记:Pika Labs 3D 动画生成工具

Pika Labs 一款3D 动画生成工具 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/134657306 目 录 1. 简介2. 准备2.1 安装 discord2.2 加入 Discord 频道 3. Pika 使用指南2.1 快速开始2.2 从图像到视频2.3 Pika Bot按钮2.4 提示&#xff08;Prompt&a…

【代码】数据驱动的多离散场景电热综合能源系统分布鲁棒优化算法matlab/yalmip+cplex/gurobi

程序名称&#xff1a;数据驱动的多离散场景电热综合能源系统分布鲁棒优化算法 实现平台&#xff1a;matlab-yalmip-cplex/gurobi 代码简介&#xff1a;数据驱动的分布鲁棒优化算法。考虑四个离散场景&#xff0c;模型采用列与约束生成(CCG)算法进行迭代求解&#xff0c;场景分…

选择更灵活的设计工具:SOLIDWORKS 软件网络版与单机版的比较

随着科技的飞速发展&#xff0c;工程设计领域对于高效、灵活的设计工具需求日益增加。SOLIDWORKS 作为一款广受欢迎的三维设计软件&#xff0c;提供了网络版和单机版两种选择。在本文中&#xff0c;我们将深入探讨这两个版本的区别&#xff0c;并为您详细介绍它们的价格差异。 …

前端面试灵魂提问

1.自我介绍 2.在实习中&#xff0c;你负责那一模块 3.any与unknow的异同 相同点&#xff1a;any和unkonwn 可以接受任何值 不同点&#xff1a;any会丢掉类型限制&#xff0c;可以用any 类型的变量随意做任何事情。unknown 变量会强制执行类型检查&#xff0c;所以在使用一个…

openwrt配置SSL证书实现https加密访问

前言&#xff1a;目前来看这个用处不是很大&#xff0c;因为只能访问一个端口&#xff0c;且因为80和443都已经被运营商封了&#xff0c;所以访问时还是得带端口。以下以阿里云证书为例&#xff1a; 一、申请证书 这个很简单&#xff0c;不想去截图了&#xff0c;直接去申请你…

【设计模式-2.2】创建型——简单工厂和工厂模式

说明&#xff1a;本文介绍设计模式中&#xff0c;创建型设计模式中的工厂模式&#xff1b; 飞机大战 创建型设计模式&#xff0c;关注于对象的创建&#xff0c;本文介绍的简单工厂和工厂模式同样也是。举一个游戏例子&#xff0c;如飞机大战游戏中&#xff0c;屏幕中敌人类型…

android viewpager 禁止滑动

android viewpager 禁止滑动 前言一、viewpager 禁止滑动是什么&#xff0c;有现成方法吗&#xff1f;二、使用setOnTouchListener三、使用自定义viewpager总结 前言 本文介绍了本人有一个相关的需求需要实现这一功能&#xff0c;在过程中发现自己之前没做过&#xff0c;然后记…

【带头学C++】----- 八、C++面向对象编程 ---- 8.5 struct结构体类型增强使用说明

目录 8.5 struct结构体类型增强使用说明 8.5.1 C结构体可以定义成员函数 8.5.2 c中定义结构体变量可以不加struct关键字 8.6 bool布尔类型关键字 8.5 struct结构体类型增强使用说明 第六章对结构体的使用、内存对齐以及数组、深拷贝和浅拷贝进行了一个详细的说明&#xff0c…

统信UOS_麒麟KYLINOS上使用远程SSH连接的工具electerm

原文链接&#xff1a;统信UOS/麒麟KYLINOS上使用SSH工具electerm Hello&#xff0c;大家好啊&#xff01;在我们日常的工作和学习中&#xff0c;远程控制和管理服务器已经成为一项常见且必要的技能。尤其是对于IT专业人士和开发者来说&#xff0c;一个高效、稳定的远程SSH连接工…

智能AI系统ChatGPT网站系统源码+Midjourney绘画+支持DALL-E3文生图,支持最新GPT-4-Turbo模型

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

漏洞扫描-德迅云安全漏洞扫描服务

漏洞扫描是指基于漏洞数据库&#xff0c;通过扫描等手段对指定的远程或者本地计算机系统的安全脆弱性进行检测&#xff0c;发现可利用漏洞的一种安全检测的行为。 漏洞扫描的主要目的是发现系统、网络或应用程序中可能存在的安全漏洞和缺陷&#xff0c;以便及时修复这些漏洞和缺…

基于STM32单片机的智能家居系统设计(论文+源码)

1.系统设计 基于STM32单片机的智能家居系统设计与实现的具体任务&#xff1a; &#xff08;1&#xff09;可以实现风扇、窗帘、空调、灯光的开关控制&#xff1b; &#xff08;2&#xff09;具有语音识别功能&#xff0c;可以通过语音控制家电&#xff1b; &#xff08;3&a…