【小程序实战系列】电商平台搭建

作者:半身风雪
上一节:什么是微信小程序



一、业务介绍

零售行业模版小程序是个经典的单店版电商小程序,涵盖了电商的黄金链路流程,从商品->购物车->结算->订单等。小程序总共包含 28 个完整的页面,涵盖首页,商品详情页,个人中心,售后流程等基础页面。采用 mock 数据进行展示,提供了完整的零售商品展示、交易与售后流程。页面详情:

模版小程序页面详情

主要页面截图如下:

example-home example-sort example-cart example-user-center example-goods-detail example-pay example-order example-order-detail

二、项目构成

零售行业模版小程序采用基础的 JavaScript + WXSS + ESLint 进行构建,降低了使用门槛。

项目目录结构如下:

在这里插入图片描述

|-- mall-starter
    |-- README.md
    |-- app.js    //JavaScrip文件
    |-- app.json   // 项目配置文件,负责窗口颜色等等
    |-- app.wxss   //类似CSS文件
    |-- components  //  公共组件库
    |-- config  //  基础配置
    |-- custom-tab-bar  //  自定义 tabbar
    |-- model //  mock 数据
    |-- pages
    |   |-- cart  //  购物车相关页面
    |   |-- coupon  //  优惠券相关页面
    |   |-- goods //  商品相关页面
    |   |-- home  //  首页
    |   |-- order //  订单售后相关页面
    |   |-- promotion-detail  //  营销活动页面
    |   |-- usercenter  //  个人中心及收货地址相关页面
    |-- services  //  请求接口
    |-- style //  公共样式与iconfont
    |-- utils //  工具库

三、 数据模拟

零售小程序采用真实的接口数据,模拟后端返回逻辑,在小程序展示完整的购物场景与购物体验逻辑。

四、项目部分源码

4.1、页面路由及tabBar

{
    
    
  "pages": [
    "pages/home/home",
    "pages/usercenter/index",
    "pages/usercenter/person-info/index",
    "pages/usercenter/address/list/index",
    "pages/usercenter/address/edit/index",
    "pages/goods/list/index",
    "pages/goods/details/index",
    "pages/goods/category/index",
    "pages/goods/search/index",
    "pages/goods/result/index",
    "pages/cart/index",
    "pages/order/order-confirm/index",
    "pages/order/receipt/index",
    "pages/order/pay-result/index",
    "pages/order/order-list/index",
    "pages/order/order-detail/index",
    "pages/goods/comments/index",
    "pages/order/apply-service/index",
    "pages/order/after-service-list/index",
    "pages/order/after-service-detail/index",
    "pages/goods/comments/create/index",
    "pages/coupon/coupon-list/index",
    "pages/coupon/coupon-detail/index",
    "pages/coupon/coupon-activity-goods/index",
    "pages/promotion-detail/index",
    "pages/order/fill-tracking-no/index",
    "pages/order/delivery-detail/index",
    "pages/order/invoice/index",
    "pages/usercenter/name-edit/index"
  ],
  "tabBar": {
    
    
    "custom": true,
    "color": "#666666",
    "selectedColor": "#FF5F15",
    "backgroundColor": "#ffffff",
    "borderStyle": "black",
    "list": [
      {
    
    
        "pagePath": "pages/home/home",
        "text": "首页"
      },
      {
    
    
        "pagePath": "pages/goods/category/index",
        "text": "分类"
      },
      {
    
    
        "pagePath": "pages/cart/index",
        "text": "购物车"
      },
      {
    
    
        "pagePath": "pages/usercenter/index",
        "text": "我的"
      }
    ]
  },
  "lazyCodeLoading": "requiredComponents",
  "usingComponents": {
    
    },
  "window": {
    
    
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle": "black"
  },
  "sitemapLocation": "sitemap.json",
  "permission": {
    
    
    "scope.userLocation": {
    
    
      "desc": "你的位置信息将用于小程序位置接口的效果展示"
    }
  }
}

4.2、home 首页


// home.js

import {
    
     fetchHome } from '../../services/home/home';
import {
    
     fetchGoodsList } from '../../services/good/fetchGoods';
import Toast from 'tdesign-miniprogram/toast/index';

