├── LICENSE ├── README.md ├── app.js ├── app.json ├── app.wxss ├── components ├── Mylist │ ├── Mylist.js │ ├── Mylist.json │ ├── Mylist.wxml │ └── Mylist.wxss ├── iview │ ├── badge │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── base │ │ └── index.js │ ├── card │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── cell │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── grid-icon │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── grid-item │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── grid-label │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── grid │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── icon │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── input-number │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── load-more │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── message │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── tab-bar-item │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ ├── tab │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss │ └── tabs │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss └── weui │ └── SearchBar │ ├── searchbar.js │ ├── searchbar.json │ ├── searchbar.wxml │ ├── searchbar.wxss │ └── weui-searchbar.wxss ├── pages ├── ConfirmOrder │ ├── ConfirmOrder.js │ ├── ConfirmOrder.json │ ├── ConfirmOrder.wxml │ └── ConfirmOrder.wxss ├── collection │ ├── collection.js │ ├── collection.json │ ├── collection.wxml │ └── collection.wxss ├── details │ ├── details.js │ ├── details.json │ ├── details.wxml │ └── details.wxss ├── goods │ ├── goods.js │ ├── goods.json │ ├── goods.wxml │ └── goods.wxss ├── index │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── logs │ ├── logs.js │ ├── logs.json │ ├── logs.wxml │ └── logs.wxss ├── mine │ ├── mine.js │ ├── mine.json │ ├── mine.wxml │ └── mine.wxss ├── orders │ ├── orders.js │ ├── orders.json │ ├── orders.wxml │ └── orders.wxss └── shoppingCart │ ├── shoppingCart.js │ ├── shoppingCart.json │ ├── shoppingCart.wxml │ └── shoppingCart.wxss ├── project.config.json ├── sitemap.json ├── static ├── icon │ ├── category_1.png │ ├── category_2.png │ ├── category_3.png │ ├── category_4.png │ ├── category_5.png │ ├── category_6.png │ ├── category_7.png │ ├── category_8.png │ ├── home.png │ ├── home_fill.png │ ├── search.png │ ├── search_fill.png │ ├── shoppingCart.png │ ├── shoppingCart_fill.png │ ├── user.png │ └── user_fill.png └── imgs │ └── cart-empty.jpg ├── store ├── index.js └── shoppingCart.js └── utils ├── create.js ├── obaa.js ├── path.js └── util.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 hai-27 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 小小米(vue-store 微信小程序版) 2 | ## 前言 3 | 4 | 前段时间模仿小米商城做了一个PC端的商城网站[vue-store]( https://github.com/hai-27/vue-store ),最近看了下微信小程序的文档,所以就动手做了个微信小程序版的。 5 | 6 | ## 说明 7 | 8 | > 本项目复用了 [vue-store]( https://github.com/hai-27/vue-store ) 的后端,在 [store-server](https://github.com/hai-27/store-server) 原来的基础上添加了微信小程序的登录api。 9 | 10 | > 利用网课的空余时间边学边做,略为粗糙,有问题或者有好的建议欢迎提Issues。 11 | 12 | > 由于是用测试号做的,没有线上预览版。 13 | 14 | > PC端Web版:[vue-store]( https://github.com/hai-27/vue-store )。 15 | 16 | > 后端: [store-server](https://github.com/hai-27/store-server) 。 17 | 18 | > 如果觉得这个项目还不错,您可以点右上角 `Star`支持一下, 谢谢! ^_^ 19 | 20 | ## 项目简介 21 | 22 | 为区分小米商城官方小程序,该项目我命名为小小米。该项目与小米官方没有关系,纯属个人瞎搞,若需要购买小米产品请到小米官方商城。 23 | 24 | 项目包含4个tabBar:首页、发现页(即商品展示页)、购物车、我的。另有商品详情页、我的收藏、订单结算页面、我的订单。 25 | 26 | 实现了商品的展示、商品分类查询、关键字搜索商品、商品详细信息展示、用户购物车、订单结算、用户订单、用户收藏列表。 27 | 28 | 该项目整体参考了 [vue-store]( https://github.com/hai-27/vue-store ) 实现,基本实现了其所有功能,可以说是其的微信小程序版。 29 | 30 | 后端复用了 [vue-store]( https://github.com/hai-27/vue-store ) 的后端,在 [store-server](https://github.com/hai-27/store-server) 原来的基础上添加了微信小程序的登录api。 31 | 32 | ## 技术栈 33 | 34 | - **前端:** 原生微信小程序 35 | 36 | - **后端:**`Node.js`、`Koa框架` 37 | 38 | - **数据库:**`Mysql` 39 | 40 | ## 功能模块 41 | 42 | ### 登录 43 | 44 | 小程序在启动的时候调用 **wx.login** 获取登录凭证(**code**),然后把code回传到项目的后端服务器 ,调用**auth.code2Session**接口,换取用户唯一标识 **OpenID** 和 会话密钥 **session_key**。 然后把 **OpenID** 注册到项目数据库生成本系统的唯一 **user_id** ,用于在本项目的业务验证。 45 | 46 | ### 首页 47 | 48 | 首页主要是对商品的展示,有轮播图展示推荐的商品,热门商品分类九宫格、分类别对热门商品进行展示。 49 | 50 |  51 | 52 | ### 发现(即全部商品) 53 | 54 | 全部商品页面集成了全部商品展示、商品分类查询,以及根据关键字搜索商品结果展示。 55 | 56 |  57 | 58 | ### 商品详情页 59 | 60 | 商品详情页主要是对某个商品的详细信息进行展示,用户可以在这里把喜欢的商品加入购物车或收藏列表。 61 | 62 |  63 | 64 | ### 我的购物车 65 | 66 | 购物车采用[omix](https://github.com/Tencent/omi)进行全局状态管理,实现了购物车商品的添加、删除、增加商品数量、选择结算商品、全选购物车商品结算等功能。 67 | 68 |  69 | 70 | ### 订单结算 71 | 72 | 用户在购物车选择了准备购买的商品后,点击“去结算”按钮,会来到该页面。 73 | 用户在这里选择收货地址,确认订单的相关信息,然后确认购买。 74 | 75 |  76 | 77 | ### 我的收藏 78 | 79 | 用户在商品的详情页,可以通过点击加入 喜欢 按钮,把喜欢的商品加入到收藏列表。 80 | 81 |  82 | 83 | ### 我的订单 84 | 85 | 对用户的所有订单进行展示。 86 | 87 |  88 | 89 | ### 我的 90 | 91 |  92 | 93 | ## 运行项目 94 | 95 | ``` 96 | 请clone项目到本地 97 | git clone https://github.com/hai-27/store-miniprogram.git 98 | 导入项目到微信开发者工具即可 99 | ``` 100 | 101 | 102 | 103 | **作者** [hai-27](https://github.com/hai-27) 104 | 105 | 2020年3月31日 -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | // import create from '/utils/create'; 3 | import store from '/store/index'; 4 | let { 5 | baseURL, 6 | $ajax 7 | } = require('./utils/util.js') 8 | App({ 9 | onLaunch: function() { 10 | // 展示本地存储能力 11 | var logs = wx.getStorageSync('logs') || [] 12 | logs.unshift(Date.now()) 13 | wx.setStorageSync('logs', logs) 14 | 15 | // 登录 16 | wx.login({ 17 | success: async res => { 18 | // 发送 res.code 到后台换取 openId, sessionKey, unionId 19 | let loginRes = await $ajax('users/miniProgramLogin', { 20 | data: { 21 | code: res.code 22 | } 23 | }); 24 | // 登录成功 25 | if (loginRes.code === '001') { 26 | this.globalData.userId = loginRes.userId; 27 | // 获取购物车信息 28 | if (this.globalData.userId) { 29 | let shoppingCart = await $ajax('user/shoppingCart/getShoppingCart', { 30 | data: { 31 | user_id: this.globalData.userId 32 | } 33 | }); 34 | store.data.shoppingCart = shoppingCart.shoppingCartData; 35 | } 36 | } 37 | } 38 | }); 39 | // 获取用户信息 40 | wx.getSetting({ 41 | success: res => { 42 | if (res.authSetting['scope.userInfo']) { 43 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 44 | wx.getUserInfo({ 45 | success: res => { 46 | // 可以将 res 发送给后台解码出 unionId 47 | this.globalData.userInfo = res.userInfo 48 | 49 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 50 | // 所以此处加入 callback 以防止这种情况 51 | if (this.userInfoReadyCallback) { 52 | this.userInfoReadyCallback(res) 53 | } 54 | } 55 | }) 56 | } 57 | } 58 | }) 59 | }, 60 | globalData: { 61 | userInfo: null, 62 | userId: '', 63 | baseURL, 64 | $ajax, 65 | categoryId: 0 66 | } 67 | }) -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/index/index", 4 | "pages/goods/goods", 5 | "pages/shoppingCart/shoppingCart", 6 | "pages/mine/mine", 7 | "pages/details/details", 8 | "pages/confirmOrder/confirmOrder", 9 | "pages/orders/orders", 10 | "pages/collection/collection", 11 | "pages/logs/logs" 12 | ], 13 | "window": { 14 | "backgroundTextStyle": "dark", 15 | "navigationBarBackgroundColor": "#ff6700", 16 | "navigationBarTitleText": "小小米", 17 | "navigationBarTextStyle": "white" 18 | }, 19 | "tabBar": { 20 | "color": "#8a8a8a", 21 | "selectedColor": "#ff6700", 22 | "list": [ 23 | { 24 | "pagePath": "pages/index/index", 25 | "text": "首页", 26 | "iconPath": "/static/icon/home.png", 27 | "selectedIconPath": "/static/icon/home_fill.png" 28 | }, 29 | { 30 | "pagePath": "pages/goods/goods", 31 | "text": "发现", 32 | "iconPath": "/static/icon/search.png", 33 | "selectedIconPath": "/static/icon/search_fill.png" 34 | }, 35 | { 36 | "pagePath": "pages/shoppingCart/shoppingCart", 37 | "text": "购物车", 38 | "iconPath": "/static/icon/shoppingCart.png", 39 | "selectedIconPath": "/static/icon/shoppingCart_fill.png" 40 | }, 41 | { 42 | "pagePath": "pages/mine/mine", 43 | "text": "我的", 44 | "iconPath": "/static/icon/user.png", 45 | "selectedIconPath": "/static/icon/user_fill.png" 46 | } 47 | ] 48 | }, 49 | "style": "v2", 50 | "sitemapLocation": "sitemap.json" 51 | } -------------------------------------------------------------------------------- /app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: space-between; 8 | padding: 200rpx 0; 9 | box-sizing: border-box; 10 | } 11 | -------------------------------------------------------------------------------- /components/Mylist/Mylist.js: -------------------------------------------------------------------------------- 1 | const { 2 | baseURL 3 | } = getApp().globalData; 4 | Component({ 5 | /** 6 | * 组件的属性列表 7 | */ 8 | properties: { 9 | arr: Object, 10 | titleName: String 11 | }, 12 | 13 | /** 14 | * 组件的初始数据 15 | */ 16 | data: { 17 | baseURL 18 | }, 19 | 20 | /** 21 | * 组件的方法列表 22 | */ 23 | methods: { 24 | 25 | } 26 | }) -------------------------------------------------------------------------------- /components/Mylist/Mylist.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /components/Mylist/Mylist.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{titleName}} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{item.product_name}} 13 | {{item.product_title}} 14 | 15 | {{item.product_selling_price}}元 16 | {{item.product_price}}元 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /components/Mylist/Mylist.wxss: -------------------------------------------------------------------------------- 1 | .list { 2 | width: 100%; 3 | background-color: #f5f5f5; 4 | overflow: hidden; 5 | } 6 | 7 | .list .list-main { 8 | margin: 2%; 9 | float: left; 10 | } 11 | 12 | /* .list .list-main::after { 13 | content: ""; 14 | display: block; 15 | clear: left; 16 | } */ 17 | 18 | .list .list-main .list-title { 19 | height: 50px; 20 | padding-left: 10px; 21 | line-height: 50px; 22 | font-size: 20px; 23 | color: #6c6c6c; 24 | font-weight: 550; 25 | background-color: #fff; 26 | } 27 | 28 | .list-main .pro-item { 29 | width: 49.5%; 30 | margin-top: 1%; 31 | float: left; 32 | background-color: #fff; 33 | } 34 | 35 | .list-main .pro-item:nth-child(2n) { 36 | margin-left: 1%; 37 | } 38 | 39 | .list-main .pro-item image { 40 | margin: 0 auto; 41 | padding: 0 20px 0 20px; 42 | width: 80%; 43 | height: 150px; 44 | } 45 | 46 | .list-main .pro-item .pro-info { 47 | margin: 0 10px 10px 10px; 48 | } 49 | 50 | .list-main .pro-item .pro-info .pro-title { 51 | width: 100%; 52 | height: 20px; 53 | float: left; 54 | font-size: 14px; 55 | font-weight: 400; 56 | color: #191919; 57 | text-overflow: ellipsis; 58 | overflow: hidden; 59 | display: -webkit-box; 60 | -webkit-line-clamp: 1; 61 | -webkit-box-orient: vertical; 62 | } 63 | 64 | .list-main .pro-item .pro-info .pro-des { 65 | width: 100%; 66 | height: 14px; 67 | float: left; 68 | font-size: 12px; 69 | font-weight: 400; 70 | color: #7f7f7f; 71 | padding: 5px 0 5px 0; 72 | text-overflow: ellipsis; 73 | overflow: hidden; 74 | display: -webkit-box; 75 | -webkit-line-clamp: 1; 76 | -webkit-box-orient: vertical; 77 | } 78 | 79 | .list-main .pro-item .pro-info .pro-price { 80 | width: 100%; 81 | height: 20px; 82 | padding-bottom: 10px; 83 | float: left; 84 | font-size: 16px; 85 | color: #ff6700; 86 | text-overflow: ellipsis; 87 | overflow: hidden; 88 | -webkit-line-clamp: 1; 89 | -webkit-box-orient: vertical; 90 | } 91 | 92 | .list-main .pro-item .pro-info .pro-price .del { 93 | font-size: 12px; 94 | height: 20px; 95 | padding-bottom: 10px; 96 | margin-left: 0.5em; 97 | color: #7f7f7f; 98 | text-decoration: line-through; 99 | text-overflow: ellipsis; 100 | overflow: hidden; 101 | -webkit-line-clamp: 1; 102 | -webkit-box-orient: vertical; 103 | } 104 | -------------------------------------------------------------------------------- /components/iview/badge/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class', 'i-class-alone'], 3 | 4 | properties: { 5 | count: { 6 | type: Number, 7 | value: 0, 8 | observer: 'finalCount' 9 | }, 10 | overflowCount: { 11 | type: Number, 12 | value: 99 13 | }, 14 | dot: { 15 | type: Boolean, 16 | value: false 17 | }, 18 | }, 19 | data: { 20 | finalCount: 0 21 | }, 22 | methods: { 23 | finalCount() { 24 | this.setData({ 25 | finalCount: parseInt(this.data.count) >= parseInt(this.data.overflowCount) ? `${this.data.overflowCount}+` : this.data.count 26 | }); 27 | }, 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /components/iview/badge/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/badge/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ finalCount }} 5 | 6 | -------------------------------------------------------------------------------- /components/iview/badge/index.wxss: -------------------------------------------------------------------------------- 1 | .i-badge{position:relative;display:inline-block;line-height:1;vertical-align:middle}.i-badge-count{position:absolute;transform:translateX(50%);top:-6px;right:0;height:18px;border-radius:9px;min-width:18px;background:#ed3f14;border:1px solid transparent;color:#fff;line-height:18px;text-align:center;padding:0 5px;font-size:12px;white-space:nowrap;transform-origin:-10% center;z-index:10;box-shadow:0 0 0 1px #fff;box-sizing:border-box;text-rendering:optimizeLegibility}.i-badge-count-alone{top:auto;display:block;position:relative;transform:translateX(0)}.i-badge-dot{position:absolute;transform:translateX(-50%);transform-origin:0 center;top:-4px;right:-8px;height:8px;width:8px;border-radius:100%;background:#ed3f14;z-index:10;box-shadow:0 0 0 1px #fff} -------------------------------------------------------------------------------- /components/iview/base/index.js: -------------------------------------------------------------------------------- 1 | function getCtx (selector) { 2 | const pages = getCurrentPages(); 3 | const ctx = pages[pages.length - 1]; 4 | 5 | const componentCtx = ctx.selectComponent(selector); 6 | 7 | if (!componentCtx) { 8 | console.error('无法找到对应的组件,请按文档说明使用组件'); 9 | return null; 10 | } 11 | return componentCtx; 12 | } 13 | 14 | function Toast(options) { 15 | const { selector = '#toast' } = options; 16 | const ctx = getCtx(selector); 17 | 18 | ctx.handleShow(options); 19 | } 20 | 21 | Toast.hide = function (selector = '#toast') { 22 | const ctx = getCtx(selector); 23 | 24 | ctx.handleHide(); 25 | }; 26 | 27 | function Message(options) { 28 | const { selector = '#message' } = options; 29 | const ctx = getCtx(selector); 30 | 31 | ctx.handleShow(options); 32 | } 33 | 34 | module.exports = { 35 | $Toast: Toast, 36 | $Message: Message 37 | }; -------------------------------------------------------------------------------- /components/iview/card/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | options: { 5 | multipleSlots: true 6 | }, 7 | 8 | properties: { 9 | full: { 10 | type: Boolean, 11 | value: false 12 | }, 13 | thumb: { 14 | type: String, 15 | value: '' 16 | }, 17 | title: { 18 | type: String, 19 | value: '' 20 | }, 21 | extra: { 22 | type: String, 23 | value: '' 24 | }, 25 | checked:{ 26 | type: Boolean, 27 | value: false 28 | } 29 | } 30 | }); -------------------------------------------------------------------------------- /components/iview/card/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/card/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ title }} 9 | 10 | 11 | 12 | 13 | {{ extra }} 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /components/iview/card/index.wxss: -------------------------------------------------------------------------------- 1 | .i-card { 2 | margin: 0 16px 0 0; 3 | font-size: 14px; 4 | overflow: hidden; 5 | position: relative; 6 | background: #fff; 7 | border-bottom: 1px solid #dddee1; 8 | border-radius: 5px; 9 | } 10 | 11 | .i-card-full { 12 | margin: 0; 13 | border-left: none; 14 | border-right: none; 15 | border-radius: 0; 16 | } 17 | 18 | .i-card-header { 19 | display: flex; 20 | padding: 6px 10px 0 5px; 21 | align-items: center; 22 | } 23 | 24 | .i-card-header-content { 25 | flex: 4; 26 | text-align: left; 27 | overflow: hidden; 28 | } 29 | .i-card-header-content .title { 30 | float: left; 31 | display: inline-block; 32 | width:65%; 33 | padding-left:5px; 34 | line-height: 64px; 35 | vertical-align: middle; 36 | text-overflow: ellipsis; 37 | overflow: hidden; 38 | display: -webkit-box; 39 | -webkit-line-clamp: 1; 40 | -webkit-box-orient: vertical; 41 | } 42 | 43 | .i-card-header-thumb { 44 | float: left; 45 | display: inline-block; 46 | width: 64px; 47 | height: 64px; 48 | position: relative; 49 | margin-left: auto; 50 | margin-right: auto; 51 | overflow: hidden; 52 | background-size: cover; 53 | vertical-align: middle; 54 | } 55 | 56 | .i-card-header-title { 57 | display: inline-block; 58 | vertical-align: middle; 59 | font-size: 14px; 60 | color: #1c2438; 61 | } 62 | 63 | .i-card-header-extra { 64 | flex: 1; 65 | color: #ff6700; 66 | text-align: right; 67 | font-size: 14px; 68 | } 69 | 70 | .i-card-body { 71 | margin: 5px 10px 5px 33px; 72 | color: #495060; 73 | font-size: 14px; 74 | overflow: hidden; 75 | } 76 | 77 | .i-card-body::before { 78 | content: ''; 79 | position: absolute; 80 | top: 0; 81 | left: 0; 82 | width: 200%; 83 | height: 200%; 84 | transform: scale(0.5); 85 | transform-origin: 0 0; 86 | pointer-events: none; 87 | box-sizing: border-box; 88 | border: 0 solid #e9eaec; 89 | border-top-width: 1px; 90 | } 91 | 92 | .check-box{ 93 | float: left; 94 | line-height: 94px; 95 | padding: 0 5px; 96 | width: 20px; 97 | height:20px; 98 | } -------------------------------------------------------------------------------- /components/iview/cell/index.js: -------------------------------------------------------------------------------- 1 | const warn = (msg, getValue) => { 2 | console.warn(msg); 3 | console.log('接受到的值为:', getValue); 4 | }; 5 | 6 | Component({ 7 | externalClasses: ['i-class'], 8 | 9 | options: { 10 | multipleSlots: true 11 | }, 12 | 13 | relations: { 14 | '../cell-group/index': { 15 | type: 'parent' 16 | } 17 | }, 18 | 19 | properties: { 20 | // 左侧标题 21 | title: { 22 | type: String 23 | }, 24 | // 标题下方的描述信息 25 | label: { 26 | type: String 27 | }, 28 | // 右侧内容 29 | value: { 30 | type: String 31 | }, 32 | // 只有点击 footer 区域才触发 tab 事件 33 | onlyTapFooter: { 34 | type: Boolean 35 | }, 36 | // 是否展示右侧箭头并开启尝试以 url 跳转 37 | isLink: { 38 | type: null, 39 | value: '' 40 | }, 41 | // 链接类型,可选值为 navigateTo,redirectTo,switchTab,reLaunch 42 | linkType: { 43 | type: String, 44 | value: 'navigateTo' 45 | }, 46 | url: { 47 | type: String, 48 | value: '' 49 | } 50 | }, 51 | 52 | data: { 53 | isLastCell: true 54 | }, 55 | 56 | methods: { 57 | navigateTo () { 58 | const { url } = this.data; 59 | const type = typeof this.data.isLink; 60 | 61 | this.triggerEvent('click', {}); 62 | 63 | if (!this.data.isLink || !url || url === 'true' || url === 'false') return; 64 | 65 | if (type !== 'boolean' && type !== 'string') { 66 | warn('isLink 属性值必须是一个字符串或布尔值', this.data.isLink); 67 | return; 68 | } 69 | 70 | if (['navigateTo', 'redirectTo', 'switchTab', 'reLaunch'].indexOf(this.data.linkType) === -1) { 71 | warn('linkType 属性可选值为 navigateTo,redirectTo,switchTab,reLaunch', this.data.linkType); 72 | return; 73 | } 74 | wx[this.data.linkType].call(wx, {url}); 75 | }, 76 | handleTap () { 77 | if (!this.data.onlyTapFooter) { 78 | this.navigateTo(); 79 | } 80 | }, 81 | 82 | updateIsLastCell (isLastCell) { 83 | this.setData({ isLastCell }); 84 | } 85 | } 86 | }); 87 | -------------------------------------------------------------------------------- /components/iview/cell/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/cell/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ label }} 7 | {{ title }} 8 | 9 | 10 | 11 | {{ value }} 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /components/iview/cell/index.wxss: -------------------------------------------------------------------------------- 1 | .i-cell { 2 | position: relative; 3 | padding: 12px 15px; 4 | display: flex; 5 | background: #fff; 6 | align-items: center; 7 | line-height: 1.4; 8 | font-size: 14px; 9 | border-bottom: 1px solid #e9eaec; 10 | overflow: hidden; 11 | } 12 | 13 | .i-cell::after { 14 | content: ''; 15 | position: absolute; 16 | top: 0; 17 | left: 0; 18 | width: 200%; 19 | height: 200%; 20 | transform: scale(0.5); 21 | transform-origin: 0 0; 22 | pointer-events: none; 23 | box-sizing: border-box; 24 | border: 0 solid #e9eaec; 25 | border-bottom: 1px solid #e9eaec; 26 | /* left: 15px; */ 27 | right: 0; 28 | } 29 | 30 | .i-cell-last::after { 31 | display: none; 32 | } 33 | 34 | .i-cell-icon { 35 | margin-right: 5px; 36 | } 37 | 38 | .i-cell-icon:empty { 39 | display: none; 40 | } 41 | 42 | .i-cell-bd { 43 | flex: 1; 44 | } 45 | 46 | .i-cell-text { 47 | float: left; 48 | width: 70%; 49 | line-height: 24px; 50 | font-size: 14px; 51 | text-overflow: ellipsis; 52 | overflow: hidden; 53 | display: -webkit-box; 54 | -webkit-line-clamp: 1; 55 | -webkit-box-orient: vertical; 56 | } 57 | 58 | .i-cell-desc { 59 | float: left; 60 | padding-right: 20px; 61 | line-height: 24px; 62 | font-size: 12px; 63 | color: #80848f; 64 | } 65 | 66 | .i-cell-ft { 67 | position: relative; 68 | text-align: right; 69 | /* color: #495060; */ 70 | color: #ff6700; 71 | } 72 | 73 | .i-cell-access .i-cell-ft { 74 | padding-right: 13px; 75 | } 76 | 77 | .i-cell-access .i-cell-ft::after { 78 | content: " "; 79 | display: inline-block; 80 | width: 6px; 81 | height: 6px; 82 | position: absolute; 83 | top: 50%; 84 | right: 2px; 85 | border-width: 2px 2px 0 0; 86 | border-color: #dddee1; 87 | border-style: solid; 88 | transform: translateY(-50%) matrix(0.71, 0.71, -.71, 0.71, 0, 0); 89 | } 90 | -------------------------------------------------------------------------------- /components/iview/grid-icon/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | relations: { 5 | '../grid-item/index': { 6 | type: 'parent' 7 | } 8 | }, 9 | 10 | }); 11 | -------------------------------------------------------------------------------- /components/iview/grid-icon/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/grid-icon/index.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/iview/grid-icon/index.wxss: -------------------------------------------------------------------------------- 1 | .i-grid-icon{display:block;width:28px;height:28px;margin:0 auto}.i-grid-icon image{width:100%;height:100%} -------------------------------------------------------------------------------- /components/iview/grid-item/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | relations: { 5 | '../grid/index': { 6 | type: 'parent' 7 | }, 8 | '../grid-icon/index': { 9 | type: 'child' 10 | } 11 | }, 12 | 13 | data: { 14 | width: '33.33%' 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /components/iview/grid-item/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/grid-item/index.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/iview/grid-item/index.wxss: -------------------------------------------------------------------------------- 1 | .i-grid-item{position:relative;float:left;padding:20px 10px;width:33.33333333%;box-sizing:border-box;border-right:1rpx solid #e9eaec;border-bottom:1rpx solid #e9eaec} -------------------------------------------------------------------------------- /components/iview/grid-label/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | relations: { 5 | '../grid-item/index': { 6 | type: 'parent' 7 | } 8 | }, 9 | 10 | }); 11 | -------------------------------------------------------------------------------- /components/iview/grid-label/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/grid-label/index.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/iview/grid-label/index.wxss: -------------------------------------------------------------------------------- 1 | .i-grid-label{margin-top:5px;display:block;text-align:center;color:#1c2438;font-size:14px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden} -------------------------------------------------------------------------------- /components/iview/grid/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | relations: { 5 | '../grid-item/index': { 6 | type: 'child', 7 | linked () { 8 | this.setGridItemWidth(); 9 | }, 10 | linkChanged () { 11 | this.setGridItemWidth(); 12 | }, 13 | unlinked () { 14 | this.setGridItemWidth(); 15 | } 16 | } 17 | }, 18 | 19 | methods: { 20 | setGridItemWidth () { 21 | const nodes = this.getRelationNodes('../grid-item/index'); 22 | 23 | // const len = nodes.length; 24 | // if (len < 3) { 25 | // nodes.forEach(item => { 26 | // item.setData({ 27 | // 'width': '33.33%' 28 | // }); 29 | // }); 30 | // } else { 31 | // const width = 100 / nodes.length; 32 | // nodes.forEach(item => { 33 | // item.setData({ 34 | // 'width': width + '%' 35 | // }); 36 | // }); 37 | // } 38 | const width = 100 / nodes.length; 39 | nodes.forEach(item => { 40 | item.setData({ 41 | 'width': width + '%' 42 | }); 43 | }); 44 | } 45 | }, 46 | 47 | ready () { 48 | this.setGridItemWidth(); 49 | } 50 | }); 51 | -------------------------------------------------------------------------------- /components/iview/grid/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/grid/index.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/iview/grid/index.wxss: -------------------------------------------------------------------------------- 1 | .i-grid{border-top:1rpx solid #e9eaec;border-left:1rpx solid #e9eaec;overflow:hidden} -------------------------------------------------------------------------------- /components/iview/icon/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | properties: { 5 | type: { 6 | type: String, 7 | value: '' 8 | }, 9 | custom: { 10 | type: String, 11 | value: '' 12 | }, 13 | size: { 14 | type: Number, 15 | value: 14 16 | }, 17 | color: { 18 | type: String, 19 | value: '' 20 | } 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /components/iview/icon/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/icon/index.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/iview/icon/index.wxss: -------------------------------------------------------------------------------- 1 | @font-face{font-family:iconfont;src:url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff')}.i-icon{display:inline-block;font-family:iconfont;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;text-rendering:auto;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;vertical-align:middle}.i-icon-accessory:before{content:"\e6dd"}.i-icon-activity:before{content:"\e6de"}.i-icon-activity_fill:before{content:"\e6df"}.i-icon-add:before{content:"\e6e0"}.i-icon-addressbook_fill:before{content:"\e6e2"}.i-icon-addressbook:before{content:"\e6e3"}.i-icon-barrage_fill:before{content:"\e6e4"}.i-icon-barrage:before{content:"\e6e5"}.i-icon-browse_fill:before{content:"\e6e6"}.i-icon-browse:before{content:"\e6e7"}.i-icon-brush:before{content:"\e6e8"}.i-icon-brush_fill:before{content:"\e6e9"}.i-icon-businesscard_fill:before{content:"\e6ea"}.i-icon-businesscard:before{content:"\e6eb"}.i-icon-camera_fill:before{content:"\e6ec"}.i-icon-camera:before{content:"\e6ed"}.i-icon-clock_fill:before{content:"\e6ee"}.i-icon-clock:before{content:"\e6ef"}.i-icon-close:before{content:"\e6f0"}.i-icon-collection_fill:before{content:"\e6f1"}.i-icon-collection:before{content:"\e6f2"}.i-icon-computer_fill:before{content:"\e6f3"}.i-icon-computer:before{content:"\e6f4"}.i-icon-coordinates_fill:before{content:"\e6f5"}.i-icon-coordinates:before{content:"\e6f6"}.i-icon-coupons_fill:before{content:"\e6f7"}.i-icon-coupons:before{content:"\e6f8"}.i-icon-createtask_fill:before{content:"\e6f9"}.i-icon-createtask:before{content:"\e6fa"}.i-icon-customerservice_fill:before{content:"\e6fb"}.i-icon-customerservice:before{content:"\e6fc"}.i-icon-delete_fill:before{content:"\e6fd"}.i-icon-delete:before{content:"\e6fe"}.i-icon-document:before{content:"\e6ff"}.i-icon-document_fill:before{content:"\e700"}.i-icon-dynamic_fill:before{content:"\e701"}.i-icon-dynamic:before{content:"\e702"}.i-icon-editor:before{content:"\e703"}.i-icon-eit:before{content:"\e704"}.i-icon-emoji_fill:before{content:"\e705"}.i-icon-emoji:before{content:"\e706"}.i-icon-enter:before{content:"\e707"}.i-icon-enterinto:before{content:"\e708"}.i-icon-enterinto_fill:before{content:"\e709"}.i-icon-feedback_fill:before{content:"\e70a"}.i-icon-feedback:before{content:"\e70b"}.i-icon-flag_fill:before{content:"\e70c"}.i-icon-flag:before{content:"\e70d"}.i-icon-flashlight:before{content:"\e70e"}.i-icon-flashlight_fill:before{content:"\e70f"}.i-icon-fullscreen:before{content:"\e710"}.i-icon-group:before{content:"\e711"}.i-icon-group_fill:before{content:"\e712"}.i-icon-homepage_fill:before{content:"\e713"}.i-icon-homepage:before{content:"\e714"}.i-icon-integral_fill:before{content:"\e715"}.i-icon-integral:before{content:"\e716"}.i-icon-interactive_fill:before{content:"\e717"}.i-icon-interactive:before{content:"\e718"}.i-icon-keyboard:before{content:"\e719"}.i-icon-label:before{content:"\e71a"}.i-icon-label_fill:before{content:"\e71b"}.i-icon-like_fill:before{content:"\e71c"}.i-icon-like:before{content:"\e71d"}.i-icon-live_fill:before{content:"\e71e"}.i-icon-live:before{content:"\e71f"}.i-icon-lock_fill:before{content:"\e720"}.i-icon-lock:before{content:"\e721"}.i-icon-mail:before{content:"\e722"}.i-icon-mail_fill:before{content:"\e723"}.i-icon-message:before{content:"\e724"}.i-icon-message_fill:before{content:"\e725"}.i-icon-mine:before{content:"\e726"}.i-icon-mine_fill:before{content:"\e727"}.i-icon-mobilephone_fill:before{content:"\e728"}.i-icon-mobilephone:before{content:"\e729"}.i-icon-more:before{content:"\e72a"}.i-icon-narrow:before{content:"\e72b"}.i-icon-offline_fill:before{content:"\e72c"}.i-icon-offline:before{content:"\e72d"}.i-icon-other:before{content:"\e72e"}.i-icon-picture_fill:before{content:"\e72f"}.i-icon-picture:before{content:"\e730"}.i-icon-play:before{content:"\e731"}.i-icon-play_fill:before{content:"\e732"}.i-icon-playon_fill:before{content:"\e733"}.i-icon-playon:before{content:"\e734"}.i-icon-praise_fill:before{content:"\e735"}.i-icon-praise:before{content:"\e736"}.i-icon-prompt_fill:before{content:"\e737"}.i-icon-prompt:before{content:"\e738"}.i-icon-redpacket_fill:before{content:"\e739"}.i-icon-redpacket:before{content:"\e73a"}.i-icon-refresh:before{content:"\e73b"}.i-icon-remind_fill:before{content:"\e73c"}.i-icon-remind:before{content:"\e73d"}.i-icon-return:before{content:"\e73e"}.i-icon-right:before{content:"\e73f"}.i-icon-scan:before{content:"\e740"}.i-icon-send:before{content:"\e741"}.i-icon-service_fill:before{content:"\e742"}.i-icon-service:before{content:"\e743"}.i-icon-setup_fill:before{content:"\e744"}.i-icon-setup:before{content:"\e745"}.i-icon-share_fill:before{content:"\e746"}.i-icon-share:before{content:"\e747"}.i-icon-success_fill:before{content:"\e748"}.i-icon-success:before{content:"\e749"}.i-icon-suspend:before{content:"\e74a"}.i-icon-switch:before{content:"\e74b"}.i-icon-systemprompt_fill:before{content:"\e74c"}.i-icon-systemprompt:before{content:"\e74d"}.i-icon-tailor:before{content:"\e74e"}.i-icon-task:before{content:"\e74f"}.i-icon-task_fill:before{content:"\e750"}.i-icon-tasklist_fill:before{content:"\e751"}.i-icon-tasklist:before{content:"\e752"}.i-icon-time_fill:before{content:"\e753"}.i-icon-time:before{content:"\e754"}.i-icon-translation_fill:before{content:"\e755"}.i-icon-translation:before{content:"\e756"}.i-icon-trash:before{content:"\e757"}.i-icon-trash_fill:before{content:"\e758"}.i-icon-undo:before{content:"\e759"}.i-icon-video:before{content:"\e75a"}.i-icon-video_fill:before{content:"\e75b"}.i-icon-warning_fill:before{content:"\e75c"}.i-icon-warning:before{content:"\e75d"}.i-icon-search:before{content:"\e75e"}.i-icon-searchfill:before{content:"\e75f"}.i-icon-publishgoods_fill:before{content:"\e760"}.i-icon-shop_fill:before{content:"\e761"}.i-icon-transaction_fill:before{content:"\e762"}.i-icon-packup:before{content:"\e763"}.i-icon-unfold:before{content:"\e764"}.i-icon-financial_fill:before{content:"\e765"}.i-icon-commodity:before{content:"\e766"} -------------------------------------------------------------------------------- /components/iview/input-number/index.js: -------------------------------------------------------------------------------- 1 | function addNum (num1, num2) { 2 | let sq1, sq2, m; 3 | try { 4 | sq1 = num1.toString().split('.')[1].length; 5 | } 6 | catch (e) { 7 | sq1 = 0; 8 | } 9 | try { 10 | sq2 = num2.toString().split('.')[1].length; 11 | } 12 | catch (e) { 13 | sq2 = 0; 14 | } 15 | m = Math.pow(10, Math.max(sq1, sq2)); 16 | return (Math.round(num1 * m) + Math.round(num2 * m)) / m; 17 | } 18 | 19 | Component({ 20 | externalClasses: ['i-class'], 21 | 22 | properties: { 23 | // small || default || large 24 | size: String, 25 | value: { 26 | type: Number, 27 | value: 1 28 | }, 29 | min: { 30 | type: Number, 31 | value: -Infinity 32 | }, 33 | max: { 34 | type: Number, 35 | value: Infinity 36 | }, 37 | step: { 38 | type: Number, 39 | value: 1 40 | } 41 | }, 42 | 43 | 44 | methods: { 45 | handleChangeStep(e, type) { 46 | const { dataset = {} } = e.currentTarget; 47 | const { disabled } = dataset; 48 | const { step } = this.data; 49 | let { value } = this.data; 50 | 51 | if (disabled) return null; 52 | 53 | if (type === 'minus') { 54 | value = addNum(value, -step); 55 | } else if (type === 'plus') { 56 | value = addNum(value, step); 57 | } 58 | 59 | if (value < this.data.min || value > this.data.max) return null; 60 | 61 | this.handleEmit(value, type); 62 | }, 63 | 64 | handleMinus(e) { 65 | this.handleChangeStep(e, 'minus'); 66 | }, 67 | 68 | handlePlus(e) { 69 | this.handleChangeStep(e, 'plus'); 70 | }, 71 | 72 | handleBlur(e) { 73 | let { value } = e.detail; 74 | const { min, max } = this.data; 75 | 76 | if (!value) { 77 | setTimeout(() => { 78 | this.handleEmit(value); 79 | }, 16); 80 | return; 81 | } 82 | 83 | value = +value; 84 | if (value > max) { 85 | value = max; 86 | } else if (value < min) { 87 | value = min; 88 | } 89 | 90 | this.handleEmit(value); 91 | }, 92 | handleEmit (value, type) { 93 | const data = { 94 | value: value 95 | }; 96 | if (type) data.type = type; 97 | 98 | this.triggerEvent('change', data); 99 | } 100 | } 101 | }); 102 | -------------------------------------------------------------------------------- /components/iview/input-number/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/input-number/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | - 3 | 4 | + 5 | 6 | -------------------------------------------------------------------------------- /components/iview/input-number/index.wxss: -------------------------------------------------------------------------------- 1 | .i-input-number { 2 | color: #495060; 3 | } 4 | 5 | .i-input-number view { 6 | display: inline-block; 7 | line-height: 20px; 8 | text-align: center; 9 | vertical-align: middle; 10 | font-size: 12px; 11 | } 12 | 13 | .i-input-number-minus { 14 | width: 25px; 15 | min-height: 20px; 16 | max-height: 20px; 17 | border-right: none; 18 | border-radius: 2px 0 0 2px; 19 | border: 1px solid #dddee1; 20 | } 21 | 22 | .i-input-number-plus { 23 | width: 25px; 24 | min-height: 20px; 25 | max-height: 20px; 26 | border-left: none; 27 | border-radius: 0 2px 2px 0; 28 | border: 1px solid #dddee1; 29 | } 30 | 31 | .i-input-number-text { 32 | border: 1px solid #dddee1; 33 | display: inline-block; 34 | text-align: center; 35 | vertical-align: middle; 36 | width: 30px; 37 | min-height: 20px; 38 | max-height: 20px; 39 | font-size: 12px; 40 | } 41 | 42 | .i-input-number-disabled { 43 | border-color: #dddee1; 44 | color: #bbbec4; 45 | background: #f7f7f7; 46 | } 47 | -------------------------------------------------------------------------------- /components/iview/load-more/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | properties: { 5 | loading: { 6 | type: Boolean, 7 | value: true 8 | }, 9 | tip: { 10 | type: String, 11 | value: '' 12 | } 13 | }, 14 | }); 15 | -------------------------------------------------------------------------------- /components/iview/load-more/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/load-more/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ tip }} 5 | 正在加载 6 | 7 | 8 | -------------------------------------------------------------------------------- /components/iview/load-more/index.wxss: -------------------------------------------------------------------------------- 1 | .i-load-more{width:65%;padding-top:20px;margin:0 auto;line-height:1.6em;font-size:14px;text-align:center}.i-load-more-loading{display:inline-block;margin-right:12px;vertical-align:middle;width:14px;height:14px;background:0 0;border-radius:50%;border:2px solid #e9eaec;border-color:#e9eaec #e9eaec #e9eaec #2d8cf0;animation:btn-spin .6s linear;animation-iteration-count:infinite}.i-load-more-tip{display:inline-block;vertical-align:middle;color:#495060}.i-load-more-line{border-top:1px solid #dddee1;display:flex;border-top:0}.i-load-more-line::before{position:relative;top:-1px;-webkit-box-flex:1;-webkit-flex:1;flex:1;content:'';border-top:1px solid #dddee1}.i-load-more-line::after{position:relative;top:-1px;-webkit-box-flex:1;-webkit-flex:1;flex:1;content:'';border-top:1px solid #dddee1}.i-load-more-line .i-load-more-tip{position:relative;top:-.9em;padding:0 .55em}.i-load-more-empty{width:4px;height:4px;border-radius:50%;background-color:#e5e5e5;display:inline-block;position:relative;vertical-align:0;top:-.16em}@keyframes btn-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}} -------------------------------------------------------------------------------- /components/iview/message/index.js: -------------------------------------------------------------------------------- 1 | const default_data = { 2 | visible: false, 3 | content: '', 4 | duration: 2, 5 | type: 'default', // default || success || warning || error 6 | }; 7 | 8 | let timmer = null; 9 | 10 | Component({ 11 | externalClasses: ['i-class'], 12 | 13 | data: { 14 | ...default_data 15 | }, 16 | 17 | methods: { 18 | handleShow (options) { 19 | const { type = 'default', duration = 2 } = options; 20 | 21 | this.setData({ 22 | ...options, 23 | type, 24 | duration, 25 | visible: true 26 | }); 27 | 28 | const d = this.data.duration * 1000; 29 | 30 | if (timmer) clearTimeout(timmer); 31 | if (d !== 0) { 32 | timmer = setTimeout(() => { 33 | this.handleHide(); 34 | timmer = null; 35 | }, d); 36 | } 37 | }, 38 | 39 | handleHide () { 40 | this.setData({ 41 | ...default_data 42 | }); 43 | } 44 | } 45 | }); -------------------------------------------------------------------------------- /components/iview/message/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/message/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | {{ content }} 3 | -------------------------------------------------------------------------------- /components/iview/message/index.wxss: -------------------------------------------------------------------------------- 1 | .i-message{display:block;width:100%;min-height:32px;line-height:2.3;position:fixed;top:0;left:0;right:0;background:#2d8cf0;color:#fff;text-align:center;font-size:14px;z-index:1010;opacity:0;-webkit-transform:translateZ(0) translateY(-100%);transition:all .4s ease-in-out}.i-message-show{-webkit-transform:translateZ(0) translateY(0);opacity:1}.i-message-default{background:#2d8cf0}.i-message-success{background:#19be6b}.i-message-warning{background:#f90}.i-message-error{background:#ed3f14} -------------------------------------------------------------------------------- /components/iview/tab-bar-item/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | relations: { 5 | '../tab-bar/index': { 6 | type: 'parent' 7 | } 8 | }, 9 | 10 | properties: { 11 | icon: { 12 | type: String, 13 | value: '' 14 | }, 15 | currentIcon: { 16 | type: String, 17 | value: '' 18 | }, 19 | img: { 20 | type: String, 21 | value: '' 22 | }, 23 | currentImg: { 24 | type: String, 25 | value: '' 26 | }, 27 | key: { 28 | type: String, 29 | value: '' 30 | }, 31 | title: { 32 | type: String, 33 | value: '' 34 | }, 35 | dot: { 36 | type: Boolean, 37 | value: false 38 | }, 39 | count: { 40 | type: Number, 41 | value: 0 42 | } 43 | }, 44 | 45 | data: { 46 | current: false, 47 | currentColor: '' 48 | }, 49 | 50 | methods: { 51 | changeCurrent (current) { 52 | this.setData({ current }); 53 | }, 54 | changeCurrentColor (currentColor) { 55 | this.setData({ currentColor }); 56 | }, 57 | handleClickItem () { 58 | const parent = this.getRelationNodes('../tab-bar/index')[0]; 59 | parent.emitEvent(this.data.key); 60 | } 61 | } 62 | }); 63 | -------------------------------------------------------------------------------- /components/iview/tab-bar-item/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": 4 | { 5 | "i-badge": "../badge/index", 6 | "i-icon": "../icon/index" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /components/iview/tab-bar-item/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ title }} 7 | {{ title }} 8 | 9 | 10 | -------------------------------------------------------------------------------- /components/iview/tab-bar-item/index.wxss: -------------------------------------------------------------------------------- 1 | .i-tab-bar-item{flex:1;display:flex;width:100%;-webkit-box-pack:center;justify-content:center;-webkit-box-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;text-align:center}.i-tab-bar-item-icon{display:flex;-webkit-box-pack:center;justify-content:center;box-sizing:border-box;color:#80848f}.i-tab-bar-item-icon-current{color:#2d8cf0}.i-tab-bar-item-img{display:flex;-webkit-box-pack:center;justify-content:center;box-sizing:border-box;width:22px;height:22px}.i-tab-bar-item-title{font-size:10px;margin:3px 0 0;line-height:1;text-align:center;box-sizing:border-box;color:#80848f}.i-tab-bar-item-title-current{color:#2d8cf0}.i-tab-bar-item-img{display:flex;-webkit-box-pack:center;justify-content:center;box-sizing:border-box;color:#80848f} -------------------------------------------------------------------------------- /components/iview/tab/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | relations: { 5 | '../tabs/index': { 6 | type: 'parent' 7 | } 8 | }, 9 | 10 | properties: { 11 | key: { 12 | type: String, 13 | value: '' 14 | }, 15 | title: { 16 | type: String, 17 | value: '' 18 | }, 19 | dot: { 20 | type: Boolean, 21 | value: false 22 | }, 23 | count: { 24 | type: Number, 25 | value: 0 26 | } 27 | }, 28 | 29 | data: { 30 | current: false, 31 | currentColor: '', 32 | scroll: false 33 | }, 34 | 35 | methods: { 36 | changeCurrent (current) { 37 | this.setData({ current }); 38 | }, 39 | changeCurrentColor (currentColor) { 40 | this.setData({ currentColor }); 41 | }, 42 | changeScroll (scroll) { 43 | this.setData({ scroll }); 44 | }, 45 | handleClickItem () { 46 | const parent = this.getRelationNodes('../tabs/index')[0]; 47 | parent.emitEvent(this.data.key); 48 | } 49 | } 50 | }); 51 | -------------------------------------------------------------------------------- /components/iview/tab/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": 4 | { 5 | "i-badge": "../badge/index" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /components/iview/tab/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title }} 5 | {{ title }} 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /components/iview/tab/index.wxss: -------------------------------------------------------------------------------- 1 | .i-tabs-tab{flex:1;display:flex;width:100%;-webkit-box-pack:center;justify-content:center;-webkit-box-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;text-align:center;position:relative}.i-tabs-tab-bar{display:block;width:100%;height:2px;background:0 0;position:absolute;bottom:0;left:0;background:#2d8cf0}.i-tabs-tab-title{font-size:14px;text-align:center;box-sizing:border-box;color:#80848f}.i-tabs-tab-title-current{color:#2d8cf0}.i-tabs-tab-scroll{display:inline-block;width:60px} -------------------------------------------------------------------------------- /components/iview/tabs/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | externalClasses: ['i-class'], 3 | 4 | relations: { 5 | '../tab/index': { 6 | type: 'child', 7 | linked () { 8 | this.changeCurrent(); 9 | }, 10 | linkChanged () { 11 | this.changeCurrent(); 12 | }, 13 | unlinked () { 14 | this.changeCurrent(); 15 | } 16 | } 17 | }, 18 | 19 | properties: { 20 | current: { 21 | type: String, 22 | value: '', 23 | observer: 'changeCurrent' 24 | }, 25 | color: { 26 | type: String, 27 | value: '' 28 | }, 29 | scroll: { 30 | type: Boolean, 31 | value: false 32 | }, 33 | fixed: { 34 | type: Boolean, 35 | value: false 36 | } 37 | }, 38 | 39 | methods: { 40 | changeCurrent (val = this.data.current) { 41 | let items = this.getRelationNodes('../tab/index'); 42 | const len = items.length; 43 | 44 | if (len > 0) { 45 | items.forEach(item => { 46 | item.changeScroll(this.data.scroll); 47 | item.changeCurrent(item.data.key === val); 48 | item.changeCurrentColor(this.data.color); 49 | }); 50 | } 51 | }, 52 | emitEvent (key) { 53 | this.triggerEvent('change', { key }); 54 | } 55 | } 56 | }); 57 | -------------------------------------------------------------------------------- /components/iview/tabs/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } 4 | -------------------------------------------------------------------------------- /components/iview/tabs/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/iview/tabs/index.wxss: -------------------------------------------------------------------------------- 1 | .i-tabs{display:flex;width:100%;height:42px;line-height:42px;box-sizing:border-box;position:relative;justify-content:space-around;align-items:center;-webkit-box-align:center;background:#fff}.i-tabs::after{content:'';position:absolute;top:0;left:0;width:200%;height:200%;transform:scale(.5);transform-origin:0 0;pointer-events:none;box-sizing:border-box;border:0 solid #e9eaec;border-bottom-width:1px}.i-tabs-scroll{display:block;overflow-x:auto;white-space:nowrap}.i-tabs-fixed{position:fixed;top:0;z-index:2} -------------------------------------------------------------------------------- /components/weui/SearchBar/searchbar.js: -------------------------------------------------------------------------------- 1 | Page({ 2 | data: { 3 | inputShowed: false, 4 | inputVal: "", 5 | search: JSON.parse(wx.getStorageSync("search") || '[]'), 6 | showSearch: '' 7 | }, 8 | showInput: function() { 9 | this.setData({ 10 | inputShowed: true 11 | }); 12 | }, 13 | hideInput: function() { 14 | this.setData({ 15 | inputVal: "", 16 | inputShowed: false 17 | }); 18 | }, 19 | clearInput: function() { 20 | this.setData({ 21 | inputVal: "" 22 | }); 23 | }, 24 | inputTyping: function(e) { 25 | const inputVal = e.detail.value; 26 | // 判断是否为空 27 | let showSearch = '' 28 | if (inputVal) { 29 | // 过滤数组,过滤出来类似的数据 30 | showSearch = this.data.search.filter(item => { 31 | if (item != inputVal) { 32 | return item.includes(inputVal); 33 | } 34 | }) 35 | } 36 | this.setData({ 37 | inputVal, 38 | showSearch 39 | }); 40 | }, 41 | // 确认搜索条件 42 | searchConfirm: function(e) { 43 | const inputVal = this.data.inputVal; 44 | if (inputVal) { 45 | // 判断是否已经存在该数据,没有则添加 46 | if (this.data.search.indexOf(inputVal) < 0) { 47 | this.data.search.push(inputVal) 48 | wx.setStorageSync('search', JSON.stringify(this.data.search)); 49 | } 50 | // 向父组件传值 51 | this.triggerEvent('myevent', { 52 | search: inputVal 53 | }); 54 | 55 | this.setData({ 56 | inputVal: "" 57 | }); 58 | this.hideInput(); 59 | } 60 | }, 61 | // searchBlur: function() { 62 | // // 离焦确认搜索 63 | // this.searchConfirm(); 64 | // }, 65 | 66 | // 点击历史搜索记录 67 | searchItemTap: function(e) { 68 | console.log("vbdjvsdbsj") 69 | let inputVal = e.currentTarget.dataset.search; 70 | this.setData({ 71 | inputVal 72 | }) 73 | this.searchConfirm(); 74 | } 75 | }); -------------------------------------------------------------------------------- /components/weui/SearchBar/searchbar.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /components/weui/SearchBar/searchbar.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 搜索 13 | 14 | 15 | 取消 16 | 17 | 18 | 19 | 20 | {{inputVal}} 21 | 22 | 23 | 24 | 25 | {{item}} 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /components/weui/SearchBar/searchbar.wxss: -------------------------------------------------------------------------------- 1 | /*! 2 | * WeUI v2.3.0 (https://github.com/weui/weui-wxss) 3 | * Copyright 2020 Tencent, Inc. 4 | * Licensed under the MIT license 5 | */ 6 | @import "./weui-searchbar.wxss"; 7 | 8 | .searchbar-result { 9 | width: 100%; 10 | min-height: 80px; 11 | margin-top: 0; 12 | font-size: 14px; 13 | z-index: 3000; 14 | position: absolute; 15 | background-color: #fff; 16 | } 17 | 18 | .searchbar-result .weui-cell__bd { 19 | padding: 10px 0 10px 10px; 20 | border-bottom: 1px solid #e9eaec; 21 | color: #191919; 22 | } 23 | 24 | .searchbar-result:before { 25 | display: none; 26 | } 27 | -------------------------------------------------------------------------------- /components/weui/SearchBar/weui-searchbar.wxss: -------------------------------------------------------------------------------- 1 | /*! 2 | * WeUI v2.3.0 (https://github.com/weui/weui-wxss) 3 | * Copyright 2020 Tencent, Inc. 4 | * Licensed under the MIT license 5 | */ 6 | [data-weui-theme=light],page{--weui-BG-0:#ededed;--weui-BG-1:#f7f7f7;--weui-BG-2:#fff;--weui-BG-3:#f7f7f7;--weui-BG-4:#4c4c4c;--weui-BG-5:#fff;--weui-FG-0:rgba(0,0,0,.9);--weui-FG-HALF:rgba(0,0,0,.9);--weui-FG-1:rgba(0,0,0,.5);--weui-FG-2:rgba(0,0,0,.3);--weui-FG-3:rgba(0,0,0,.1);--weui-RED:#fa5151;--weui-ORANGE:#fa9d3b;--weui-YELLOW:#ffc300;--weui-GREEN:#91d300;--weui-LIGHTGREEN:#95ec69;--weui-BRAND:#07c160;--weui-BLUE:#10aeff;--weui-INDIGO:#1485ee;--weui-PURPLE:#6467f0;--weui-WHITE:#fff;--weui-LINK:#576b95;--weui-TEXTGREEN:#06ae56;--weui-FG:#000;--weui-BG:#fff;--weui-TAG-TEXT-ORANGE:#fa9d3b;--weui-TAG-BACKGROUND-ORANGE:rgba(250,157,59,.1);--weui-TAG-TEXT-GREEN:#06ae56;--weui-TAG-BACKGROUND-GREEN:rgba(6,174,86,.1);--weui-TAG-TEXT-BLUE:#10aeff;--weui-TAG-BACKGROUND-BLUE:rgba(16,174,255,.1);--weui-TAG-TEXT-BLACK:rgba(0,0,0,.5);--weui-TAG-BACKGROUND-BLACK:rgba(0,0,0,.05)}[data-weui-theme=dark]{--weui-BG-0:#191919;--weui-BG-1:#1f1f1f;--weui-BG-2:#232323;--weui-BG-3:#2f2f2f;--weui-BG-4:#606060;--weui-BG-5:#2c2c2c;--weui-FG-0:hsla(0,0%,100%,.8);--weui-FG-HALF:hsla(0,0%,100%,.6);--weui-FG-1:hsla(0,0%,100%,.5);--weui-FG-2:hsla(0,0%,100%,.3);--weui-FG-3:hsla(0,0%,100%,.05);--weui-RED:#fa5151;--weui-ORANGE:#c87d2f;--weui-YELLOW:#cc9c00;--weui-GREEN:#74a800;--weui-LIGHTGREEN:#28b561;--weui-BRAND:#07c160;--weui-BLUE:#10aeff;--weui-INDIGO:#1196ff;--weui-PURPLE:#8183ff;--weui-WHITE:hsla(0,0%,100%,.8);--weui-LINK:#7d90a9;--weui-TEXTGREEN:#259c5c;--weui-FG:#fff;--weui-BG:#000;--weui-TAG-TEXT-ORANGE:rgba(250,157,59,.6);--weui-TAG-BACKGROUND-ORANGE:rgba(250,157,59,.1);--weui-TAG-TEXT-GREEN:rgba(6,174,86,.6);--weui-TAG-BACKGROUND-GREEN:rgba(6,174,86,.1);--weui-TAG-TEXT-BLUE:rgba(16,174,255,.6);--weui-TAG-BACKGROUND-BLUE:rgba(16,174,255,.1);--weui-TAG-TEXT-BLACK:hsla(0,0%,100%,.5);--weui-TAG-BACKGROUND-BLACK:hsla(0,0%,100%,.05)}[data-weui-theme=light],page{--weui-BG-COLOR-ACTIVE:#ececec}[data-weui-theme=dark]{--weui-BG-COLOR-ACTIVE:#373737}[data-weui-theme=light],page{--weui-BTN-DISABLED-FONT-COLOR:rgba(0,0,0,.2)}[data-weui-theme=dark]{--weui-BTN-DISABLED-FONT-COLOR:hsla(0,0%,100%,.2)}[data-weui-theme=light],page{--weui-BTN-DEFAULT-BG:#f2f2f2}[data-weui-theme=dark]{--weui-BTN-DEFAULT-BG:hsla(0,0%,100%,.08)}[data-weui-theme=light],page{--weui-BTN-DEFAULT-COLOR:#06ae56}[data-weui-theme=dark]{--weui-BTN-DEFAULT-COLOR:hsla(0,0%,100%,.8)}[data-weui-theme=light],page{--weui-BTN-DEFAULT-ACTIVE-BG:#e6e6e6}[data-weui-theme=dark]{--weui-BTN-DEFAULT-ACTIVE-BG:hsla(0,0%,100%,.126)}[data-weui-theme=light],page{--weui-DIALOG-LINE-COLOR:rgba(0,0,0,.1)}[data-weui-theme=dark]{--weui-DIALOG-LINE-COLOR:hsla(0,0%,100%,.1)}.weui-search-bar{position:relative;padding:8px;display:-webkit-box;display:-webkit-flex;display:flex;box-sizing:border-box;background-color:var(--weui-BG-0);-webkit-text-size-adjust:100%;-webkit-box-align:center;-webkit-align-items:center;align-items:center}.weui-search-bar.weui-search-bar_focusing .weui-search-bar__cancel-btn{display:block}.weui-search-bar.weui-search-bar_focusing .weui-search-bar__label{display:none}.weui-search-bar .weui-icon-search{width:16px;height:16px}.weui-search-bar__form{position:relative;-webkit-box-flex:1;-webkit-flex:auto;flex:auto;background-color:var(--weui-BG-2);border-radius:4px}.weui-search-bar__box{position:relative;padding-left:28px;padding-right:32px;height:100%;width:100%;box-sizing:border-box;z-index:1}.weui-search-bar__box .weui-search-bar__input{padding:8px 0;width:100%;height:1.14285714em;border:0;font-size:14px;line-height:1.14285714em;box-sizing:content-box;background:transparent;caret-color:var(--weui-BRAND);color:var(--weui-FG-0)}.weui-search-bar__box .weui-search-bar__input:focus{outline:none}.weui-search-bar__box .weui-icon-search{position:absolute;top:50%;left:8px;margin-top:-8px}.weui-search-bar__box .weui-icon-clear{position:absolute;top:50%;right:0;margin-top:-16px;padding:8px;width:16px;height:16px;-webkit-mask-size:16px;mask-size:16px}.weui-search-bar__label{position:absolute;top:0;right:0;bottom:0;left:0;z-index:2;font-size:0;border-radius:4px;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-align:center;-webkit-align-items:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;justify-content:center;color:var(--weui-FG-1);background:var(--weui-BG-2)}.weui-search-bar__label span{display:inline-block;font-size:14px;vertical-align:middle}.weui-search-bar__label .weui-icon-search{margin-right:4px}.weui-search-bar__cancel-btn{display:none;margin-left:8px;line-height:28px;color:var(--weui-LINK);white-space:nowrap}.weui-search-bar__input:not(:valid)+.weui-icon-clear{display:none}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{display:none} -------------------------------------------------------------------------------- /pages/ConfirmOrder/ConfirmOrder.js: -------------------------------------------------------------------------------- 1 | // pages/ConfirmOrder/ConfirmOrder.js 2 | import create from '../../utils/create'; 3 | import store from '../../store/index'; 4 | const { 5 | $Message 6 | } = require('../../components/iview/base/index'); 7 | const { 8 | baseURL, 9 | $ajax 10 | } = getApp().globalData; 11 | 12 | create.Page(store, { 13 | 14 | /** 15 | * 页面的初始数据 16 | */ 17 | data: { 18 | baseURL 19 | }, 20 | 21 | computed: { 22 | // 获取结算商品信息 23 | getCheckGoods() { 24 | return store.getCheckGoods(); 25 | }, 26 | // 订单总价 27 | getTotalPrice() { 28 | return store.getTotalPrice(); 29 | } 30 | }, 31 | /** 32 | * 提交订单 33 | */ 34 | async confirmOrder(){ 35 | let addOrderRes = await $ajax('user/order/addOrder', { 36 | data: { 37 | user_id: getApp().globalData.userId, 38 | products: this.data.getCheckGoods 39 | } 40 | }); 41 | let products = this.data.getCheckGoods; 42 | switch (addOrderRes.code) { 43 | // 001代表结算成功 44 | case "001": 45 | for (let i = 0; i < products.length; i++) { 46 | const temp = products[i]; 47 | // 删除已经结算的购物车商品 48 | store.deleteShoppingCart(temp.productID); 49 | } 50 | // 提示结算结果 51 | $Message({ 52 | content: addOrderRes.msg, 53 | type: 'success' 54 | }); 55 | // 跳转我的订单页面 56 | wx.navigateTo({ 57 | url: '/pages/orders/orders' 58 | }) 59 | break; 60 | default: 61 | // 提示失败信息 62 | $Message({ 63 | content: addOrderRes.msg, 64 | type: 'error' 65 | }); 66 | } 67 | }, 68 | 69 | /** 70 | * 生命周期函数--监听页面加载 71 | */ 72 | onLoad: function(options) { 73 | 74 | }, 75 | 76 | /** 77 | * 生命周期函数--监听页面初次渲染完成 78 | */ 79 | onReady: function() { 80 | 81 | }, 82 | 83 | /** 84 | * 生命周期函数--监听页面显示 85 | */ 86 | onShow: function() { 87 | if (this.data.getCheckGoods.length == 0) { 88 | $Message({ 89 | content: '请先勾选商品再结算!', 90 | type: 'error' 91 | }); 92 | setTimeout(() => { 93 | wx.switchTab({ 94 | url: '/pages/shoppingCart/shoppingCart' 95 | }); 96 | }, 1000) 97 | } 98 | }, 99 | 100 | /** 101 | * 生命周期函数--监听页面隐藏 102 | */ 103 | onHide: function() { 104 | 105 | }, 106 | 107 | /** 108 | * 生命周期函数--监听页面卸载 109 | */ 110 | onUnload: function() { 111 | 112 | }, 113 | 114 | /** 115 | * 页面相关事件处理函数--监听用户下拉动作 116 | */ 117 | onPullDownRefresh: function() { 118 | 119 | }, 120 | 121 | /** 122 | * 页面上拉触底事件的处理函数 123 | */ 124 | onReachBottom: function() { 125 | 126 | }, 127 | 128 | /** 129 | * 用户点击右上角分享 130 | */ 131 | onShareAppMessage: function() { 132 | 133 | } 134 | }) -------------------------------------------------------------------------------- /pages/ConfirmOrder/ConfirmOrder.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "i-cell": "../../components/iview/cell/index", 4 | "i-card": "../../components/iview/card/index", 5 | "i-message": "../../components/iview/message/index" 6 | }, 7 | "navigationBarTitleText": "订单结算" 8 | } -------------------------------------------------------------------------------- /pages/ConfirmOrder/ConfirmOrder.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{item.num}}x 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 使用微信支付 -------------------------------------------------------------------------------- /pages/ConfirmOrder/ConfirmOrder.wxss: -------------------------------------------------------------------------------- 1 | page{ 2 | background-color: #f5f5f5; 3 | } 4 | .space{ 5 | display: block; 6 | margin-top: 10px; 7 | } 8 | 9 | .bottom-bar{ 10 | position: fixed; 11 | left: 0; 12 | bottom: 0; 13 | height: 50px; 14 | line-height: 50px; 15 | text-align: center; 16 | font-size: 18px; 17 | color: #fff; 18 | width: 100%; 19 | z-index: 9999; 20 | padding-left: 5px; 21 | background-color: #17a916; 22 | } -------------------------------------------------------------------------------- /pages/collection/collection.js: -------------------------------------------------------------------------------- 1 | // pages/collection/collection.js 2 | const { 3 | baseURL, 4 | $ajax 5 | } = getApp().globalData; 6 | Page({ 7 | 8 | /** 9 | * 页面的初始数据 10 | */ 11 | data: { 12 | collectList: [] 13 | }, 14 | 15 | /** 16 | * 生命周期函数--监听页面加载 17 | */ 18 | onLoad: function(options) { 19 | 20 | }, 21 | 22 | /** 23 | * 生命周期函数--监听页面初次渲染完成 24 | */ 25 | onReady: function() { 26 | 27 | }, 28 | 29 | /** 30 | * 生命周期函数--监听页面显示 31 | */ 32 | onShow: async function() { 33 | // 获取收藏数据 34 | let res = await $ajax('user/collect/getCollect', { 35 | data: { 36 | user_id: getApp().globalData.userId 37 | } 38 | }); 39 | if (res.code === "001") { 40 | this.setData({ 41 | collectList: res.collectList 42 | }) 43 | } 44 | }, 45 | 46 | /** 47 | * 生命周期函数--监听页面隐藏 48 | */ 49 | onHide: function() { 50 | 51 | }, 52 | 53 | /** 54 | * 生命周期函数--监听页面卸载 55 | */ 56 | onUnload: function() { 57 | 58 | }, 59 | 60 | /** 61 | * 页面相关事件处理函数--监听用户下拉动作 62 | */ 63 | onPullDownRefresh: function() { 64 | 65 | }, 66 | 67 | /** 68 | * 页面上拉触底事件的处理函数 69 | */ 70 | onReachBottom: function() { 71 | 72 | }, 73 | 74 | /** 75 | * 用户点击右上角分享 76 | */ 77 | onShareAppMessage: function() { 78 | 79 | } 80 | }) -------------------------------------------------------------------------------- /pages/collection/collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "my-list": "../../components/Mylist/Mylist" 4 | }, 5 | "navigationBarTitleText": "我的收藏" 6 | } -------------------------------------------------------------------------------- /pages/collection/collection.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 您还没有收藏的商品哦! 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /pages/collection/collection.wxss: -------------------------------------------------------------------------------- 1 | /* pages/collection/collection.wxss */ 2 | page{ 3 | background-color: #f5f5f5; 4 | } 5 | .empty { 6 | height: 100%; 7 | width: 100%; 8 | position: absolute; 9 | top: 0px; 10 | bottom: 0px; 11 | background-color: #f7f7f7; 12 | } 13 | 14 | .empty image { 15 | display: block; 16 | margin: 0 auto; 17 | padding-top: 50px; 18 | width: 147px; 19 | height: 136px; 20 | } 21 | 22 | .empty text { 23 | display: block; 24 | width: 100%; 25 | font-weight: 600; 26 | text-align: center; 27 | color: #b0b0b0; 28 | padding-top: 20px; 29 | } -------------------------------------------------------------------------------- /pages/details/details.js: -------------------------------------------------------------------------------- 1 | // pages/details/details.js 2 | import create from '../../utils/create'; 3 | import store from '../../store/index'; 4 | const { 5 | $Message 6 | } = require('../../components/iview/base/index'); 7 | const { 8 | baseURL, 9 | $ajax 10 | } = getApp().globalData; 11 | 12 | create.Page(store, { 13 | 14 | use: ['shoppingCart'], 15 | /** 16 | * 页面的初始数据 17 | */ 18 | data: { 19 | baseURL, 20 | productID: '', 21 | productInfo: '', 22 | productImages: '', 23 | hotProduct: '', 24 | full: false 25 | }, 26 | computed: { 27 | // 购物车商品总数量 28 | getNum() { 29 | return store.getNum(); 30 | } 31 | }, 32 | /** 33 | * 添加购物车 34 | */ 35 | async addShoppingCart() { 36 | // 判断是否登录 37 | if (!getApp().globalData.userId) { 38 | // 先登录 39 | return; 40 | } 41 | // 如果达到限购数量不继续执行 42 | if (this.data.full) { 43 | $Message({ 44 | content: "加购数量达到限购数量", 45 | type: 'warning' 46 | }); 47 | return; 48 | } 49 | // 向后端发起加入购物车的请求 50 | let addShoppingCartRes = await $ajax('user/shoppingCart/addShoppingCart', { 51 | data: { 52 | user_id: getApp().globalData.userId, 53 | product_id: this.data.productID 54 | } 55 | }); 56 | switch (addShoppingCartRes.code) { 57 | case "001": 58 | // 新加入购物车成功 59 | store.unshiftShoppingCart(addShoppingCartRes.shoppingCartData[0]); 60 | $Message({ 61 | content: addShoppingCartRes.msg, 62 | type: 'success' 63 | }); 64 | break; 65 | case "002": 66 | // 该商品已经在购物车,数量+1 67 | store.addShoppingCartNum(this.data.productID); 68 | $Message({ 69 | content: addShoppingCartRes.msg, 70 | type: 'success' 71 | }); 72 | break; 73 | case "003": 74 | // 商品数量达到限购数量 75 | this.data.full = true; 76 | $Message({ 77 | content: addShoppingCartRes.msg, 78 | type: 'warning' 79 | }); 80 | break; 81 | default: 82 | $Message({ 83 | content: addShoppingCartRes.msg, 84 | type: 'error' 85 | }); 86 | } 87 | }, 88 | /** 89 | * 添加收藏 90 | */ 91 | async addCollect() { 92 | // 判断是否登录 93 | if (!getApp().globalData.userId) { 94 | // 先登录 95 | return; 96 | } 97 | 98 | // 向后端发起加入购物车的请求 99 | let addCollect = await $ajax('user/collect/addCollect', { 100 | data: { 101 | user_id: getApp().globalData.userId, 102 | product_id: this.data.productID 103 | } 104 | }); 105 | 106 | if (addCollect.code == "001") { 107 | // 添加收藏成功 108 | $Message({ 109 | content: addCollect.msg, 110 | type: 'success' 111 | }); 112 | } else { 113 | // 添加收藏失败 114 | $Message({ 115 | content: addCollect.msg, 116 | type: 'error' 117 | }); 118 | } 119 | }, 120 | 121 | /** 122 | * 生命周期函数--监听页面加载 123 | */ 124 | onLoad: async function(options) { 125 | const { 126 | productID 127 | } = options; // 接收路由传递的商品id 128 | // 从后端获取需要的数据 129 | // 商品数据 130 | let product = await $ajax('product/getDetails', { 131 | data: { 132 | productID 133 | } 134 | }); 135 | // 商品图片 136 | let productImages = await $ajax('product/getDetailsPicture', { 137 | data: { 138 | productID 139 | } 140 | }); 141 | this.setData({ 142 | productID, 143 | productImages: productImages.ProductPicture, 144 | productInfo: product.Product[0] 145 | }); 146 | // 获取推荐商品信息 147 | let hotProduct = await $ajax('product/getProductByCategory', { 148 | data: { 149 | categoryID: this.data.productInfo.category_id, 150 | currentPage: 1, 151 | pageSize: 10 152 | } 153 | }); 154 | this.setData({ 155 | hotProduct: hotProduct.Product 156 | }) 157 | }, 158 | 159 | /** 160 | * 生命周期函数--监听页面初次渲染完成 161 | */ 162 | onReady: function() { 163 | 164 | }, 165 | 166 | /** 167 | * 生命周期函数--监听页面显示 168 | */ 169 | onShow: function() { 170 | 171 | }, 172 | 173 | /** 174 | * 生命周期函数--监听页面隐藏 175 | */ 176 | onHide: function() { 177 | 178 | }, 179 | 180 | /** 181 | * 生命周期函数--监听页面卸载 182 | */ 183 | onUnload: function() { 184 | 185 | }, 186 | 187 | /** 188 | * 页面相关事件处理函数--监听用户下拉动作 189 | */ 190 | onPullDownRefresh: function() { 191 | 192 | }, 193 | 194 | /** 195 | * 页面上拉触底事件的处理函数 196 | */ 197 | onReachBottom: function() { 198 | 199 | }, 200 | 201 | /** 202 | * 用户点击右上角分享 203 | */ 204 | onShareAppMessage: function() { 205 | 206 | } 207 | }) -------------------------------------------------------------------------------- /pages/details/details.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "i-tab-bar-item": "../../components/iview/tab-bar-item/index", 4 | "i-cell": "../../components/iview/cell/index", 5 | "my-list": "../../components/Mylist/Mylist", 6 | "i-message": "../../components/iview/message/index" 7 | }, 8 | "navigationBarTitleText": "商品详情" 9 | } -------------------------------------------------------------------------------- /pages/details/details.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {{productInfo.product_name}} 17 | {{productInfo.product_intro}} 18 | 19 | {{productInfo.product_selling_price}}元 20 | {{productInfo.product_price}}元 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 加入购物车 45 | 46 | 47 | 喜欢 48 | 49 | 50 | -------------------------------------------------------------------------------- /pages/details/details.wxss: -------------------------------------------------------------------------------- 1 | /* pages/details/details.wxss */ 2 | 3 | .carousel .product-img { 4 | display: block; 5 | margin: 0 auto; 6 | } 7 | 8 | .pro-info { 9 | margin: 0 10px 10px 10px; 10 | overflow: hidden; 11 | } 12 | 13 | .pro-info .pro-title { 14 | width: 100%; 15 | float: left; 16 | font-size: 14px; 17 | font-weight: 400; 18 | color: #191919; 19 | text-overflow: ellipsis; 20 | overflow: hidden; 21 | display: -webkit-box; 22 | -webkit-line-clamp: 1; 23 | -webkit-box-orient: vertical; 24 | } 25 | 26 | .pro-info .pro-des { 27 | width: 100%; 28 | float: left; 29 | font-size: 12px; 30 | font-weight: 400; 31 | line-height: 20px; 32 | color: #7f7f7f; 33 | padding: 5px 0 5px 0; 34 | text-overflow: ellipsis; 35 | overflow: hidden; 36 | display: -webkit-box; 37 | -webkit-line-clamp: 3; 38 | -webkit-box-orient: vertical; 39 | } 40 | 41 | .pro-info .pro-price { 42 | width: 100%; 43 | height: 20px; 44 | float: left; 45 | font-size: 16px; 46 | color: #ff6700; 47 | text-overflow: ellipsis; 48 | overflow: hidden; 49 | -webkit-line-clamp: 1; 50 | -webkit-box-orient: vertical; 51 | } 52 | 53 | .pro-info .pro-price .del { 54 | font-size: 12px; 55 | height: 20px; 56 | margin-left: 0.5em; 57 | color: #7f7f7f; 58 | text-decoration: line-through; 59 | text-overflow: ellipsis; 60 | overflow: hidden; 61 | -webkit-line-clamp: 1; 62 | -webkit-box-orient: vertical; 63 | } 64 | 65 | /* .pro-info::after { 66 | content: ""; 67 | display: block; 68 | clear: left; 69 | } */ 70 | 71 | .info-list { 72 | padding-top: 8px; 73 | background-color: #f5f5f5; 74 | } 75 | 76 | .bottom-bar { 77 | position: fixed; 78 | left: 0; 79 | bottom: 0; 80 | width: 100%; 81 | height: 50px; 82 | line-height: 50px; 83 | z-index: 9999; 84 | background-color: #fff; 85 | } 86 | 87 | .bottom-bar .shopping-cart { 88 | width: 20%; 89 | float: left; 90 | } 91 | 92 | .bottom-bar .add-shopping-cart { 93 | width: 40%; 94 | float: left; 95 | text-align: center; 96 | color: #fff; 97 | background-color: #ff6700; 98 | } 99 | 100 | .bottom-bar .add-collect { 101 | width: 40%; 102 | float: left; 103 | text-align: center; 104 | color: #fff; 105 | background-color: #b0b0b0; 106 | } 107 | -------------------------------------------------------------------------------- /pages/goods/goods.js: -------------------------------------------------------------------------------- 1 | // pages/goods/goods.js 2 | const { 3 | baseURL, 4 | $ajax 5 | } = getApp().globalData; 6 | Page({ 7 | 8 | /** 9 | * 页面的初始数据 10 | */ 11 | data: { 12 | currentPage: 1, 13 | pageSize: 15, 14 | current_scroll: -1, 15 | category: [], 16 | search: '', 17 | product: [], 18 | productTotal: 0 19 | }, 20 | // 选择分类 21 | handleChangeScroll({detail}) { 22 | if (this.data.current_scroll != detail.key) { 23 | this.setData({ 24 | search: '', 25 | current_scroll: detail.key, 26 | currentPage: 1, 27 | product: [] 28 | }); 29 | // 修改存在globalData中的分类id 30 | getApp().globalData.categoryId = detail.key; 31 | this.getData(); // 获取商品数据 32 | } 33 | }, 34 | onSearch(e){ 35 | let {search} = e.detail; 36 | if (search != this.data.search){ 37 | this.setData({ 38 | search, 39 | current_scroll: -1, 40 | currentPage: 1, 41 | product: [] 42 | }) 43 | this.getData(); // 获取搜索的商品数据 44 | } 45 | }, 46 | // 获取商品数据 47 | async getData() { 48 | let api = ''; 49 | if (this.data.search) { 50 | api = 'product/getProductBySearch'; 51 | } else { 52 | api = this.data.current_scroll == 0 ? 'product/getAllProduct' : 'product/getProductByCategory'; 53 | } 54 | 55 | let productTemp = await $ajax(api, { 56 | data: { 57 | search: this.data.search, 58 | categoryID: this.data.current_scroll, 59 | currentPage: this.data.currentPage, 60 | pageSize: this.data.pageSize 61 | } 62 | }); 63 | const product = this.data.product.concat(productTemp.Product); 64 | this.setData({ 65 | product, 66 | productTotal: productTemp.total 67 | }) 68 | 69 | }, 70 | /** 71 | * 生命周期函数--监听页面加载 72 | */ 73 | onLoad: async function(options) { 74 | // 从后端获取需要的数据 75 | // this.getData(); // 获取商品数据 76 | let categoryRes = await $ajax('product/getCategory'); // 分类列表 77 | 78 | // 处理分类列表,添加“全部” 79 | const all = { 80 | category_id: 0, 81 | category_name: "全部" 82 | }; 83 | let categoryTemp = categoryRes.category 84 | categoryTemp.unshift(all); 85 | 86 | this.setData({ 87 | category: categoryTemp 88 | }) 89 | }, 90 | 91 | /** 92 | * 生命周期函数--监听页面初次渲染完成 93 | */ 94 | onReady: function() { 95 | 96 | }, 97 | 98 | /** 99 | * 生命周期函数--监听页面显示 100 | */ 101 | onShow: function() { 102 | // 获取存在globalData中的分类id 103 | let categoryId = getApp().globalData.categoryId; 104 | // 如果globalData中的分类id与当前页面显示的分类id不等于,重新加载数据 105 | if (categoryId != this.data.current_scroll) { 106 | this.setData({ 107 | current_scroll: categoryId, 108 | search: '', 109 | currentPage: 1, 110 | product: [] 111 | }) 112 | this.getData() 113 | } 114 | }, 115 | 116 | /** 117 | * 生命周期函数--监听页面隐藏 118 | */ 119 | onHide: function() { 120 | 121 | }, 122 | 123 | /** 124 | * 生命周期函数--监听页面卸载 125 | */ 126 | onUnload: function() { 127 | 128 | }, 129 | 130 | /** 131 | * 页面相关事件处理函数--监听用户下拉动作 132 | */ 133 | onPullDownRefresh: function() { 134 | 135 | }, 136 | 137 | /** 138 | * 页面上拉触底事件的处理函数 139 | */ 140 | onReachBottom: function() { 141 | if (this.data.productTotal > this.data.product.length) { 142 | this.setData({ 143 | currentPage: this.data.currentPage + 1 144 | }) 145 | this.getData(); 146 | } 147 | }, 148 | 149 | /** 150 | * 用户点击右上角分享 151 | */ 152 | onShareAppMessage: function() { 153 | 154 | } 155 | }) -------------------------------------------------------------------------------- /pages/goods/goods.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "my-list": "../../components/Mylist/Mylist", 4 | "SearchBar": "../../components/weui/SearchBar/searchbar", 5 | "i-tabs": "../../components/iview/tabs/index", 6 | "i-tab": "../../components/iview/tab/index", 7 | "i-load-more": "../../components/iview/load-more/index" 8 | } 9 | } -------------------------------------------------------------------------------- /pages/goods/goods.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /pages/goods/goods.wxss: -------------------------------------------------------------------------------- 1 | /* pages/goods/goods.wxss */ 2 | page{ 3 | background-color: #f5f5f5; 4 | } 5 | -------------------------------------------------------------------------------- /pages/index/index.js: -------------------------------------------------------------------------------- 1 | //index.js 2 | const { 3 | baseURL, 4 | $ajax 5 | } = getApp().globalData; 6 | Page({ 7 | 8 | /** 9 | * 页面的初始数据 10 | */ 11 | data: { 12 | baseURL, 13 | carousel: '', 14 | category: '', 15 | phoneList: '', 16 | tvList: '', 17 | applianceList: '', 18 | accessoryList: '' 19 | }, 20 | 21 | // 点击分类 22 | tapCategory(e) { 23 | // wx.switchTab不支持传递参数 24 | // 把点击的分类id存在globalData中,跳转发现页面后可以获取到 25 | getApp().globalData.categoryId = e.currentTarget.dataset.categoryid; 26 | // d导航到发现页面 27 | wx.switchTab({ 28 | url: "/pages/goods/goods" 29 | }) 30 | }, 31 | 32 | /** 33 | * 生命周期函数--监听页面加载 34 | */ 35 | onLoad: async function(options) { 36 | // 从后端获取需要的数据 37 | let carouselRes = await $ajax('resources/carousel'); // 轮播图 38 | let categoryRes = await $ajax('product/getCategory'); // 分类列表 39 | // 手机热买推销数据 40 | let phoneList = await $ajax('product/getPromoProduct', { 41 | data: { 42 | categoryName: "手机" 43 | } 44 | }); 45 | // 电视机热买推销数据 46 | let tvList = await $ajax('product/getPromoProduct', { 47 | data: { 48 | categoryName: "电视机" 49 | } 50 | }); 51 | // 家电热买推销数据 52 | let applianceList = await $ajax('product/getHotProduct', { 53 | data: { 54 | categoryName: ["电视机", "空调", "洗衣机"], 55 | } 56 | }); 57 | // 配件热买推销数据 58 | let accessoryList = await $ajax('product/getHotProduct', { 59 | data: { 60 | categoryName: ["保护套", "保护膜", "充电器", "充电宝"] 61 | } 62 | }); 63 | 64 | // 删除最后一条数据,保留6条数据 65 | phoneList.Product.pop(); 66 | tvList.Product.pop(); 67 | applianceList.Product.pop(); 68 | accessoryList.Product.pop(); 69 | 70 | // 处理分类列表 71 | let categoryTemp = []; 72 | let item = []; 73 | for (let i = 0; categoryRes.category.length > i; i++) { 74 | const temp = categoryRes.category[i]; 75 | if ((i + 1) % 4 == 0) { 76 | item.push(temp); 77 | categoryTemp.push(item); 78 | item = []; 79 | } else { 80 | item.push(temp); 81 | } 82 | } 83 | 84 | this.setData({ 85 | carousel: carouselRes.carousel, 86 | category: categoryTemp, 87 | phoneList: phoneList.Product, 88 | tvList: tvList.Product, 89 | applianceList: applianceList.Product, 90 | accessoryList: accessoryList.Product 91 | }) 92 | }, 93 | 94 | /** 95 | * 生命周期函数--监听页面初次渲染完成 96 | */ 97 | onReady: function() { 98 | 99 | }, 100 | 101 | /** 102 | * 生命周期函数--监听页面显示 103 | */ 104 | onShow: function() { 105 | 106 | }, 107 | 108 | /** 109 | * 生命周期函数--监听页面隐藏 110 | */ 111 | onHide: function() { 112 | 113 | }, 114 | 115 | /** 116 | * 生命周期函数--监听页面卸载 117 | */ 118 | onUnload: function() { 119 | 120 | }, 121 | 122 | /** 123 | * 页面相关事件处理函数--监听用户下拉动作 124 | */ 125 | onPullDownRefresh: function() { 126 | 127 | }, 128 | 129 | /** 130 | * 页面上拉触底事件的处理函数 131 | */ 132 | onReachBottom: function() { 133 | 134 | }, 135 | 136 | /** 137 | * 用户点击右上角分享 138 | */ 139 | onShareAppMessage: function() { 140 | 141 | } 142 | }) -------------------------------------------------------------------------------- /pages/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "i-grid": "../../components/iview/grid/index", 4 | "i-grid-item": "../../components/iview/grid-item/index", 5 | "i-grid-icon": "../../components/iview/grid-icon/index", 6 | "i-grid-label": "../../components/iview/grid-label/index", 7 | "my-list": "../../components/Mylist/Mylist" 8 | } 9 | } -------------------------------------------------------------------------------- /pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {{item.category_name}} 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | 3 | /* 分类列表 */ 4 | 5 | .category-list .grid { 6 | height: 70px; 7 | border: 0; 8 | } 9 | 10 | .category-list .grid .item-index--i-grid-item { 11 | border: 0; 12 | padding: 10px 10px 0 10px; 13 | } 14 | 15 | /* 分类列表 */ 16 | -------------------------------------------------------------------------------- /pages/logs/logs.js: -------------------------------------------------------------------------------- 1 | //logs.js 2 | const util = require('../../utils/util.js') 3 | 4 | Page({ 5 | data: { 6 | logs: [] 7 | }, 8 | onLoad: function () { 9 | this.setData({ 10 | logs: (wx.getStorageSync('logs') || []).map(log => { 11 | return util.formatTime(new Date(log)) 12 | }) 13 | }) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /pages/logs/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "查看启动日志", 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /pages/logs/logs.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{index + 1}}. {{log}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /pages/logs/logs.wxss: -------------------------------------------------------------------------------- 1 | .log-list { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 40rpx; 5 | } 6 | .log-item { 7 | margin: 10rpx; 8 | } 9 | -------------------------------------------------------------------------------- /pages/mine/mine.js: -------------------------------------------------------------------------------- 1 | // pages/mine/mine.js 2 | //获取应用实例 3 | const app = getApp() 4 | 5 | Page({ 6 | data: { 7 | userInfo: {}, 8 | hasUserInfo: false, 9 | canIUse: wx.canIUse('button.open-type.getUserInfo') 10 | }, 11 | //事件处理函数 12 | bindViewTap: function() { 13 | wx.navigateTo({ 14 | url: '../logs/logs' 15 | }) 16 | }, 17 | onLoad: function() { 18 | if (app.globalData.userInfo) { 19 | this.setData({ 20 | userInfo: app.globalData.userInfo, 21 | hasUserInfo: true 22 | }) 23 | } else if (this.data.canIUse) { 24 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 25 | // 所以此处加入 callback 以防止这种情况 26 | app.userInfoReadyCallback = res => { 27 | this.setData({ 28 | userInfo: res.userInfo, 29 | hasUserInfo: true 30 | }) 31 | } 32 | } else { 33 | // 在没有 open-type=getUserInfo 版本的兼容处理 34 | wx.getUserInfo({ 35 | success: res => { 36 | app.globalData.userInfo = res.userInfo 37 | this.setData({ 38 | userInfo: res.userInfo, 39 | hasUserInfo: true 40 | }) 41 | } 42 | }) 43 | } 44 | }, 45 | getUserInfo: function(e) { 46 | app.globalData.userInfo = e.detail.userInfo 47 | this.setData({ 48 | userInfo: e.detail.userInfo, 49 | hasUserInfo: true 50 | }) 51 | }, 52 | toOrders() { 53 | // 跳转我的订单页面 54 | wx.navigateTo({ 55 | url: '/pages/orders/orders' 56 | }) 57 | } 58 | }) -------------------------------------------------------------------------------- /pages/mine/mine.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "i-cell": "../../components/iview/cell/index", 4 | "i-card": "../../components/iview/card/index", 5 | "i-icon": "../../components/iview/icon/index" 6 | } 7 | } -------------------------------------------------------------------------------- /pages/mine/mine.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 获取头像昵称 6 | 7 | 8 | 欢迎你! 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /pages/mine/mine.wxss: -------------------------------------------------------------------------------- 1 | /* pages/mine/mine.wxss */ 2 | .mine{ 3 | height: 100%; 4 | width: 100%; 5 | position: absolute; 6 | top: 0px; 7 | bottom: 0px; 8 | background-color: #f5f5f5; 9 | } 10 | .space{ 11 | display: block; 12 | margin-top: 10px; 13 | } 14 | 15 | .userinfo { 16 | display: flex; 17 | flex-direction: column; 18 | align-items: center; 19 | } 20 | 21 | .userinfo-avatar { 22 | width: 128rpx; 23 | height: 128rpx; 24 | margin: 20rpx; 25 | border-radius: 50%; 26 | } 27 | 28 | .userinfo-nickname { 29 | color: #aaa; 30 | } 31 | 32 | .usermotto { 33 | margin-top: 200px; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /pages/orders/orders.js: -------------------------------------------------------------------------------- 1 | // pages/orders/orders.js 2 | const util = require('../../utils/util.js') 3 | const { 4 | baseURL, 5 | $ajax 6 | } = getApp().globalData; 7 | const { 8 | $Message 9 | } = require('../../components/iview/base/index'); 10 | Page({ 11 | 12 | /** 13 | * 页面的初始数据 14 | */ 15 | data: { 16 | baseURL, 17 | util, 18 | orders: [] 19 | }, 20 | 21 | /** 22 | * 生命周期函数--监听页面加载 23 | */ 24 | onLoad: function(options) { 25 | 26 | }, 27 | 28 | /** 29 | * 生命周期函数--监听页面初次渲染完成 30 | */ 31 | onReady: function() { 32 | 33 | }, 34 | 35 | /** 36 | * 生命周期函数--监听页面显示 37 | */ 38 | onShow: async function() { 39 | // 获取用户订单信息 40 | let orderRes = await $ajax('user/order/getOrder', { 41 | data: { 42 | user_id: getApp().globalData.userId 43 | } 44 | }); 45 | if (orderRes.code === "001") { 46 | // 计算每个订单的总价格 47 | let total = []; 48 | for (let i = 0; i < orderRes.orders.length; i++) { 49 | const element = orderRes.orders[i]; 50 | 51 | let totalPrice = 0; 52 | for (let j = 0; j < element.length; j++) { 53 | const temp = element[j]; 54 | totalPrice += temp.product_price * temp.product_num; 55 | 56 | element[j].order_time = util.formatTime(new Date(element[j].order_time)) 57 | } 58 | total.push(totalPrice); 59 | } 60 | this.setData({ 61 | orders: orderRes.orders, 62 | total: total 63 | }); 64 | } else { 65 | $Message({ 66 | content: orderRes.msg, 67 | type: 'error' 68 | }); 69 | } 70 | }, 71 | 72 | /** 73 | * 生命周期函数--监听页面隐藏 74 | */ 75 | onHide: function() { 76 | 77 | }, 78 | 79 | /** 80 | * 生命周期函数--监听页面卸载 81 | */ 82 | onUnload: function() { 83 | 84 | }, 85 | 86 | /** 87 | * 页面相关事件处理函数--监听用户下拉动作 88 | */ 89 | onPullDownRefresh: function() { 90 | 91 | }, 92 | 93 | /** 94 | * 页面上拉触底事件的处理函数 95 | */ 96 | onReachBottom: function() { 97 | 98 | }, 99 | 100 | /** 101 | * 用户点击右上角分享 102 | */ 103 | onShareAppMessage: function() { 104 | 105 | } 106 | }) -------------------------------------------------------------------------------- /pages/orders/orders.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "i-cell": "../../components/iview/cell/index", 4 | "i-card": "../../components/iview/card/index", 5 | "i-message": "../../components/iview/message/index" 6 | }, 7 | "navigationBarTitleText": "我的订单" 8 | } -------------------------------------------------------------------------------- /pages/orders/orders.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{item.product_num}}x 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /pages/orders/orders.wxss: -------------------------------------------------------------------------------- 1 | /* pages/orders/orders.wxss */ 2 | page{ 3 | background-color: #f5f5f5; 4 | } 5 | .space{ 6 | display: block; 7 | margin-top: 10px; 8 | } -------------------------------------------------------------------------------- /pages/shoppingCart/shoppingCart.js: -------------------------------------------------------------------------------- 1 | // pages/shoppingCart/shoppingCart.js 2 | 3 | import create from '../../utils/create'; 4 | import store from '../../store/index'; 5 | const { 6 | $Message 7 | } = require('../../components/iview/base/index'); 8 | const { 9 | baseURL, 10 | $ajax 11 | } = getApp().globalData; 12 | 13 | create.Page(store, { 14 | 15 | use: ['shoppingCart'], 16 | /** 17 | * 页面的初始数据 18 | */ 19 | data: { 20 | baseURL 21 | }, 22 | computed: { 23 | // 获取购物车状态 24 | getShoppingCart() { 25 | return store.getShoppingCart(); 26 | }, 27 | // 判断是否全选 28 | getIsAllCheck() { 29 | return store.getIsAllCheck(); 30 | }, 31 | // 获取购物车勾选的商品数量 32 | getCheckNum() { 33 | return store.getCheckNum(); 34 | }, 35 | getTotalPrice() { 36 | return store.getTotalPrice(); 37 | } 38 | }, 39 | /** 40 | * 修改商品数量 41 | */ 42 | async handleChangeNum(e) { 43 | // 判断数量是否发生变化 44 | if (e.detail.value == e.target.dataset.value) { 45 | return; 46 | } 47 | // 当修改数量时,默认勾选 48 | this.handleChangeChecked(e); 49 | // 向后端发起更新购物车的数据库信息请求 50 | let updateShoppingCartRes = await $ajax('user/shoppingCart/updateShoppingCart', { 51 | data: { 52 | user_id: getApp().globalData.userId, 53 | product_id: e.target.dataset.productid, 54 | num: e.detail.value 55 | } 56 | }); 57 | 58 | switch (updateShoppingCartRes.code) { 59 | case "001": 60 | // 001代表更新成功 61 | // 更新状态 62 | store.updateShoppingCart({ 63 | key: e.target.dataset.key, 64 | prop: "num", 65 | val: e.detail.value 66 | }); 67 | break; 68 | default: 69 | // 提示更新失败信息 70 | $Message({ 71 | content: updateShoppingCartRes.msg, 72 | type: 'error' 73 | }); 74 | } 75 | }, 76 | /** 77 | * 修改商品勾选状态 78 | */ 79 | handleChangeChecked(e) { 80 | store.updateShoppingCart({ 81 | key: e.target.dataset.key, 82 | prop: "check", 83 | val: !e.target.dataset.checked 84 | }); 85 | }, 86 | /** 87 | * 全选按钮 88 | */ 89 | handleChangeCheckAll(e) { 90 | store.checkAll(!e.target.dataset.value) 91 | }, 92 | /** 93 | * 删除购物车商品 94 | */ 95 | async bindDelete(e) { 96 | // 向后端发起删除购物车的数据库信息请求 97 | let deleteShoppingCartRes = await $ajax('user/shoppingCart/deleteShoppingCart', { 98 | data: { 99 | user_id: getApp().globalData.userId, 100 | product_id: e.target.dataset.productid 101 | } 102 | }); 103 | switch (deleteShoppingCartRes.code) { 104 | case "001": 105 | // 001删除成功 106 | // 更新状态 107 | store.deleteShoppingCart(e.target.dataset.productid); 108 | // 提示删除成功信息 109 | $Message({ 110 | content: deleteShoppingCartRes.msg, 111 | type: 'success' 112 | }); 113 | break; 114 | default: 115 | // 提示删除失败信息 116 | $Message({ 117 | content: deleteShoppingCartRes.msg, 118 | type: 'error' 119 | }); 120 | } 121 | }, 122 | /** 123 | * 去结算 124 | */ 125 | toPay(){ 126 | if (!this.data.getCheckNum){ 127 | $Message({ 128 | content: '请先勾选商品再结算!', 129 | type: 'error' 130 | }); 131 | return; 132 | } 133 | wx.navigateTo({ 134 | url: '/pages/confirmOrder/confirmOrder' 135 | }) 136 | }, 137 | /** 138 | * 生命周期函数--监听页面加载 139 | */ 140 | onLoad: async function(options) { 141 | 142 | }, 143 | 144 | /** 145 | * 生命周期函数--监听页面初次渲染完成 146 | */ 147 | onReady: function() { 148 | 149 | }, 150 | 151 | /** 152 | * 生命周期函数--监听页面显示 153 | */ 154 | onShow: function() { 155 | 156 | }, 157 | 158 | /** 159 | * 生命周期函数--监听页面隐藏 160 | */ 161 | onHide: function() { 162 | 163 | }, 164 | 165 | /** 166 | * 生命周期函数--监听页面卸载 167 | */ 168 | onUnload: function() { 169 | 170 | }, 171 | 172 | /** 173 | * 页面相关事件处理函数--监听用户下拉动作 174 | */ 175 | onPullDownRefresh: function() { 176 | 177 | }, 178 | 179 | /** 180 | * 页面上拉触底事件的处理函数 181 | */ 182 | onReachBottom: function() { 183 | 184 | }, 185 | 186 | /** 187 | * 用户点击右上角分享 188 | */ 189 | onShareAppMessage: function() { 190 | 191 | } 192 | }) -------------------------------------------------------------------------------- /pages/shoppingCart/shoppingCart.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "i-card": "../../components/iview/card/index", 4 | "i-input-number": "../../components/iview/input-number/index", 5 | "i-message": "../../components/iview/message/index", 6 | "i-icon": "../../components/iview/icon/index" 7 | } 8 | } -------------------------------------------------------------------------------- /pages/shoppingCart/shoppingCart.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 小计:{{item.num*item.price}}元 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 您的购物车还是空的哦! 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 已选: {{getCheckNum}}件 26 | 结算 27 | 合计: {{getTotalPrice}}元 28 | 29 | -------------------------------------------------------------------------------- /pages/shoppingCart/shoppingCart.wxss: -------------------------------------------------------------------------------- 1 | /* pages/shoppingCart/shoppingCart.wxss */ 2 | 3 | .total { 4 | float: left; 5 | color: #ff6700; 6 | } 7 | 8 | .input-number { 9 | float: right; 10 | } 11 | 12 | .delete { 13 | float: right; 14 | margin-right: 5px; 15 | } 16 | 17 | .cart-tabbar { 18 | position: fixed; 19 | left: 0; 20 | bottom: 0; 21 | height: 50px; 22 | line-height: 50px; 23 | font-size: 12px; 24 | color: #8a8a8a; 25 | width: 100%; 26 | z-index: 9999; 27 | padding-left: 5px; 28 | border-top: 1px solid #dddee1; 29 | background-color: #fff; 30 | } 31 | 32 | .cart-tabbar .check-box { 33 | float: left; 34 | } 35 | 36 | .cart-tabbar .num { 37 | font-size: 16px; 38 | color: #ff6700; 39 | } 40 | 41 | .cart-tabbar .totalNum { 42 | float: left; 43 | width: 80px; 44 | font-size: 14px; 45 | vertical-align: middle; 46 | text-overflow: ellipsis; 47 | overflow: hidden; 48 | display: -webkit-box; 49 | -webkit-line-clamp: 1; 50 | -webkit-box-orient: vertical; 51 | } 52 | 53 | .cart-tabbar .totalPrice { 54 | float: right; 55 | width: calc(100% - 225px); 56 | font-size: 14px; 57 | vertical-align: middle; 58 | padding-right: 5px; 59 | text-align: right; 60 | text-overflow: ellipsis; 61 | overflow: hidden; 62 | display: -webkit-box; 63 | -webkit-line-clamp: 1; 64 | -webkit-box-orient: vertical; 65 | } 66 | 67 | .cart-tabbar .btn { 68 | float: right; 69 | width: 100px; 70 | height: 48px; 71 | line-height: 48px; 72 | padding: 0; 73 | color: #fff; 74 | font-weight: 500; 75 | background-color: #ff6700; 76 | border-radius: 30px; 77 | margin: 1px 10px 1px 0; 78 | } 79 | 80 | .cart-empty { 81 | height: 100%; 82 | width: 100%; 83 | position: absolute; 84 | top: 0px; 85 | bottom: 0px; 86 | background-color: #f7f7f7; 87 | } 88 | 89 | .cart-empty image { 90 | display: block; 91 | margin: 0 auto; 92 | padding-top: 50px; 93 | width: 147px; 94 | height: 136px; 95 | } 96 | 97 | .cart-empty text { 98 | display: block; 99 | width: 100%; 100 | font-weight: 600; 101 | text-align: center; 102 | color: #b0b0b0; 103 | padding-top: 20px; 104 | } 105 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": false, 8 | "es6": true, 9 | "enhance": true, 10 | "postcss": true, 11 | "minified": true, 12 | "newFeature": true, 13 | "coverView": true, 14 | "nodeModules": false, 15 | "autoAudits": false, 16 | "showShadowRootInWxmlPanel": true, 17 | "scopeDataCheck": true, 18 | "checkInvalidKey": true, 19 | "checkSiteMap": true, 20 | "uploadWithSourceMap": true, 21 | "babelSetting": { 22 | "ignore": [], 23 | "disablePlugins": [], 24 | "outputPath": "" 25 | }, 26 | "bundle": false 27 | }, 28 | "compileType": "miniprogram", 29 | "libVersion": "2.10.3", 30 | "appid": "wxeb6a44c58ffde6c6", 31 | "projectname": "store-miniprogram", 32 | "debugOptions": { 33 | "hidedInDevtools": [] 34 | }, 35 | "isGameTourist": false, 36 | "simulatorType": "wechat", 37 | "simulatorPluginLibVersion": {}, 38 | "condition": { 39 | "search": { 40 | "current": -1, 41 | "list": [] 42 | }, 43 | "conversation": { 44 | "current": -1, 45 | "list": [] 46 | }, 47 | "plugin": { 48 | "current": -1, 49 | "list": [] 50 | }, 51 | "game": { 52 | "currentL": -1, 53 | "list": [] 54 | }, 55 | "gamePlugin": { 56 | "current": -1, 57 | "list": [] 58 | }, 59 | "miniprogram": { 60 | "current": -1, 61 | "list": [ 62 | { 63 | "id": 0, 64 | "name": "发现", 65 | "pathName": "pages/goods/goods", 66 | "query": "", 67 | "scene": null 68 | }, 69 | { 70 | "id": 1, 71 | "name": "pages/details/details", 72 | "pathName": "pages/details/details", 73 | "query": "productID=23", 74 | "scene": null 75 | }, 76 | { 77 | "id": -1, 78 | "name": "购物车", 79 | "pathName": "pages/shoppingCart/shoppingCart", 80 | "query": "", 81 | "scene": null 82 | }, 83 | { 84 | "id": 3, 85 | "name": "确认订单", 86 | "pathName": "pages/confirmOrder/confirmOrder", 87 | "query": "", 88 | "scene": null 89 | }, 90 | { 91 | "id": -1, 92 | "name": "订单", 93 | "pathName": "pages/orders/orders", 94 | "query": "", 95 | "scene": null 96 | }, 97 | { 98 | "id": 5, 99 | "name": "我的", 100 | "pathName": "pages/mine/mine", 101 | "query": "", 102 | "scene": null 103 | } 104 | ] 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /sitemap.json: -------------------------------------------------------------------------------- 1 | { 2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", 3 | "rules": [{ 4 | "action": "allow", 5 | "page": "*" 6 | }] 7 | } -------------------------------------------------------------------------------- /static/icon/category_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/category_1.png -------------------------------------------------------------------------------- /static/icon/category_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/category_2.png -------------------------------------------------------------------------------- /static/icon/category_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/category_3.png -------------------------------------------------------------------------------- /static/icon/category_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/category_4.png -------------------------------------------------------------------------------- /static/icon/category_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/category_5.png -------------------------------------------------------------------------------- /static/icon/category_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/category_6.png -------------------------------------------------------------------------------- /static/icon/category_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/category_7.png -------------------------------------------------------------------------------- /static/icon/category_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/category_8.png -------------------------------------------------------------------------------- /static/icon/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/home.png -------------------------------------------------------------------------------- /static/icon/home_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/home_fill.png -------------------------------------------------------------------------------- /static/icon/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/search.png -------------------------------------------------------------------------------- /static/icon/search_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/search_fill.png -------------------------------------------------------------------------------- /static/icon/shoppingCart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/shoppingCart.png -------------------------------------------------------------------------------- /static/icon/shoppingCart_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/shoppingCart_fill.png -------------------------------------------------------------------------------- /static/icon/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/user.png -------------------------------------------------------------------------------- /static/icon/user_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/icon/user_fill.png -------------------------------------------------------------------------------- /static/imgs/cart-empty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hai-27/store-miniprogram/433f338496914592fde82c8bab0c08c3cfee84bd/static/imgs/cart-empty.jpg -------------------------------------------------------------------------------- /store/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | shoppingCart, 3 | getters, 4 | actions 5 | } from '/shoppingCart.js'; 6 | 7 | const store = { 8 | data: { 9 | shoppingCart: shoppingCart 10 | }, 11 | ...getters, 12 | ...actions, 13 | //无脑全部更新,组件或页面不需要声明 use 14 | //updateAll: true, 15 | debug: true 16 | } 17 | export default store -------------------------------------------------------------------------------- /store/shoppingCart.js: -------------------------------------------------------------------------------- 1 | export const shoppingCart = [] 2 | 3 | /* 4 | // shoppingCart结构 5 | shoppingCart = { 6 | id: "", // 购物车id 7 | productID: "", // 商品id 8 | productName: "", // 商品名称 9 | productImg: "", // 商品图片 10 | price: "", // 商品价格 11 | num: "", // 商品数量 12 | maxNum: "", // 商品限购数量 13 | check: false // 是否勾选 14 | } */ 15 | 16 | export const getters = { 17 | getShoppingCart() { 18 | // 获取购物车状态 19 | return this.data.shoppingCart; 20 | }, 21 | getNum() { 22 | // 购物车商品总数量 23 | let totalNum = 0; 24 | for (let i = 0; i < this.data.shoppingCart.length; i++) { 25 | const temp = this.data.shoppingCart[i]; 26 | totalNum += temp.num; 27 | } 28 | return totalNum; 29 | }, 30 | getIsAllCheck() { 31 | // 判断是否全选 32 | let isAllCheck = true; 33 | if (this.data.shoppingCart.length==0){ 34 | isAllCheck = false; 35 | return isAllCheck; 36 | } 37 | for (let i = 0; i < this.data.shoppingCart.length; i++) { 38 | const temp = this.data.shoppingCart[i]; 39 | // 只要有一个商品没有勾选立即return false; 40 | if (!temp.check) { 41 | isAllCheck = false; 42 | return isAllCheck; 43 | } 44 | } 45 | return isAllCheck; 46 | }, 47 | getCheckGoods() { 48 | // 获取勾选的商品信息 49 | // 用于确认订单页面 50 | let checkGoods = []; 51 | for (let i = 0; i < this.data.shoppingCart.length; i++) { 52 | const temp = this.data.shoppingCart[i]; 53 | if (temp.check) { 54 | checkGoods.push(temp); 55 | } 56 | } 57 | return checkGoods; 58 | }, 59 | getCheckNum() { 60 | // 获取购物车勾选的商品数量 61 | let totalNum = 0; 62 | for (let i = 0; i < this.data.shoppingCart.length; i++) { 63 | const temp = this.data.shoppingCart[i]; 64 | if (temp.check) { 65 | totalNum += temp.num; 66 | } 67 | } 68 | return totalNum; 69 | }, 70 | getTotalPrice() { 71 | // 购物车勾选的商品总价格 72 | let totalPrice = 0; 73 | for (let i = 0; i < this.data.shoppingCart.length; i++) { 74 | const temp = this.data.shoppingCart[i]; 75 | if (temp.check) { 76 | totalPrice += temp.price * temp.num; 77 | } 78 | } 79 | return totalPrice; 80 | } 81 | }; 82 | 83 | export const actions = { 84 | unshiftShoppingCart(data) { 85 | // 添加购物车 86 | // 用于在商品详情页点击添加购物车,后台添加成功后,更新状态 87 | this.data.shoppingCart.unshift(data); 88 | }, 89 | updateShoppingCart(payload) { 90 | // 更新购物车 91 | // 可更新商品数量和是否勾选 92 | // 用于购物车点击勾选及加减商品数量 93 | if (payload.prop == "num") { 94 | // 判断效果的商品数量是否大于限购数量或小于1 95 | if (this.data.shoppingCart[payload.key].maxNum < payload.val) { 96 | return; 97 | } 98 | if (payload.val < 1) { 99 | return; 100 | } 101 | } 102 | // 根据商品在购物车的数组的索引和属性更改 103 | this.data.shoppingCart[payload.key][payload.prop] = payload.val; 104 | }, 105 | addShoppingCartNum(productID) { 106 | // 增加购物车商品数量 107 | // 用于在商品详情页点击添加购物车,后台返回002,“该商品已在购物车,数量 +1”,更新商品数量 108 | for (let i = 0; i < this.data.shoppingCart.length; i++) { 109 | const temp = this.data.shoppingCart[i]; 110 | if (temp.productID == productID) { 111 | if (temp.num < temp.maxNum) { 112 | temp.num++; 113 | } 114 | } 115 | } 116 | }, 117 | deleteShoppingCart(productID) { 118 | // 根据购物车id删除购物车商品 119 | for (let i = 0; i < this.data.shoppingCart.length; i++) { 120 | const temp = this.data.shoppingCart[i]; 121 | if (temp.productID == productID) { 122 | console.log("说出来") 123 | this.data.shoppingCart.splice(i, 1); 124 | } 125 | } 126 | }, 127 | checkAll(data) { 128 | // 点击全选按钮,更改每个商品的勾选状态 129 | for (let i = 0; i < this.data.shoppingCart.length; i++) { 130 | this.data.shoppingCart[i].check = data; 131 | } 132 | } 133 | }; 134 | 135 | // export default { 136 | // shoppingCart, 137 | // getters, 138 | // actions 139 | // } -------------------------------------------------------------------------------- /utils/create.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * omix v2.4.0 by dntzhang 3 | * Github: https://github.com/Tencent/omi 4 | * MIT Licensed. 5 | */ 6 | 7 | import obaa from './obaa' 8 | import { getPath, needUpdate, fixPath, getUsing } from './path' 9 | 10 | function create(store, option) { 11 | if (arguments.length === 2) { 12 | if (!store.instances) { 13 | store.instances = {} 14 | } 15 | 16 | if (!store.__changes_) { 17 | store.__changes_ = [] 18 | } 19 | 20 | const changes = store.__changes_ 21 | if (!store.onChange) { 22 | store.onChange = function (fn) { 23 | changes.push(fn) 24 | } 25 | } 26 | 27 | if (!store.offChange) { 28 | store.offChange = function (fn) { 29 | for (let i = 0, len = changes.length; i < len; i++) { 30 | if (changes[i] === fn) { 31 | changes.splice(i, 1) 32 | break 33 | } 34 | } 35 | } 36 | } 37 | const hasData = typeof option.data !== 'undefined' 38 | let clone 39 | if (option.data) { 40 | clone = JSON.parse(JSON.stringify(option.data)) 41 | option.data.$ = store.data 42 | } else { 43 | option.data = store.data 44 | } 45 | observeStore(store) 46 | const onLoad = option.onLoad 47 | const onUnload = option.onUnload 48 | 49 | option.onLoad = function (e) { 50 | this.store = store 51 | 52 | option.use && (this.__updatePath = getPath(option.use)) 53 | this.__use = option.use 54 | this.__hasData = hasData 55 | if (hasData) { 56 | Object.assign(option.data, JSON.parse(JSON.stringify(clone))) 57 | } 58 | store.instances[this.route] = store.instances[this.route] || [] 59 | store.instances[this.route].push(this) 60 | this.computed = option.computed 61 | this.setData(option.data) 62 | const using = getUsing(store.data, option.use) 63 | 64 | option.computed && compute(option.computed, store, using, this) 65 | this.setData(using) 66 | 67 | onLoad && onLoad.call(this, e) 68 | } 69 | 70 | option.onUnload = function (e) { 71 | store.instances[this.route] = store.instances[this.route].filter(ins => ins !== this) 72 | onUnload && onUnload.call(this, e) 73 | } 74 | 75 | Page(option) 76 | } else { 77 | store.lifetimes = store.lifetimes || {} 78 | const ready = store.lifetimes.ready || store.ready 79 | 80 | store.ready = store.lifetimes.ready = function () { 81 | const page = getCurrentPages()[getCurrentPages().length - 1] 82 | store.use && (this.__updatePath = getPath(store.use)) 83 | this.store = page.store 84 | this.__use = store.use 85 | 86 | this.computed = store.computed 87 | store.data = this.store.data 88 | this.setData(store.data) 89 | const using = getUsing(this.store.data, store.use) 90 | 91 | store.computed && compute(store.computed, this.store, using, this) 92 | this.setData(using) 93 | 94 | page._omixComponents = page._omixComponents || [] 95 | page._omixComponents.push(this) 96 | ready && ready.call(this) 97 | } 98 | Component(store) 99 | } 100 | } 101 | 102 | create.Page = function (store, option) { 103 | create(store, option) 104 | } 105 | 106 | create.Component = function (store, option) { 107 | if (arguments.length === 2) { 108 | if (!store.instances) { 109 | store.instances = {} 110 | } 111 | 112 | if (!store.__changes_) { 113 | store.__changes_ = [] 114 | } 115 | 116 | const changes = store.__changes_ 117 | if (!store.onChange) { 118 | store.onChange = function (fn) { 119 | changes.push(fn) 120 | } 121 | } 122 | 123 | if (!store.offChange) { 124 | store.offChange = function (fn) { 125 | for (let i = 0, len = changes.length; i < len; i++) { 126 | if (changes[i] === fn) { 127 | changes.splice(i, 1) 128 | break 129 | } 130 | } 131 | } 132 | } 133 | const hasData = typeof option.data !== 'undefined' 134 | let clone 135 | if (option.data) { 136 | clone = JSON.parse(JSON.stringify(option.data)) 137 | option.data.$ = store.data 138 | } else { 139 | option.data = store.data 140 | } 141 | observeStore(store) 142 | 143 | const detached = option.detached 144 | 145 | option.lifetimes = option.lifetimes || {} 146 | const created = option.lifetimes.created || option.created 147 | const ready = option.lifetimes.ready || option.ready 148 | 149 | option.created = option.lifetimes.created = function (e) { 150 | this.store = store 151 | 152 | option.use && (this.__updatePath = getPath(option.use)) 153 | this.__use = option.use 154 | this.__hasData = hasData 155 | if (hasData) { 156 | Object.assign(option.data, JSON.parse(JSON.stringify(clone))) 157 | } 158 | 159 | created && created.call(this, e) 160 | } 161 | 162 | option.ready = option.lifetimes.ready = function (e) { 163 | const store = this.store 164 | store.instances[this.route] = store.instances[this.route] || [] 165 | store.instances[this.route].push(this) 166 | this.computed = option.computed 167 | this.setData(option.data) 168 | const using = getUsing(store.data, option.use) 169 | 170 | option.computed && compute(option.computed, store, using, this) 171 | this.setData(using) 172 | 173 | ready && ready.call(this, e) 174 | } 175 | 176 | option.lifetimes.detached = option.detached = function (e) { 177 | this.store.instances[this.route] = this.store.instances[this.route].filter(ins => ins !== this) 178 | detached && detached.call(this, e) 179 | } 180 | 181 | Component(option) 182 | } else { 183 | store.lifetimes = store.lifetimes || {} 184 | const ready = store.lifetimes.ready || store.ready 185 | 186 | store.ready = store.lifetimes.ready = function () { 187 | const page = getCurrentPages()[getCurrentPages().length - 1] 188 | store.use && (this.__updatePath = getPath(store.use)) 189 | this.store = page.store 190 | this.__use = store.use 191 | this.computed = store.computed 192 | store.data = this.store.data 193 | this.setData(store.data) 194 | const using = getUsing(this.store.data, store.use) 195 | 196 | store.computed && compute(store.computed, this.store, using, this) 197 | this.setData(using) 198 | 199 | page._omixComponents = page._omixComponents || [] 200 | page._omixComponents.push(this) 201 | ready && ready.call(this) 202 | } 203 | Component(store) 204 | } 205 | } 206 | 207 | function compute(computed, store, using, scope) { 208 | for (let key in computed) { 209 | using[key] = computed[key].call(store.data, scope) 210 | } 211 | } 212 | 213 | function observeStore(store) { 214 | const oba = obaa(store.data, (prop, value, old, path) => { 215 | let patch = {} 216 | if (prop.indexOf('Array-push') === 0) { 217 | let dl = value.length - old.length 218 | for (let i = 0; i < dl; i++) { 219 | patch[fixPath(path + '-' + (old.length + i))] = value[(old.length + i)] 220 | } 221 | } else if (prop.indexOf('Array-') === 0) { 222 | patch[fixPath(path)] = value 223 | } else { 224 | patch[fixPath(path + '-' + prop)] = value 225 | } 226 | 227 | _update(patch, store) 228 | 229 | 230 | }) 231 | 232 | if (!store.set) { 233 | store.set = function (obj, prop, val) { 234 | obaa.set(obj, prop, val, oba) 235 | } 236 | } 237 | 238 | const backer = store.data 239 | Object.defineProperty(store, 'data', { 240 | enumerable: true, 241 | get: function() { 242 | return backer 243 | }, 244 | set: function() { 245 | throw new Error('You must not replace store.data directly, instead assign nest prop') 246 | } 247 | }) 248 | } 249 | 250 | function _update(kv, store) { 251 | for (let key in store.instances) { 252 | store.instances[key].forEach(ins => { 253 | _updateOne(kv, store, ins) 254 | if(ins._omixComponents){ 255 | ins._omixComponents.forEach(compIns => { 256 | _updateOne(kv, store, compIns) 257 | }) 258 | } 259 | }) 260 | } 261 | store.__changes_.forEach(change => { 262 | change(kv) 263 | }) 264 | store.debug && storeChangeLogger(store, kv) 265 | } 266 | 267 | function _updateOne(kv, store, ins){ 268 | if (!(store.updateAll || ins.__updatePath && needUpdate(kv, ins.__updatePath))) { 269 | return 270 | } 271 | if (!ins.__hasData) { 272 | return _updateImpl(kv, store, ins) 273 | } 274 | const patch = Object.assign({}, kv) 275 | for (let pk in patch) { 276 | if (!/\$\./.test(pk)) { 277 | patch['$.' + pk] = kv[pk] 278 | delete patch[pk] 279 | } 280 | } 281 | _updateImpl(patch, store, ins) 282 | } 283 | 284 | function _updateImpl(data, store, ins) { 285 | if (!wx.nextTick) { 286 | return _doUpdate(data, store, ins) 287 | } 288 | if (ins._omixDataBuffer === undefined) { 289 | ins._omixDataBuffer = {} 290 | } 291 | Object.assign(ins._omixDataBuffer, data) 292 | if (!ins._omixTickScheduled) { 293 | wx.nextTick(function() { 294 | _doUpdate(ins._omixDataBuffer, store, ins) 295 | ins._omixDataBuffer = {} 296 | ins._omixTickScheduled = false 297 | }) 298 | ins._omixTickScheduled = true 299 | } 300 | } 301 | 302 | function _doUpdate(data, store, ins) { 303 | if (Object.keys(data).length === 0) { 304 | return 305 | } 306 | ins.setData.call(ins, data) 307 | const using = getUsing(store.data, ins.__use) 308 | ins.computed && compute(ins.computed, store, using, ins) 309 | ins.setData.call(ins, using) 310 | } 311 | 312 | function storeChangeLogger(store, diffResult) { 313 | try { 314 | const preState = wx.getStorageSync(`CurrentState`) || {} 315 | const title = `Data Changed` 316 | console.groupCollapsed(`%c ${title} %c ${Object.keys(diffResult)}`, 'color:#e0c184; font-weight: bold', 'color:#f0a139; font-weight: bold') 317 | console.log(`%c Pre Data`, 'color:#ff65af; font-weight: bold', preState) 318 | console.log(`%c Change Data`, 'color:#3d91cf; font-weight: bold', diffResult) 319 | console.log(`%c Next Data`, 'color:#2c9f67; font-weight: bold', store.data) 320 | console.groupEnd() 321 | wx.setStorageSync(`CurrentState`, store.data) 322 | } catch (e) { 323 | console.log(e) 324 | } 325 | } 326 | 327 | 328 | 329 | create.obaa = obaa 330 | 331 | 332 | export default create 333 | -------------------------------------------------------------------------------- /utils/obaa.js: -------------------------------------------------------------------------------- 1 | /* obaa 1.0.0 2 | * By dntzhang 3 | * Github: https://github.com/Tencent/omi 4 | * MIT Licensed. 5 | */ 6 | 7 | export default function obaa(target, arr, callback) { 8 | var _observe = function (target, arr, callback) { 9 | //if (!target.$observer) target.$observer = this 10 | var $observer = this 11 | var eventPropArr = [] 12 | if (obaa.isArray(target)) { 13 | if (target.length === 0) { 14 | $observer.track(target) 15 | } 16 | $observer.mock(target) 17 | } 18 | if (target && typeof target === 'object' && Object.keys(target).length === 0) { 19 | $observer.track(target) 20 | } 21 | for (var prop in target) { 22 | if (target.hasOwnProperty(prop)) { 23 | if (callback) { 24 | if (obaa.isArray(arr) && obaa.isInArray(arr, prop)) { 25 | eventPropArr.push(prop) 26 | $observer.watch(target, prop) 27 | } else if (obaa.isString(arr) && prop == arr) { 28 | eventPropArr.push(prop) 29 | $observer.watch(target, prop) 30 | } 31 | } else { 32 | eventPropArr.push(prop) 33 | $observer.watch(target, prop) 34 | } 35 | } 36 | } 37 | $observer.target = target 38 | if (!$observer.propertyChangedHandler) 39 | $observer.propertyChangedHandler = [] 40 | var propChanged = callback ? callback : arr 41 | $observer.propertyChangedHandler.push({ 42 | all: !callback, 43 | propChanged: propChanged, 44 | eventPropArr: eventPropArr 45 | }) 46 | } 47 | _observe.prototype = { 48 | onPropertyChanged: function (prop, value, oldValue, target, path) { 49 | if (value !== oldValue && (!(nan(value) && nan(oldValue))) && this.propertyChangedHandler) { 50 | var rootName = obaa._getRootName(prop, path) 51 | for ( 52 | var i = 0, len = this.propertyChangedHandler.length; 53 | i < len; 54 | i++ 55 | ) { 56 | var handler = this.propertyChangedHandler[i] 57 | if ( 58 | handler.all || 59 | obaa.isInArray(handler.eventPropArr, rootName) || 60 | rootName.indexOf('Array-') === 0 61 | ) { 62 | handler.propChanged.call(this.target, prop, value, oldValue, path) 63 | } 64 | } 65 | } 66 | if (prop.indexOf('Array-') !== 0 && typeof value === 'object') { 67 | this.watch(target, prop, target.$observeProps.$observerPath) 68 | } 69 | }, 70 | mock: function (target) { 71 | var self = this 72 | obaa.methods.forEach(function (item) { 73 | target[item] = function () { 74 | var old = Array.prototype.slice.call(this, 0) 75 | var result = Array.prototype[item].apply( 76 | this, 77 | Array.prototype.slice.call(arguments) 78 | ) 79 | if (new RegExp('\\b' + item + '\\b').test(obaa.triggerStr)) { 80 | for (var cprop in this) { 81 | if ( 82 | this.hasOwnProperty(cprop) && 83 | !obaa.isFunction(this[cprop]) 84 | ) { 85 | self.watch(this, cprop, this.$observeProps.$observerPath) 86 | } 87 | } 88 | //todo 89 | self.onPropertyChanged( 90 | 'Array-' + item, 91 | this, 92 | old, 93 | this, 94 | this.$observeProps.$observerPath 95 | ) 96 | } 97 | return result 98 | } 99 | target[ 100 | 'pure' + item.substring(0, 1).toUpperCase() + item.substring(1) 101 | ] = function () { 102 | return Array.prototype[item].apply( 103 | this, 104 | Array.prototype.slice.call(arguments) 105 | ) 106 | } 107 | }) 108 | }, 109 | watch: function (target, prop, path) { 110 | if (prop === '$observeProps' || prop === '$observer') return 111 | if (obaa.isFunction(target[prop])) return 112 | if (!target.$observeProps) { 113 | Object.defineProperty(target, '$observeProps', { 114 | configurable: true, 115 | enumerable: false, 116 | writable: true, 117 | value: {} 118 | }) 119 | } 120 | if (path !== undefined) { 121 | target.$observeProps.$observerPath = path 122 | } else { 123 | target.$observeProps.$observerPath = '#' 124 | } 125 | var self = this 126 | var currentValue = (target.$observeProps[prop] = target[prop]) 127 | Object.defineProperty(target, prop, { 128 | get: function () { 129 | return this.$observeProps[prop] 130 | }, 131 | set: function (value) { 132 | var old = this.$observeProps[prop] 133 | this.$observeProps[prop] = value 134 | self.onPropertyChanged( 135 | prop, 136 | value, 137 | old, 138 | this, 139 | target.$observeProps.$observerPath 140 | ) 141 | } 142 | }) 143 | if (typeof currentValue == 'object') { 144 | if (obaa.isArray(currentValue)) { 145 | this.mock(currentValue) 146 | //为0,就不会进下面的 for 循环,就不会执行里面的 watch,就不会有 $observeProps 属性 147 | if (currentValue.length === 0) { 148 | this.track(currentValue, prop, path) 149 | } 150 | } 151 | if (currentValue && Object.keys(currentValue).length === 0) { 152 | this.track(currentValue, prop, path) 153 | } 154 | for (var cprop in currentValue) { 155 | if (currentValue.hasOwnProperty(cprop)) { 156 | this.watch( 157 | currentValue, 158 | cprop, 159 | target.$observeProps.$observerPath + '-' + prop 160 | ) 161 | } 162 | } 163 | } 164 | }, 165 | track: function(obj, prop, path) { 166 | if (obj.$observeProps) { 167 | return 168 | } 169 | Object.defineProperty(obj, '$observeProps', { 170 | configurable: true, 171 | enumerable: false, 172 | writable: true, 173 | value: {} 174 | }) 175 | if (path !== undefined && path !== null) { 176 | obj.$observeProps.$observerPath = path + '-' + prop 177 | } else { 178 | if (prop !== undefined && prop !== null) { 179 | obj.$observeProps.$observerPath = '#' + '-' + prop 180 | } else { 181 | obj.$observeProps.$observerPath = '#' 182 | } 183 | } 184 | } 185 | } 186 | return new _observe(target, arr, callback) 187 | } 188 | 189 | obaa.methods = [ 190 | 'concat', 191 | 'copyWithin', 192 | 'entries', 193 | 'every', 194 | 'fill', 195 | 'filter', 196 | 'find', 197 | 'findIndex', 198 | 'forEach', 199 | 'includes', 200 | 'indexOf', 201 | 'join', 202 | 'keys', 203 | 'lastIndexOf', 204 | 'map', 205 | 'pop', 206 | 'push', 207 | 'reduce', 208 | 'reduceRight', 209 | 'reverse', 210 | 'shift', 211 | 'slice', 212 | 'some', 213 | 'sort', 214 | 'splice', 215 | 'toLocaleString', 216 | 'toString', 217 | 'unshift', 218 | 'values', 219 | 'size' 220 | ] 221 | obaa.triggerStr = [ 222 | 'concat', 223 | 'copyWithin', 224 | 'fill', 225 | 'pop', 226 | 'push', 227 | 'reverse', 228 | 'shift', 229 | 'sort', 230 | 'splice', 231 | 'unshift', 232 | 'size' 233 | ].join(',') 234 | 235 | obaa.isArray = function (obj) { 236 | return Object.prototype.toString.call(obj) === '[object Array]' 237 | } 238 | 239 | obaa.isString = function (obj) { 240 | return typeof obj === 'string' 241 | } 242 | 243 | obaa.isInArray = function (arr, item) { 244 | for (var i = arr.length; --i > -1;) { 245 | if (item === arr[i]) return true 246 | } 247 | return false 248 | } 249 | 250 | obaa.isFunction = function (obj) { 251 | return Object.prototype.toString.call(obj) == '[object Function]' 252 | } 253 | 254 | obaa._getRootName = function (prop, path) { 255 | if (path === '#') { 256 | return prop 257 | } 258 | return path.split('-')[1] 259 | } 260 | 261 | obaa.add = function (obj, prop) { 262 | var $observer = obj.$observer 263 | $observer.watch(obj, prop) 264 | } 265 | 266 | obaa.set = function (obj, prop, value, oba) { 267 | // if (exec) { 268 | // obj[prop] = value 269 | // } 270 | if (obj[prop] === undefined) { 271 | var $observer = obj.$observer || oba 272 | $observer.watch(obj, prop, obj.$observeProps.$observerPath) 273 | } 274 | //if (!exec) { 275 | obj[prop] = value 276 | //} 277 | } 278 | 279 | Array.prototype.size = function (length) { 280 | this.length = length 281 | } 282 | 283 | function nan(value) { 284 | return typeof value === "number" && isNaN(value) 285 | } 286 | 287 | -------------------------------------------------------------------------------- /utils/path.js: -------------------------------------------------------------------------------- 1 | const OBJECTTYPE = '[object Object]' 2 | const ARRAYTYPE = '[object Array]' 3 | 4 | export function getUsing(data, paths) { 5 | if(!paths) return {} 6 | const obj = {} 7 | paths.forEach((path, index) => { 8 | const isPath = typeof path === 'string' 9 | if (!isPath) { 10 | const key = Object.keys(path)[0] 11 | const value = path[key] 12 | if (typeof value !== 'string') { 13 | 14 | const tempPath = value[0] 15 | if (typeof tempPath === 'string') { 16 | const tempVal = getTargetByPath(data, tempPath) 17 | obj[key] = value[1] ? value[1](tempVal) : tempVal 18 | } else { 19 | const args = [] 20 | tempPath.forEach(path => { 21 | args.push(getTargetByPath(data, path)) 22 | }) 23 | obj[key] = value[1].apply(null, args) 24 | } 25 | 26 | } 27 | } 28 | }) 29 | return obj 30 | } 31 | 32 | export function getTargetByPath(origin, path) { 33 | const arr = path 34 | .replace(/]/g, '') 35 | .replace(/\[/g, '.') 36 | .split('.') 37 | let current = origin 38 | for (let i = 0, len = arr.length; i < len; i++) { 39 | current = current[arr[i]] 40 | } 41 | return current 42 | } 43 | 44 | export function getPath(obj) { 45 | if (Object.prototype.toString.call(obj) === '[object Array]') { 46 | const result = {} 47 | obj.forEach(item => { 48 | if (typeof item === 'string') { 49 | result[item] = true 50 | } else { 51 | const tempPath = item[Object.keys(item)[0]] 52 | if (typeof tempPath === 'string') { 53 | result[tempPath] = true 54 | } else if (typeof tempPath[0] === 'string') { 55 | result[tempPath[0]] = true 56 | } else { 57 | tempPath[0].forEach(path => (result[path] = true)) 58 | } 59 | } 60 | }) 61 | return result 62 | } 63 | return getUpdatePath(obj) 64 | } 65 | 66 | export function getUpdatePath(data) { 67 | const result = {} 68 | dataToPath(data, result) 69 | return result 70 | } 71 | 72 | function dataToPath(data, result) { 73 | Object.keys(data).forEach(key => { 74 | result[key] = true 75 | const type = Object.prototype.toString.call(data[key]) 76 | if (type === OBJECTTYPE) { 77 | _objToPath(data[key], key, result) 78 | } else if (type === ARRAYTYPE) { 79 | _arrayToPath(data[key], key, result) 80 | } 81 | }) 82 | } 83 | 84 | function _objToPath(data, path, result) { 85 | Object.keys(data).forEach(key => { 86 | result[path + '.' + key] = true 87 | delete result[path] 88 | const type = Object.prototype.toString.call(data[key]) 89 | if (type === OBJECTTYPE) { 90 | _objToPath(data[key], path + '.' + key, result) 91 | } else if (type === ARRAYTYPE) { 92 | _arrayToPath(data[key], path + '.' + key, result) 93 | } 94 | }) 95 | } 96 | 97 | function _arrayToPath(data, path, result) { 98 | data.forEach((item, index) => { 99 | result[path + '[' + index + ']'] = true 100 | delete result[path] 101 | const type = Object.prototype.toString.call(item) 102 | if (type === OBJECTTYPE) { 103 | _objToPath(item, path + '[' + index + ']', result) 104 | } else if (type === ARRAYTYPE) { 105 | _arrayToPath(item, path + '[' + index + ']', result) 106 | } 107 | }) 108 | } 109 | 110 | export function needUpdate(diffResult, updatePath) { 111 | for (let keyA in diffResult) { 112 | if (updatePath[keyA]) { 113 | return true 114 | } 115 | for (let keyB in updatePath) { 116 | if (includePath(keyA, keyB)) { 117 | return true 118 | } 119 | } 120 | } 121 | return false 122 | } 123 | 124 | function includePath(pathA, pathB) { 125 | if (pathA.indexOf(pathB) === 0) { 126 | const next = pathA.substr(pathB.length, 1) 127 | if (next === '[' || next === '.') { 128 | return true 129 | } 130 | } 131 | return false 132 | } 133 | 134 | export function fixPath(path) { 135 | let mpPath = '' 136 | const arr = path.replace('#-', '').split('-') 137 | arr.forEach((item, index) => { 138 | if (index) { 139 | if (isNaN(Number(item))) { 140 | mpPath += '.' + item 141 | } else { 142 | mpPath += '[' + item + ']' 143 | } 144 | } else { 145 | mpPath += item 146 | } 147 | }) 148 | return mpPath 149 | } 150 | -------------------------------------------------------------------------------- /utils/util.js: -------------------------------------------------------------------------------- 1 | const formatTime = date => { 2 | const year = date.getFullYear() 3 | const month = date.getMonth() + 1 4 | const day = date.getDate() 5 | const hour = date.getHours() 6 | const minute = date.getMinutes() 7 | const second = date.getSeconds() 8 | 9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 10 | } 11 | 12 | const formatNumber = n => { 13 | n = n.toString() 14 | return n[1] ? n : '0' + n 15 | } 16 | 17 | const baseURL = "http://47.115.85.237:3000/"; 18 | // const baseURL = "http://localhost:3000/"; 19 | const $ajax = (api, params = {}) => { 20 | const url = baseURL + api; 21 | return new Promise((resolve) => { 22 | wx.showLoading({ 23 | title: '加载中...', 24 | }); 25 | wx.request({ 26 | header: { 27 | 'content-type': 'application/json', 28 | Cookie: wx.getStorageSync("cookie") 29 | }, 30 | url, 31 | method: params.type ? params.type : "post", 32 | data: params.data ? params.data : {}, 33 | success: function(res) { 34 | resolve(res.data); 35 | }, 36 | fail: function(error) { 37 | console.log(error); 38 | }, 39 | complete: function(res) { 40 | // 隐藏loading图标 41 | wx.hideLoading(); 42 | 43 | // 把cookie存在本地 44 | if (res.header['Set-Cookie']) { 45 | const reg = /koa\S*;/g 46 | const tempCookie = res.header['Set-Cookie'].match(reg) 47 | const cookie = tempCookie[0] + ' ' + tempCookie[1]; 48 | wx.setStorageSync('cookie', cookie); 49 | } 50 | } 51 | }) 52 | }); 53 | } 54 | 55 | module.exports = { 56 | formatTime: formatTime, 57 | baseURL, 58 | $ajax 59 | } --------------------------------------------------------------------------------
15 | {{item.product_selling_price}}元 16 | {{item.product_price}}元 17 |
19 | {{productInfo.product_selling_price}}元 20 | {{productInfo.product_price}}元 21 |