Page({
    
    
  data: {
    
    
    imgSrcs: [],
    tabList: [],
    goodsList: [],
    goodsListLoadStatus: 0,
    pageLoading: false,
    current: 1,
    autoplay: true,
    duration: 500,
    interval: 5000,
    navigation: {
    
     type: 'dots' },
  },

  goodListPagination: {
    
    
    index: 0,
    num: 20,
  },

  privateData: {
    
    
    tabIndex: 0,
  },

  onShow() {
    
    
    this.getTabBar().init();
  },

  onLoad() {
    
    
    this.init();
  },

  onReachBottom() {
    
    
    if (this.data.goodsListLoadStatus === 0) {
    
    
      this.loadGoodsList();
    }
  },

  onPullDownRefresh() {
    
    
    this.init();
  },

  init() {
    
    
    this.loadHomePage();
  },

  loadHomePage() {
    
    
    wx.stopPullDownRefresh();

    this.setData({
    
    
      pageLoading: true,
    });
    fetchHome().then(({
    
     swiper, tabList }) => {
    
    
      this.setData({
    
    
        tabList,
        imgSrcs: swiper,
        pageLoading: false,
      });
      this.loadGoodsList(true);
    });
  },

  tabChangeHandle(e) {
    
    
    this.privateData.tabIndex = e.detail;
    this.loadGoodsList(true);
  },

  onReTry() {
    
    
    this.loadGoodsList();
  },

  async loadGoodsList(fresh = false) {
    
    
    if (fresh) {
    
    
      wx.pageScrollTo({
    
    
        scrollTop: 0,
      });
    }

    this.setData({
    
     goodsListLoadStatus: 1 });

    const pageSize = this.goodListPagination.num;
    let pageIndex =
      this.privateData.tabIndex * pageSize + this.goodListPagination.index + 1;
    if (fresh) {
    
    
      pageIndex = 0;
    }

    try {
    
    
      const nextList = await fetchGoodsList(pageIndex, pageSize);
      this.setData({
    
    
        goodsList: fresh ? nextList : this.data.goodsList.concat(nextList),
        goodsListLoadStatus: 0,
      });

      this.goodListPagination.index = pageIndex;
      this.goodListPagination.num = pageSize;
    } catch (err) {
    
    
      this.setData({
    
     goodsListLoadStatus: 3 });
    }
  },

  goodListClickHandle(e) {
    
    
    const {
    
     index } = e.detail;
    const {
    
     spuId } = this.data.goodsList[index];
    wx.navigateTo({
    
    
      url: `/pages/goods/details/index?spuId=${
    
    spuId}`,
    });
  },

  goodListAddCartHandle() {
    
    
    Toast({
    
    
      context: this,
      selector: '#t-toast',
      message: '点击加入购物车',
    });
  },

  navToSearchPage() {
    
    
    wx.navigateTo({
    
     url: '/pages/goods/search/index' });
  },

  navToActivityDetail({
    
     detail }) {
    
    
    const {
    
     index: promotionID = 0 } = detail || {
    
    };
    wx.navigateTo({
    
    
      url: `/pages/promotion-detail/index?promotion_id=${
    
    promotionID}`,
    });
  },
});

// home.json
{
    
    
  "navigationBarTitleText": "首页",
  "onReachBottomDistance": 10,
  "backgroundTextStyle": "light",
  "enablePullDownRefresh": true,
  "usingComponents": {
    
    
    "t-search": "tdesign-miniprogram/search/search",
    "t-loading": "tdesign-miniprogram/loading/loading",
    "t-swiper": "tdesign-miniprogram/swiper/swiper",
    "t-swiper-item": "tdesign-miniprogram/swiper/swiper-item",
    "t-swiper-nav": "tdesign-miniprogram/swiper/swiper-nav",
    "t-image": "/components/webp-image/index",
    "t-icon": "tdesign-miniprogram/icon/icon",
    "t-toast": "tdesign-miniprogram/toast/toast",
    "t-tabs": "tdesign-miniprogram/tabs/tabs",
    "t-tab-panel": "tdesign-miniprogram/tabs/tab-panel",
    "goods-list": "/components/goods-list/index",
    "load-more": "/components/load-more/index"
  }
}

<!-- home.wxml -->
<view style="text-align: center" wx:if="{
     
     {pageLoading}}">
	<t-loading
	  theme="circular"
	  size="40rpx"
	  loading
	  t-class-indicator="t-class-indicator"
	>
		<span slot="text" class="loading-text">加载中...</span>
	</t-loading>
</view>
<view class="home-page-header">
	<view class="search" bind:tap="navToSearchPage">
		<t-search
		  t-class-input="t-search__input"
		  t-class-input-container="t-search__input-container"
		  placeholder="iphone 13 火热发售中"
		  leftIcon=""
		  disabled
		>
			<t-icon
			  slot="left-icon"
			  prefix="wr"
			  name="search"
			  size="40rpx"
			  color="#bbb"
			/>
		</t-search>
	</view>
	<view class="swiper-wrap">
		<t-swiper
		  wx:if="{
     
     {imgSrcs.length > 0}}"
		  current="{
     
     {current}}"
		  autoplay="{
     
     {autoplay}}"
		  duration="{
     
     {duration}}"
		  interval="{
     
     {interval}}"
		  navigation="{
     
     {navigation}}"
		>
			<t-swiper-item wx:for="{
     
     {imgSrcs}}" wx:key="index">
				<t-image src="{
     
     {item.img}}" t-class="t-image__swiper" bind:tap="navToActivityDetail" />
			</t-swiper-item>
		</t-swiper>
	</view>
</view>
<view class="home-page-container">
	<t-tabs
	  t-class="t-tabs"
	  t-class-active="t-class-item"
	  t-class-track="t-class-track"
	  defaultValue="{
     
     {0}}"
	  bind:change="tabChangeHandle"
	>
		<t-tab-panel
		  wx:for="{
     
     {tabList}}"
		  wx:for-index="index"
		  wx:key="index"
		  label="{
     
     {item.text}}"
		  value="{
     
     {item.key}}"
		/>
	</t-tabs>
	<goods-list
	  wr-class="goods-list-container"
	  goodsList="{
     
     {goodsList}}"
	  bind:click="goodListClickHandle"
	  bind:addcart="goodListAddCartHandle"
	/>
	<load-more list-is-empty="{
     
     {!goodsList.length}}" status="{
     
     {goodsListLoadStatus}}" bind:retry="onReTry" />
	<t-toast id="t-toast" />
</view>



/* home.wxss */

page {
    
    
  box-sizing: border-box;
  padding-bottom: calc(env(safe-area-inset-bottom) + 96rpx);
}

.t-tabs.t-tabs--top .t-tabs__scroll {
    
    
  border-bottom: none !important;
}

.home-page-header {
    
    
  background: linear-gradient(#fff, #f5f5f5);
}

.home-page-container {
    
    
  background: #f5f5f5;
}

.home-page-container,
.home-page-header {
    
    
  display: block;
  padding: 0 24rpx;
}

.home-page-header .t-search__input-container {
    
    
  border-radius: 32rpx !important;
  height: 64rpx !important;
}

.home-page-header .t-search__input {
    
    
  font-size: 28rpx !important;
  color: rgb(116, 116, 116) !important;
}

.home-page-header .swiper-wrap {
    
    
  margin-top: 20rpx;
}

.home-page-header .t-image__swiper {
    
    
  width: 100%;
  height: 300rpx;
  border-radius: 10rpx;
}

.home-page-container .t-tabs {
    
    
  background: #f5f5f5;
}

.home-page-container .t-tabs .t-tabs-nav {
    
    
  background-color: transparent;
  line-height: 80rpx;
  font-size: 28rpx;
  color: #333;
}

.home-page-container .t-tabs .t-tabs-scroll {
    
    
  border: none !important;
}

/* 半个字 */
.home-page-container .tab.order-nav .order-nav-item.scroll-width {
    
    
  min-width: 165rpx;
}
.home-page-container .tab .order-nav-item.active {
    
    
  color: #fa550f !important;
}

.home-page-container .tab .bottom-line {
    
    
  border-radius: 4rpx;
}

.home-page-container .tab .order-nav-item.active .bottom-line {
    
    
  background-color: #fa550f !important;
}

.home-page-container .t-class-item {
    
    
  color: #333333 !important;
  font-size: 32rpx;
}

.home-page-container .t-class-track {
    
    
  background-color: #fa4126 !important;
  height: 6rpx !important;
  border-radius: 4rpx !important;
  width: 48rpx !important;
}

.t-tabs.t-tabs--top .t-tabs__item,
.t-tabs.t-tabs--bottom .t-tabs__item {
    
    
  height: 86rpx !important;
}

.home-page-container .goods-list-container {
    
    
  background: #f5f5f5 !important;
  margin-top: 24rpx;
}
.t-class-indicator,
.loading-text {
    
    
  color: #b9b9b9 !important;
}

算了,直接源码下载

猜你喜欢

转载自blog.csdn.net/u010755471/article/details/125473201
今日推荐