├── .gitignore
├── README.md
├── cloudfunctions
├── addComment
│ ├── index.js
│ └── package.json
├── addOrder
│ ├── index.js
│ └── package.json
├── addTrolley
│ ├── index.js
│ └── package.json
├── getOrderList
│ ├── index.js
│ └── package.json
├── getTrolleyList
│ ├── index.js
│ └── package.json
├── productDetail
│ ├── index.js
│ └── package.json
└── updateTrolley
│ ├── index.js
│ └── package.json
├── data
├── products.json
├── products
│ ├── product1.jpg
│ ├── product10.jpg
│ ├── product11.jpg
│ ├── product12.jpg
│ ├── product13.jpg
│ ├── product14.jpg
│ ├── product15.jpg
│ ├── product2.jpg
│ ├── product3.jpg
│ ├── product4.jpg
│ ├── product5.jpg
│ ├── product6.jpg
│ ├── product7.jpg
│ ├── product8.jpg
│ └── product9.jpg
└── screenshot
│ ├── screenshot1.png
│ ├── screenshot2.png
│ ├── screenshot3.png
│ ├── screenshot4.png
│ ├── screenshot5.png
│ ├── screenshot6.png
│ ├── screenshot7.png
│ └── screenshot8.png
├── miniprogram
├── app.js
├── app.json
├── app.wxss
├── components
│ ├── login.js
│ ├── login.json
│ ├── login.wxml
│ ├── login.wxss
│ ├── product.js
│ ├── product.json
│ ├── product.wxml
│ └── product.wxss
├── images
│ ├── bg.png
│ ├── check-yellow.png
│ ├── check.png
│ ├── discount.png
│ ├── grey-arrow.png
│ ├── home-sel.png
│ ├── home.png
│ ├── image.png
│ ├── line-black.png
│ ├── line-red.png
│ ├── order-sel.png
│ ├── order.png
│ ├── trolley-sel.png
│ ├── trolley.png
│ ├── user-sel.png
│ └── user.png
├── pages
│ ├── add-comment
│ │ ├── add-comment.js
│ │ ├── add-comment.json
│ │ ├── add-comment.wxml
│ │ └── add-comment.wxss
│ ├── comment
│ │ ├── comment.js
│ │ ├── comment.json
│ │ ├── comment.wxml
│ │ └── comment.wxss
│ ├── detail
│ │ ├── detail.js
│ │ ├── detail.json
│ │ ├── detail.wxml
│ │ └── detail.wxss
│ ├── home
│ │ ├── home.js
│ │ ├── home.json
│ │ ├── home.wxml
│ │ └── home.wxss
│ ├── order
│ │ ├── order.js
│ │ ├── order.json
│ │ ├── order.wxml
│ │ └── order.wxss
│ ├── trolley
│ │ ├── trolley.js
│ │ ├── trolley.json
│ │ ├── trolley.wxml
│ │ └── trolley.wxss
│ └── user
│ │ ├── user.js
│ │ ├── user.json
│ │ ├── user.wxml
│ │ └── user.wxss
├── sitemap.json
└── utils
│ ├── db.js
│ └── util.js
└── project.config.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows
2 | [Dd]esktop.ini
3 | Thumbs.db
4 | $RECYCLE.BIN/
5 |
6 | # macOS
7 | .DS_Store
8 | .fseventsd
9 | .Spotlight-V100
10 | .TemporaryItems
11 | .Trashes
12 |
13 | # Node.js
14 | node_modules/
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 闲商城
2 |
3 | 优达学城商城类小程序项目。本项目使用的是云开发进行后端搭建,是一个比较综合的项目,需要具备一定的 **JavaScript、CSS** 知识。
4 |
5 | [tencent-cloud分支](https://github.com/fujianlian/mall/tree/tencent-cloud)是基于**腾讯云服务**进行后端开发的,相对比来说比较复杂,建议选择**云开发**模式开发
6 |
7 | ## 小程序截图
8 |
9 |  |  |  |  |
10 | | :--: | :--: | :--: | :--: |
11 | | 首页 | 订单 | 购物车 | 个人中心 |
12 |
13 |  |  |  |  |
14 | | :--: | :--: | :--: | :--: |
15 | | 商品详情 | 添加评论 | 用户评论 | 未登录 |
16 |
17 | # 云开发 quickstart
18 |
19 | 这是云开发的快速启动指引,其中演示了如何上手使用云开发的三大基础能力:
20 |
21 | - 数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 文档型数据库
22 | - 文件存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理
23 | - 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写业务逻辑代码
24 |
25 | ## 参考文档
26 |
27 | - [云开发文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html)
28 |
29 | # 运行准备
30 |
31 | 注册[小程序开发帐号](https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index),完成注册之后,登录[微信公众平台官网](https://mp.weixin.qq.com/) ,点击 **“设置 -> 开发设置”**,获取你的 **AppID 帐号**,后面初始化项目需要用到。
32 |
33 | ## 运行项目
34 |
35 | 1. 安装[微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html)
36 |
37 | 2. 下载源码,打开微信开发者,选择小程序导入源码,**AppID改为自己申请的**
38 |
39 | 3. 接下来申请云开发功能,进入云开发页面
40 |
41 | * 在存储里创建 **products** 文件夹,将data/products里的所有图片上传到products文件夹中
42 |
43 | * 在数据库里创建 **order/product/review/trolley** 四个集合,将data/products.json导入到product集合中,注意修改image的地址前缀
44 |
45 | * env修改,可参考[这篇文章](https://blog.csdn.net/Sprintf_HelloWorld/article/details/86746684)
46 |
47 | * 上传云函数,运行即可
48 |
49 | ## 贡献
50 |
51 | * 如果你在使用过程中遇到问题,欢迎给我提Issue
52 |
53 | * 如果你有好的想法,欢迎pull request
54 |
55 | * 觉得不错的话,顺手 **点个Star**,笔者需要您的支持
56 |
57 |
--------------------------------------------------------------------------------
/cloudfunctions/addComment/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init({
5 | traceUser: true,
6 | env: 'mall-7vt8m',
7 | })
8 |
9 | const db = cloud.database()
10 |
11 | exports.main = async (event, context) => {
12 | const wxContext = cloud.getWXContext()
13 | const user = wxContext.OPENID
14 |
15 | await db.collection('review').add({
16 | data: {
17 | user,
18 | username: event.username,
19 | avatar: event.avatar,
20 | content: event.content,
21 | productId: event.productId,
22 | createTime: +new Date(),
23 | images: (event.images || []).join(';'),
24 | },
25 | })
26 |
27 | return {}
28 | }
--------------------------------------------------------------------------------
/cloudfunctions/addComment/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "addComment",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/addOrder/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init({
5 | traceUser: true,
6 | env: 'mall-7vt8m',
7 | })
8 |
9 | const db = cloud.database()
10 |
11 | // 云函数入口函数
12 | exports.main = async (event, context) => {
13 | const wxContext = cloud.getWXContext()
14 | const user = wxContext.OPENID
15 |
16 | const productList = event.list || []
17 | const isCheckout = !!event.isCheckout
18 |
19 | await db.collection('order').add({
20 | data: {
21 | user,
22 | createTime: +new Date(),
23 | productList,
24 | },
25 | })
26 |
27 | if (isCheckout) {
28 | await db.collection('trolley').where({
29 | productId: db.command.in(productList.map(product => product.productId))
30 | }).remove()
31 | }
32 |
33 | return {}
34 | }
--------------------------------------------------------------------------------
/cloudfunctions/addOrder/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "addOrder",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/addTrolley/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init({
5 | traceUser: true,
6 | env: 'mall-7vt8m',
7 | })
8 |
9 | const db = cloud.database()
10 |
11 | // 云函数入口函数
12 | exports.main = async (event, context) => {
13 | const wxContext = cloud.getWXContext()
14 | const user = wxContext.OPENID
15 | const productId = event._id
16 |
17 | const cartRes = await db.collection('trolley').where({
18 | productId,
19 | user,
20 | }).get()
21 | const cartList = cartRes.data
22 |
23 | if (!cartList.length) {
24 | await db.collection('trolley').add({
25 | data: {
26 | productId,
27 | count: 1,
28 | user,
29 | image: event.image,
30 | name: event.name,
31 | price: event.price,
32 | },
33 | })
34 | } else {
35 | const count = cartList[0].count + 1
36 | await db.collection('trolley').doc(cartList[0]._id).update({
37 | data: {
38 | count,
39 | },
40 | })
41 | }
42 |
43 | return {}
44 | }
--------------------------------------------------------------------------------
/cloudfunctions/addTrolley/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "addTrolley",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/getOrderList/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init({
5 | traceUser: true,
6 | env: 'mall-7vt8m',
7 | })
8 |
9 | const db = cloud.database()
10 |
11 | // 云函数入口函数
12 | exports.main = async (event, context) => {
13 | const wxContext = cloud.getWXContext()
14 | const user = wxContext.OPENID
15 |
16 | // Order List
17 | const orderRes = await db.collection('order').where({
18 | user,
19 | }).get()
20 | const orderList = orderRes.data
21 |
22 | return orderList
23 | }
--------------------------------------------------------------------------------
/cloudfunctions/getOrderList/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getOrderList",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/getTrolleyList/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init({
5 | traceUser: true,
6 | env: 'mall-7vt8m',
7 | })
8 |
9 | const db = cloud.database()
10 |
11 | // 云函数入口函数
12 | exports.main = async (event, context) => {
13 | const wxContext = cloud.getWXContext()
14 | const user = wxContext.OPENID
15 |
16 | // trolley list
17 | const trolleyRes = await db.collection('trolley').where({
18 | user,
19 | }).get()
20 | const trolleyList = trolleyRes.data
21 |
22 | return trolleyList
23 | }
--------------------------------------------------------------------------------
/cloudfunctions/getTrolleyList/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "getTrolleyList",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/productDetail/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init({
5 | traceUser: true,
6 | env: 'mall-7vt8m',
7 | })
8 |
9 | const db = cloud.database()
10 |
11 | // 云函数入口函数
12 | exports.main = async (event, context) => {
13 | const id = event.id
14 |
15 | // product detail
16 | const productRes = await db.collection('product').doc(id).get()
17 | const product = productRes.data
18 |
19 | return product
20 | }
--------------------------------------------------------------------------------
/cloudfunctions/productDetail/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "productDetail",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/updateTrolley/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init({
5 | traceUser: true,
6 | env: 'mall-7vt8m',
7 | })
8 |
9 | const db = cloud.database()
10 |
11 | // 云函数入口函数
12 | exports.main = async (event, context) => {
13 | const wxContext = cloud.getWXContext()
14 | const user = wxContext.OPENID
15 | const productList = event.list
16 |
17 | // delete all the data from cart
18 | await db.collection('trolley').where({
19 | user,
20 | }).remove()
21 |
22 | // fill cart with updated data
23 | for (const product of productList) {
24 | await db.collection('trolley').add({
25 | data: {
26 | productId: product.productId,
27 | count: product.count,
28 | user,
29 | image: product.image,
30 | name: product.name,
31 | price: product.price,
32 | },
33 | })
34 | }
35 |
36 | return {}
37 | }
--------------------------------------------------------------------------------
/cloudfunctions/updateTrolley/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "updateTrolley",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/data/products.json:
--------------------------------------------------------------------------------
1 | {
2 | "image": "xxx/products/product1.jpg",
3 | "name": "Toy Holster",
4 | "price": 132.00,
5 | "source": "CHINA"
6 | }
7 | {
8 | "image": "xxx/products/product2.jpg",
9 | "name": "Golden Acoustic Guitar",
10 | "price": 480.50,
11 | "source": "CHINA"
12 | }
13 | {
14 | "image": "xxx/products/product3.jpg",
15 | "name": "Red Iron Stapler",
16 | "price": 28.00,
17 | "source": "CHINA"
18 | }
19 | {
20 | "image": "xxx/products/product4.jpg",
21 | "name": "Fresh Organic Vegetables",
22 | "price": 30.90,
23 | "source": "CHINA"
24 | }
25 | {
26 | "image": "xxx/products/product5.jpg",
27 | "name": "Imitation Iron Plate Clock",
28 | "price": 45.00,
29 | "source": "SWEDEN"
30 | }
31 | {
32 | "image": "xxx/products/product6.jpg",
33 | "name": "Fresh Grapes",
34 | "price": 24.80,
35 | "source": "CHINA"
36 | }
37 | {
38 | "image": "xxx/products/product7.jpg",
39 | "name": "Fruit and Vegetable Spree",
40 | "price": 158.00,
41 | "source": "NEW ZEALAND"
42 | }
43 | {
44 | "image": "xxx/products/product8.jpg",
45 | "name": "Red Retro Car Model",
46 | "price": 35.00,
47 | "source": "GERMANY"
48 | }
49 | {
50 | "image": "xxx/products/product9.jpg",
51 | "name": "Winding Electric Motorcycle",
52 | "price": 249.00,
53 | "source": "CHINA"
54 | }
55 | {
56 | "image": "xxx/products/product10.jpg",
57 | "name": "Red Apples",
58 | "price": 29.80,
59 | "source": "CHINA"
60 | }
61 | {
62 | "image": "xxx/products/product11.jpg",
63 | "name": "Durable Men's Shoes",
64 | "price": 335.00,
65 | "source": "CHINA"
66 | }
67 | {
68 | "image": "xxx/products/product12.jpg",
69 | "name": "Religious Place Tourism Memorial",
70 | "price": 1668.00,
71 | "source": "INDIA"
72 | }
73 | {
74 | "image": "xxx/products/product13.jpg",
75 | "name": "High Quality Pump",
76 | "price": 2000.80,
77 | "source": "CHINA"
78 | }
79 | {
80 | "image": "xxx/products/product14.jpg",
81 | "name": "King Kong Rings",
82 | "price": 34.00,
83 | "source": "CHINA"
84 | }
85 | {
86 | "image": "xxx/products/product15.jpg",
87 | "name": "Halloween Pumpkin",
88 | "price": 29.90,
89 | "source": "USA"
90 | }
--------------------------------------------------------------------------------
/data/products/product1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product1.jpg
--------------------------------------------------------------------------------
/data/products/product10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product10.jpg
--------------------------------------------------------------------------------
/data/products/product11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product11.jpg
--------------------------------------------------------------------------------
/data/products/product12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product12.jpg
--------------------------------------------------------------------------------
/data/products/product13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product13.jpg
--------------------------------------------------------------------------------
/data/products/product14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product14.jpg
--------------------------------------------------------------------------------
/data/products/product15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product15.jpg
--------------------------------------------------------------------------------
/data/products/product2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product2.jpg
--------------------------------------------------------------------------------
/data/products/product3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product3.jpg
--------------------------------------------------------------------------------
/data/products/product4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product4.jpg
--------------------------------------------------------------------------------
/data/products/product5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product5.jpg
--------------------------------------------------------------------------------
/data/products/product6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product6.jpg
--------------------------------------------------------------------------------
/data/products/product7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product7.jpg
--------------------------------------------------------------------------------
/data/products/product8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product8.jpg
--------------------------------------------------------------------------------
/data/products/product9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/products/product9.jpg
--------------------------------------------------------------------------------
/data/screenshot/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/screenshot/screenshot1.png
--------------------------------------------------------------------------------
/data/screenshot/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/screenshot/screenshot2.png
--------------------------------------------------------------------------------
/data/screenshot/screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/screenshot/screenshot3.png
--------------------------------------------------------------------------------
/data/screenshot/screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/screenshot/screenshot4.png
--------------------------------------------------------------------------------
/data/screenshot/screenshot5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/screenshot/screenshot5.png
--------------------------------------------------------------------------------
/data/screenshot/screenshot6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/screenshot/screenshot6.png
--------------------------------------------------------------------------------
/data/screenshot/screenshot7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/screenshot/screenshot7.png
--------------------------------------------------------------------------------
/data/screenshot/screenshot8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/data/screenshot/screenshot8.png
--------------------------------------------------------------------------------
/miniprogram/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 |
3 | App({
4 |
5 | onLaunch: function () {
6 |
7 | if (!wx.cloud) {
8 | console.error('请使用 2.2.3 或以上的基础库以使用云能力')
9 | } else {
10 | wx.cloud.init({
11 | traceUser: true,
12 | env: 'mall-7vt8m',
13 | })
14 | }
15 |
16 | this.globalData = {}
17 | },
18 |
19 | checkSession({
20 | success,
21 | error
22 | }) {
23 | wx.checkSession({
24 | success: () => {
25 | this.getUserInfo({
26 | success,
27 | error
28 | })
29 | },
30 | fail: () => {
31 | error && error()
32 | }
33 | })
34 | },
35 | })
36 |
--------------------------------------------------------------------------------
/miniprogram/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/home/home",
4 | "pages/order/order",
5 | "pages/trolley/trolley",
6 | "pages/user/user",
7 | "pages/detail/detail",
8 | "pages/add-comment/add-comment",
9 | "pages/comment/comment"
10 | ],
11 | "tabBar": {
12 | "color": "#5d5f64",
13 | "selectedColor": "#5d5f64",
14 | "backgroundColor": "#fff",
15 | "position": "bottom",
16 | "borderStyle": "white",
17 | "list": [
18 | {
19 | "pagePath": "pages/home/home",
20 | "iconPath": "images/home.png",
21 | "selectedIconPath": "images/home-sel.png",
22 | "text": "首页"
23 | },
24 | {
25 | "pagePath": "pages/order/order",
26 | "iconPath": "images/order.png",
27 | "selectedIconPath": "images/order-sel.png",
28 | "text": "订单"
29 | },
30 | {
31 | "pagePath": "pages/trolley/trolley",
32 | "iconPath": "images/trolley.png",
33 | "selectedIconPath": "images/trolley-sel.png",
34 | "text": "购物车"
35 | },
36 | {
37 | "pagePath": "pages/user/user",
38 | "iconPath": "images/user.png",
39 | "selectedIconPath": "images/user-sel.png",
40 | "text": "个人中心"
41 | }
42 | ]
43 | },
44 | "window": {
45 | "backgroundColor": "#F6F6F6",
46 | "backgroundTextStyle": "light",
47 | "navigationBarBackgroundColor": "#fff",
48 | "navigationBarTitleText": "商城小程序",
49 | "navigationBarTextStyle": "black"
50 | },
51 | "sitemapLocation": "sitemap.json"
52 | }
--------------------------------------------------------------------------------
/miniprogram/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 |
3 | page {
4 | background: #f9f9f9;
5 | }
6 |
7 | .bg {
8 | position: absolute;
9 | left: 0;
10 | top: 0;
11 | width: 100%;
12 | height: 144rpx;
13 | z-index: -1
14 | }
15 |
16 | .empty-list {
17 | display: flex;
18 | flex-direction: column;
19 | margin: 40rpx 30rpx;
20 | background: white;
21 | border-radius: 15rpx;
22 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.05);
23 | height: 420rpx;
24 | justify-content: center;
25 | align-items: center;
26 | }
27 |
28 | .empty-image {
29 | margin-bottom: 29rpx;
30 | width: 90rpx;
31 | height: 90rpx;
32 | opacity: 0.4;
33 | }
34 |
35 | .empty-text {
36 | font-size: 28rpx;
37 | line-height: 42rpx;
38 | color: rgba(139, 139, 139, 0.8);
39 | }
40 |
--------------------------------------------------------------------------------
/miniprogram/components/login.js:
--------------------------------------------------------------------------------
1 | // components/login.js
2 | Component({
3 | /**
4 | * 组件的属性列表
5 | */
6 | properties: {
7 |
8 | },
9 |
10 | /**
11 | * 组件的初始数据
12 | */
13 | data: {
14 |
15 | },
16 |
17 | /**
18 | * 组件的方法列表
19 | */
20 | methods: {
21 | onTapLogin(event) {
22 | const loginDetail = {
23 | userInfo: event.detail.userInfo
24 | } // detail object, Provided to the event listener function
25 |
26 | this.triggerEvent('onLogin', loginDetail)
27 | },
28 | }
29 | })
--------------------------------------------------------------------------------
/miniprogram/components/login.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/miniprogram/components/login.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 未登录
6 | 点击微信登录后可方便购物
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/miniprogram/components/login.wxss:
--------------------------------------------------------------------------------
1 | /* components/login.wxss */
2 | .login-card {
3 | display: flex;
4 | align-items: center;
5 | margin: 50rpx 27rpx 0;
6 | height: 200rpx;
7 | background: #FFFFFF;
8 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.02);
9 | border-radius: 13rpx;
10 | }
11 |
12 | .login-head {
13 | flex-shrink: 0;
14 | margin-left: 53rpx;
15 | height: 100rpx;
16 | width: 100rpx;
17 | background: #F5E069;
18 | border-radius: 50%;
19 | }
20 |
21 | .login-info {
22 | flex: 1;
23 | margin-left: 31rpx;
24 | }
25 |
26 | .login-text {
27 | line-height: 48rpx;
28 | font-size: 34rpx;
29 | color: rgba(29, 29, 38, 0.8);
30 | font-weight: bold;
31 | }
32 |
33 | .login-tips {
34 | margin-top: 6rpx;
35 | line-height: 33rpx;
36 | font-size: 24rpx;
37 | color: #8B8B8B;
38 | }
39 |
40 | .login-btn {
41 | margin: 34rpx auto 0;
42 | width: 250rpx;
43 | height: 80rpx;
44 | line-height: 80rpx;
45 | background: #F5E069;
46 | outline: none;
47 | border: none;
48 | border-radius: 10rpx;
49 | font-size: 30rpx;
50 | text-align: center;
51 | color: #34373D;
52 | font-weight: bold;
53 | }
54 |
55 | .login-btn::after {
56 | border: none;
57 | }
--------------------------------------------------------------------------------
/miniprogram/components/product.js:
--------------------------------------------------------------------------------
1 | // components/product.js
2 | Component({
3 | /**
4 | * 组件的属性列表
5 | */
6 | properties: {
7 | productImage: String,
8 | productName: String,
9 | productPrice: String
10 | },
11 |
12 | /**
13 | * 组件的初始数据
14 | */
15 | data: {
16 |
17 | },
18 |
19 | /**
20 | * 组件的方法列表
21 | */
22 | methods: {
23 |
24 | }
25 | })
26 |
--------------------------------------------------------------------------------
/miniprogram/components/product.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/miniprogram/components/product.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{productName}}
6 | ¥ {{productPrice}}
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/miniprogram/components/product.wxss:
--------------------------------------------------------------------------------
1 | /* components/product.wxss */
2 | .product-card {
3 | display: flex;
4 | align-items: center;
5 | padding-left: 26rpx;
6 | height: 200rpx;
7 | background: #FFFFFF;
8 | }
9 |
10 | .product-image {
11 | flex-shrink: 0;
12 | width: 160rpx;
13 | height: 160rpx;
14 | }
15 |
16 | .product-info {
17 | flex: 1;
18 | padding: 27rpx;
19 | height: 100%;
20 | box-sizing: border-box;
21 | font-size: 28rpx;
22 | line-height: 40rpx;
23 | }
24 |
25 | .product-name {
26 | color: rgba(29, 29, 38, 0.8);
27 | }
28 |
29 | .product-price {
30 | margin-top: 12rpx;
31 | font-weight: bold;
32 | }
--------------------------------------------------------------------------------
/miniprogram/images/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/bg.png
--------------------------------------------------------------------------------
/miniprogram/images/check-yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/check-yellow.png
--------------------------------------------------------------------------------
/miniprogram/images/check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/check.png
--------------------------------------------------------------------------------
/miniprogram/images/discount.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/discount.png
--------------------------------------------------------------------------------
/miniprogram/images/grey-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/grey-arrow.png
--------------------------------------------------------------------------------
/miniprogram/images/home-sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/home-sel.png
--------------------------------------------------------------------------------
/miniprogram/images/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/home.png
--------------------------------------------------------------------------------
/miniprogram/images/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/image.png
--------------------------------------------------------------------------------
/miniprogram/images/line-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/line-black.png
--------------------------------------------------------------------------------
/miniprogram/images/line-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/line-red.png
--------------------------------------------------------------------------------
/miniprogram/images/order-sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/order-sel.png
--------------------------------------------------------------------------------
/miniprogram/images/order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/order.png
--------------------------------------------------------------------------------
/miniprogram/images/trolley-sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/trolley-sel.png
--------------------------------------------------------------------------------
/miniprogram/images/trolley.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/trolley.png
--------------------------------------------------------------------------------
/miniprogram/images/user-sel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/user-sel.png
--------------------------------------------------------------------------------
/miniprogram/images/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fujianlian/mall/f212147e3b9753d6315ba7d485974b40970f852e/miniprogram/images/user.png
--------------------------------------------------------------------------------
/miniprogram/pages/add-comment/add-comment.js:
--------------------------------------------------------------------------------
1 | // pages/add-comment/add-comment.js
2 |
3 | const db = require('../../utils/db.js')
4 | const util = require('../../utils/util')
5 |
6 | Page({
7 |
8 | /**
9 | * 页面的初始数据
10 | */
11 | data: {
12 | userInfo: null,
13 | product: null,
14 | commentValue: '',
15 | commentImages: [],
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面加载
20 | */
21 | onLoad: function (options) {
22 | util.getUserInfo().then(userInfo => {
23 | this.setData({
24 | userInfo
25 | })
26 | this.setProduct(options)
27 | }).catch(err => {
28 | console.log('尚未通过身份验证')
29 | })
30 | },
31 |
32 | setProduct(options) {
33 | let product = this.data.product
34 | product = JSON.parse(options.data)
35 | this.setData({
36 | product
37 | })
38 | },
39 |
40 | onInput(event) {
41 | this.setData({
42 | commentValue: event.detail.value.trim()
43 | })
44 | },
45 |
46 | addComment(event) {
47 | let content = this.data.commentValue;
48 | if (!content) return
49 |
50 | wx.showLoading({
51 | title: '正在发表评论'
52 | })
53 |
54 | this.uploadImage(images => {
55 | db.addComment({
56 | username: this.data.userInfo.nickName,
57 | avatar: this.data.userInfo.avatarUrl,
58 | content,
59 | productId: this.data.product.productId,
60 | images,
61 | }).then(result => {
62 | wx.hideLoading()
63 |
64 | const data = result.result
65 |
66 | if (data) {
67 | wx.showToast({
68 | title: '发表评论成功'
69 | })
70 |
71 | setTimeout(() => {
72 | wx.navigateBack()
73 | }, 1500)
74 | } else {
75 | wx.showToast({
76 | icon: 'none',
77 | title: '发表评论失败'
78 | })
79 | }
80 | }).catch(err => {
81 | console.error(err)
82 | wx.hideLoading()
83 |
84 | wx.showToast({
85 | icon: 'none',
86 | title: '发表评论失败'
87 | })
88 | })
89 | })
90 | },
91 |
92 | chooseImage() {
93 | let currentImages = this.data.commentImages
94 | wx.chooseImage({
95 | count: 3,
96 | sizeType: ['compressed'],
97 | sourceType: ['album', 'camera'],
98 | success: res => {
99 | currentImages = currentImages.concat(res.tempFilePaths)
100 | let end = currentImages.length
101 | let begin = Math.max(end - 3, 0)
102 | currentImages = currentImages.slice(begin, end)
103 | this.setData({
104 | commentImages: currentImages
105 | });
106 | },
107 | })
108 | },
109 |
110 | previewImg(event) {
111 | let target = event.currentTarget
112 | let src = target.dataset.src
113 |
114 | wx.previewImage({
115 | current: src,
116 | urls: this.data.commentImages
117 | })
118 | },
119 |
120 | uploadImage(callback) {
121 | const commentImages = this.data.commentImages
122 | const images = []
123 |
124 | if (commentImages.length) {
125 | let imageCount = commentImages.length
126 | for (let i = 0; i < imageCount; i++) {
127 | db.uploadImage(commentImages[i]).then(result => {
128 | images.push(result.fileID)
129 | if (i === imageCount - 1) {
130 | callback && callback(images)
131 | }
132 | }).catch(err => {
133 | console.log('err', err)
134 | })
135 | }
136 | } else {
137 | callback && callback(images)
138 | }
139 | }
140 | })
--------------------------------------------------------------------------------
/miniprogram/pages/add-comment/add-comment.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "添加评论",
3 | "usingComponents": {
4 | "product": "/components/product"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/add-comment/add-comment.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
--------------------------------------------------------------------------------
/miniprogram/pages/add-comment/add-comment.wxss:
--------------------------------------------------------------------------------
1 | /* pages/add-comment/add-comment.wxss */
2 |
3 | .comment-cnt {
4 | margin: 29rpx 27rpx 0;
5 | padding-bottom: 26rpx;
6 | background: #fff;
7 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.02);
8 | border-radius: 10rpx;
9 | }
10 |
11 | .comment-ipt {
12 | width: 100%;
13 | height: 207rpx;
14 | padding: 29rpx 34rpx;
15 | box-sizing: border-box;
16 | font-size: 28rpx;
17 | line-height: 40rpx;
18 | }
19 |
20 | .comment-placeholder {
21 | color: rgba(29, 29, 38, 0.4);
22 | }
23 |
24 | .preview-cnt {
25 | display: flex;
26 | margin-top: 29rpx;
27 | margin-left: 29rpx;
28 | }
29 |
30 | .preview-image {
31 | margin-right: 10rpx;
32 | width: 180rpx;
33 | height: 180rpx;
34 | border-radius: 5rpx;
35 | }
36 |
37 | .opr-upload {
38 | display: block;
39 | margin-top: 29rpx;
40 | margin-left: 29rpx;
41 | width: 43rpx;
42 | height: 43rpx;
43 | }
44 |
45 | .comment-btn {
46 | margin: 34rpx auto;
47 | width: 250rpx;
48 | height: 80rpx;
49 | line-height: 80rpx;
50 | text-align: center;
51 | background: #f5e069;
52 | border-radius: 10rpx;
53 | font-size: 30rpx;
54 | color: #34373d;
55 | }
56 |
57 | .comment-btn.dis {
58 | color: rgba(52, 55, 61, 0.5);
59 | }
60 |
--------------------------------------------------------------------------------
/miniprogram/pages/comment/comment.js:
--------------------------------------------------------------------------------
1 | // pages/comment/comment.js
2 |
3 | const db = require('../../utils/db')
4 | const util = require('../../utils/util')
5 |
6 | Page({
7 |
8 | /**
9 | * 页面的初始数据
10 | */
11 | data: {
12 | commentList: [], // 评论列表
13 | product: null
14 | },
15 |
16 | /**
17 | * 生命周期函数--监听页面加载
18 | */
19 | onLoad: function (options) {
20 | let product = this.data.product
21 | product = JSON.parse(options.data)
22 | this.setData({
23 | product
24 | })
25 | this.getCommentList(product._id)
26 | },
27 |
28 | getCommentList(productId) {
29 | db.getComments(productId).then(result => {
30 | const data = result.data
31 | console.log(result)
32 | if (data.length) {
33 | this.setData({
34 | commentList: data.map(review => {
35 | review.createTime = util.formatTime(review.createTime, 'yyyy/MM/dd')
36 | review.images = review.images ? review.images.split(';') : []
37 | return review
38 | })
39 | })
40 | }
41 | }).catch(err => {
42 | console.error(err)
43 | })
44 | },
45 |
46 | previewImg(event) {
47 | let target = event.currentTarget
48 | let current = target.dataset.current
49 | let urls = target.dataset.urls
50 | wx.previewImage({
51 | current: current,
52 | urls: urls
53 | })
54 | }
55 | })
--------------------------------------------------------------------------------
/miniprogram/pages/comment/comment.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "用户评论",
3 | "usingComponents": {
4 | "product": "/components/product"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/comment/comment.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/miniprogram/pages/comment/comment.wxss:
--------------------------------------------------------------------------------
1 | /* pages/comment/comment.wxss */
2 |
3 | .comment-list {
4 | margin-top: 16rpx;
5 | background: #fff;
6 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.02);
7 | }
8 |
9 | .comment-title {
10 | padding: 25rpx 26rpx 14rpx;
11 | font-size: 30rpx;
12 | line-height: 42rpx;
13 | color: rgba(29, 29, 38, 0.8);
14 | font-weight: bold;
15 | }
16 |
17 | .comment-card {
18 | display: flex;
19 | padding: 30rpx 23rpx 0 26rpx;
20 | }
21 |
22 | .comment-card:last-child .comment-cnt {
23 | border-bottom: none;
24 | }
25 |
26 | .comment-avatar {
27 | flex-shrink: 0;
28 | width: 60rpx;
29 | height: 60rpx;
30 | border-radius: 50%;
31 | }
32 |
33 | .comment-cnt {
34 | flex: 1;
35 | margin-left: 24rpx;
36 | padding-bottom: 30rpx;
37 | border-bottom: 1px solid rgba(151, 151, 151, 0.2);
38 | }
39 |
40 | .comment-top {
41 | display: flex;
42 | font-size: 25rpx;
43 | line-height: 36rpx;
44 | color: rgba(29, 29, 38, 0.5);
45 | }
46 |
47 | .comment-username {
48 | flex: 1;
49 | }
50 |
51 | .comment-content {
52 | font-size: 28rpx;
53 | line-height: 40rpx;
54 | color: #1d1d26;
55 | }
56 |
57 | .preview-list {
58 | display: flex;
59 | margin-top: 16rpx;
60 | }
61 |
62 | .preview-item {
63 | margin-right: 10rpx;
64 | width: 180rpx;
65 | height: 180rpx;
66 | border-radius: 10rpx;
67 | }
68 |
69 | .preview-cnt {
70 | display: flex;
71 | margin-top: 20rpx;
72 | }
73 |
74 | .preview-image {
75 | margin-right: 10rpx;
76 | width: 180rpx;
77 | height: 180rpx;
78 | border-radius: 5rpx;
79 | }
80 |
--------------------------------------------------------------------------------
/miniprogram/pages/detail/detail.js:
--------------------------------------------------------------------------------
1 | // pages/detail/detail.js
2 |
3 | const db = require('../../utils/db.js')
4 | const util = require('../../utils/util.js')
5 |
6 | Page({
7 |
8 | /**
9 | * 页面的初始数据
10 | */
11 | data: {
12 | product: {},
13 | },
14 |
15 | /**
16 | * 生命周期函数--监听页面加载
17 | */
18 | onLoad: function (options) {
19 | let id = options.id
20 | this.getProduct(id)
21 | },
22 |
23 | getProduct(id) {
24 | let self = this
25 | wx.showLoading({
26 | title: '正在加载中...',
27 | })
28 |
29 | db.getProductDetail(id).then(result => {
30 | wx.hideLoading()
31 | const data = result.result
32 | // get 2 digits price
33 | data.price = util.formatPrice(data.price)
34 | self.setData({
35 | product: data
36 | })
37 | }).catch(err => {
38 | console.error(err)
39 | wx.hideLoading()
40 | wx.showToast({
41 | title: '加载数据失败',
42 | })
43 | })
44 | },
45 |
46 | buy() {
47 | wx.showLoading({
48 | title: '商品购买中...',
49 | })
50 |
51 | const productToBuy = Object.assign({
52 | count: 1
53 | }, this.data.product)
54 | productToBuy.productId = productToBuy._id
55 | console.log(productToBuy)
56 | db.addOrder({
57 | list: [productToBuy]
58 | }).then(result => {
59 | wx.hideLoading()
60 |
61 | const data = result.result
62 |
63 | console.log(data)
64 | if (data) {
65 | wx.showToast({
66 | title: '商品购买成功'
67 | })
68 | } else {
69 | wx.showToast({
70 | icon: 'none',
71 | title: '商品购买失败',
72 | })
73 | }
74 | }).catch(err => {
75 | console.error(err)
76 | wx.hideLoading()
77 | wx.showToast({
78 | icon: 'none',
79 | title: '商品购买失败',
80 | })
81 | })
82 | },
83 |
84 | addToTrolley() {
85 |
86 | wx.showLoading({
87 | title: '正在添加到购物车...',
88 | })
89 |
90 | db.addTrolley(this.data.product).then(result => {
91 | wx.hideLoading()
92 |
93 | const data = result.result
94 |
95 | if (data) {
96 | wx.showToast({
97 | title: '已添加到购物车'
98 | })
99 | } else {
100 | wx.showToast({
101 | icon: 'none',
102 | title: '添加到购物车失败',
103 | })
104 | }
105 | }).catch(err => {
106 | console.error(err)
107 | wx.hideLoading()
108 |
109 | wx.showToast({
110 | icon: 'none',
111 | title: '加入购物车'
112 | })
113 | })
114 | },
115 |
116 | onTapCommentEntry() {
117 | let product = this.data.product
118 | if (product.reviewCount) {
119 | wx.navigateTo({
120 | url: `/pages/comment/comment?data=${JSON.stringify(this.data.product)}`
121 | })
122 | }
123 | }
124 | })
--------------------------------------------------------------------------------
/miniprogram/pages/detail/detail.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "商品详情"
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/detail/detail.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{product.name}}
5 | {{product.source}}
6 |
7 | {{product.price}}
8 | ¥
9 |
10 |
11 |
12 |
13 |
14 | 7天免费退换
15 |
16 |
17 |
18 | 24小时内发货并赠送运费险
19 |
20 |
21 |
22 |
23 | 已买评价
24 | {{product.reviewCount}} 条
25 |
26 |
27 | {{product.firstComment.content}}
28 |
29 |
30 |
31 | 加入购物车
32 | 立即购买
33 |
34 |
--------------------------------------------------------------------------------
/miniprogram/pages/detail/detail.wxss:
--------------------------------------------------------------------------------
1 | /* pages/detail/detail.wxss */
2 | .top {
3 | background: white;
4 | padding: 30rpx 30rpx 20rpx;
5 | }
6 |
7 | .top-image {
8 | height: 300rpx;
9 | width: 300rpx;
10 | margin-left: 195rpx;
11 | }
12 |
13 | .top-name {
14 | font-size: 36rpx;
15 | line-height: 50rpx;
16 | margin-top: 20rpx;
17 | }
18 |
19 | .top-source {
20 | font-size: 26rpx;
21 | line-clamp: 35rpx;
22 | opacity: 0.5;
23 | margin-top: 5rpx;
24 | }
25 |
26 | .top-price-item {
27 | align-items: center;
28 | margin-top: 15rpx;
29 | display: flex;
30 | flex-flow: row-reverse;
31 | }
32 |
33 | .top-money {
34 | width: 36rpx;
35 | height: 36rpx;
36 | line-height: 36rpx;
37 | text-align: center;
38 | border-radius: 50%;
39 | color: #34373d;
40 | font-weight: 900;
41 | background: #f7e687;
42 | font-size: 24rpx;
43 | }
44 |
45 | .top-price {
46 | margin-left: 5rpx;
47 | font-size: 30rpx;
48 | line-height: 36rpx;
49 | }
50 |
51 | .service {
52 | padding: 25rpx 20rpx 0;
53 | margin: 30rpx;
54 | background: white;
55 | border-radius: 15rpx;
56 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.05);
57 | }
58 |
59 | .service-promise {
60 | display: flex;
61 | margin-top: 15rpx;
62 | align-items: center;
63 | }
64 |
65 | .service-check {
66 | margin-right: 10rpx;
67 | width: 22rpx;
68 | height: 16rpx;
69 | }
70 |
71 | .service-promise-text {
72 | align-items: 15rpx;
73 | font-size: 26rpx;
74 | opacity: 0.7;
75 | }
76 |
77 | .line {
78 | background: #e6e6e6;
79 | height: 1rpx;
80 | margin-top: 36rpx;
81 | }
82 |
83 | .evaluation-wrapper {
84 | display: flex;
85 | flex-flow: column;
86 | padding-bottom: 10rpx;
87 | }
88 |
89 | .evaluation {
90 | display: flex;
91 | align-items: center;
92 | padding: 30rpx 0 20rpx;
93 | }
94 |
95 | .evaluation-title {
96 | flex: 1;
97 | font-size: 28rpx;
98 | line-height: 28rpx;
99 | }
100 |
101 | .evaluation-right {
102 | width: 11rpx;
103 | height: 18rpx;
104 | }
105 |
106 | .evaluation-num {
107 | font-size: 20rpx;
108 | line-height: 25rpx;
109 | margin-right: 9rpx;
110 | opacity: 0.4;
111 | }
112 |
113 | .evaluation-text {
114 | font-size: 24rpx;
115 | line-height: 34rpx;
116 | margin-bottom: 15rpx;
117 | opacity: 0.9;
118 | }
119 |
120 | .opr {
121 | position: fixed;
122 | bottom: 0;
123 | left: 0;
124 | right: 0;
125 | display: flex;
126 | align-items: center;
127 | }
128 |
129 | .opr-trolley, .opr-buy {
130 | flex: 1;
131 | height: 100rpx;
132 | line-height: 100rpx;
133 | text-align: center;
134 | font-size: 30rpx;
135 | color: #34373d;
136 | font-weight: bold;
137 | }
138 |
139 | .opr-trolley {
140 | background: rgba(245, 224, 105, 0.6);
141 | }
142 |
143 | .opr-buy {
144 | background: #f5e069;
145 | }
146 |
--------------------------------------------------------------------------------
/miniprogram/pages/home/home.js:
--------------------------------------------------------------------------------
1 | // pages/home/home.js
2 |
3 | const db = require('../../utils/db.js')
4 | const util = require('../../utils/util.js')
5 |
6 | Page({
7 |
8 | /**
9 | * 页面的初始数据
10 | */
11 | data: {
12 | // 商品列表
13 | productList: []
14 | },
15 |
16 | /**
17 | * 生命周期函数--监听页面加载
18 | */
19 | onLoad: function(options) {
20 | this.getList()
21 | },
22 |
23 | /**
24 | * 获取商品列表
25 | */
26 | getList() {
27 | let self = this
28 | wx.showLoading({
29 | title: '正在加载中...',
30 | })
31 |
32 | db.getProductList().then(result => {
33 | wx.hideLoading()
34 |
35 | const productList = result.data
36 | // get 2 digits price
37 | productList.forEach(product => product.price = util.formatPrice(product.price))
38 | if (productList.length) {
39 | this.setData({
40 | productList
41 | })
42 | }
43 | }).catch(err => {
44 | console.error(err)
45 | wx.hideLoading()
46 | wx.showToast({
47 | title: '加载数据失败',
48 | })
49 |
50 | })
51 | },
52 |
53 | addToTrolley(event) {
54 | let index = event.currentTarget.dataset.index
55 | let d = this.data.productList[index]
56 |
57 | wx.showLoading({
58 | title: '正在添加到购物车...',
59 | })
60 |
61 | db.addTrolley(d).then(result => {
62 | wx.hideLoading()
63 |
64 | const data = result.result
65 |
66 | if (data) {
67 | wx.showToast({
68 | title: '已添加到购物车'
69 | })
70 | } else {
71 | wx.showToast({
72 | icon: 'none',
73 | title: '添加到购物车失败',
74 | })
75 | }
76 | }).catch(err => {
77 | console.error(err)
78 | wx.hideLoading()
79 |
80 | wx.showToast({
81 | icon: 'none',
82 | title: '加入购物车'
83 | })
84 | })
85 | },
86 | })
--------------------------------------------------------------------------------
/miniprogram/pages/home/home.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "首页"
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/home/home.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{productList[0].name}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | 春季推荐
15 |
16 |
17 |
18 |
19 |
20 | {{pitem.name}}
21 |
22 | ¥
23 | {{pitem.price}}
24 | +
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/miniprogram/pages/home/home.wxss:
--------------------------------------------------------------------------------
1 | /* pages/home/home.wxss */
2 | .hot-card {
3 | position: relative;
4 | margin: 32rpx 52rpx;
5 | background: white;
6 | border-radius: 15rpx;
7 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.05);
8 | height: 320rpx;
9 | }
10 |
11 | .hot-name {
12 | position: absolute;
13 | top: 36rpx;
14 | left: 36rpx;
15 | display: flex;
16 | align-items: center;
17 | }
18 |
19 | .hot-name-line {
20 | width: 24rpx;
21 | height: 39rpx;
22 | }
23 |
24 | .hot-name-text {
25 | margin: 0 20rpx;
26 | font-size: 28rpx;
27 | color: #333;
28 | font-weight: bold;
29 | }
30 |
31 | .hot-image-discount {
32 | position: absolute;
33 | width: 259rpx;
34 | height: 188rpx;
35 | bottom: 0;
36 | left: 42rpx;
37 | }
38 |
39 | .hot-image {
40 | position: absolute;
41 | width: 240rpx;
42 | height: 240rpx;
43 | right: 36rpx;
44 | top: 40rpx;
45 | }
46 |
47 | .separator {
48 | display: flex;
49 | align-items: center;
50 | justify-content: center;
51 | margin: 70rpx 0 30rpx;
52 | }
53 |
54 | .separator-line {
55 | width: 21rpx;
56 | height: 34rpx;
57 | }
58 |
59 | .separator-text {
60 | margin: 0 20rpx;
61 | font-size: 28rpx;
62 | font-weight: bold;
63 | }
64 |
65 | .list {
66 | display: flex;
67 | margin: 0 27rpx 0 52rpx;
68 | justify-content: space-around;
69 | }
70 |
71 | .list-item {
72 | background: white;
73 | border-radius: 15rpx;
74 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.05);
75 | width: 100%;
76 | margin-bottom: 25rpx;
77 | margin-right: 25rpx;
78 | }
79 |
80 | .list-item-image {
81 | height: 260rpx;
82 | width: 260rpx;
83 | margin: 10rpx 20rpx 15rpx;
84 | }
85 |
86 | .list-item-title {
87 | margin-left: 20rpx;
88 | font-size: 28rpx;
89 | font-weight: bold;
90 | opacity: 0.5;
91 | }
92 |
93 | .list-item-bottom {
94 | margin: 15rpx 20rpx;
95 | display: flex;
96 | }
97 |
98 | .list-item-bottom-icon {
99 | width: 36rpx;
100 | height: 36rpx;
101 | line-height: 36rpx;
102 | text-align: center;
103 | border-radius: 50%;
104 | color: #34373d;
105 | font-weight: 900;
106 | background: #f7e687;
107 | font-size: 24rpx;
108 | }
109 |
110 | .list-item-bottom-price {
111 | flex: 1;
112 | margin: 0 10rpx;
113 | font-size: 28rpx;
114 | }
115 |
--------------------------------------------------------------------------------
/miniprogram/pages/order/order.js:
--------------------------------------------------------------------------------
1 | // pages/order/order.js
2 |
3 | const db = require('../../utils/db.js')
4 | const util = require('../../utils/util')
5 |
6 | Page({
7 |
8 | /**
9 | * 页面的初始数据
10 | */
11 | data: {
12 | userInfo: null,
13 | orderList: [], // 订单列表
14 | },
15 |
16 | onShow() {
17 | util.getUserInfo().then(userInfo => {
18 | this.setData({
19 | userInfo
20 | })
21 | this.getOrder()
22 | }).catch(err => {
23 | console.log('尚未通过身份验证');
24 | })
25 | },
26 |
27 | onTapLogin(event) {
28 | this.setData({
29 | userInfo: event.detail.userInfo
30 | })
31 | },
32 |
33 | getOrder() {
34 | let that = this
35 | if (this.data.orderList.length == 0)
36 | wx.showLoading({
37 | title: '刷新订单数据...',
38 | })
39 | db.getOrderList().then(result => {
40 | wx.hideLoading()
41 | that.setData({
42 | orderList: result.result
43 | })
44 | }).catch(err => {
45 | console.error(err)
46 | wx.hideLoading()
47 | wx.showToast({
48 | title: '刷新订单数据失败',
49 | })
50 | })
51 | },
52 |
53 | goComment(event) {
54 | let product = event.currentTarget.dataset.item
55 | wx.navigateTo({
56 | url: '/pages/add-comment/add-comment?data=' + JSON.stringify(product),
57 | })
58 | }
59 |
60 | })
--------------------------------------------------------------------------------
/miniprogram/pages/order/order.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "订单",
3 | "usingComponents": {
4 | "login": "/components/login"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/order/order.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 暂时还没有订单
9 |
10 |
11 |
12 |
13 | 已完成
14 |
15 |
16 |
17 |
18 |
19 | {{item.name}}
20 | ¥ {{item.price}}
21 |
22 |
23 | 评价
24 | x{{item.count}}
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/miniprogram/pages/order/order.wxss:
--------------------------------------------------------------------------------
1 | /* pages/order/order.wxss */
2 | .order-head {
3 | margin: 40rpx 30rpx 15rpx;
4 | display: flex;
5 | align-items: center;
6 | }
7 |
8 | .order-head-line {
9 | width: 21rpx;
10 | height: 34rpx;
11 | }
12 |
13 | .order-head-text {
14 | margin-left: 10rpx;
15 | font-size: 24rpx;
16 | line-height: 33rpx;
17 | color: rgba(52, 55, 61, 0.8);
18 | }
19 |
20 | .order-block {
21 | margin: 0 26rpx 26rpx;
22 | background: #fff;
23 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.02);
24 | border-radius: 13rpx;
25 | }
26 |
27 | .order-card {
28 | display: flex;
29 | align-items: center;
30 | margin-left: 19rpx;
31 | margin-right: 23rpx;
32 | height: 200rpx;
33 | border-bottom: 1px solid rgba(151, 151, 151, 0.2);
34 | }
35 |
36 | .order-card:last-child {
37 | border-bottom: none;
38 | }
39 |
40 | .order-image {
41 | flex-shrink: 0;
42 | width: 160rpx;
43 | height: 160rpx;
44 | }
45 |
46 | .order-info {
47 | flex: 1;
48 | padding: 27rpx;
49 | height: 100%;
50 | box-sizing: border-box;
51 | font-size: 28rpx;
52 | line-height: 40rpx;
53 | }
54 |
55 | .order-name {
56 | color: rgba(29, 29, 38, 0.8);
57 | }
58 |
59 | .order-price {
60 | margin-top: 12rpx;
61 | font-weight: bold;
62 | }
63 |
64 | .order-opr {
65 | flex-shrink: 0;
66 | margin-left: 59rpx;
67 | padding-top: 34rpx;
68 | height: 100%;
69 | box-sizing: border-box;
70 | font-size: 28rpx;
71 | }
72 |
73 | .order-btn {
74 | width: 100rpx;
75 | height: 52rpx;
76 | line-height: 52rpx;
77 | background: #F5E069;
78 | border-radius: 8rpx;
79 | text-align: center;
80 | }
81 |
82 | .order-count {
83 | margin-top: 49rpx;
84 | line-height: 40rpx;
85 | font-weight: bold;
86 | text-align: right;
87 | }
88 |
--------------------------------------------------------------------------------
/miniprogram/pages/trolley/trolley.js:
--------------------------------------------------------------------------------
1 | // pages/trolley/trolley.js
2 |
3 | const db = require('../../utils/db.js')
4 | const util = require('../../utils/util')
5 |
6 | Page({
7 |
8 | /**
9 | * 页面的初始数据
10 | */
11 | data: {
12 | userInfo: null,
13 | trolleyList: [], // 购物车商品列表
14 | trolleyCheckMap: {}, // 购物车中选中的id哈希表
15 | trolleyAccount: 0, // 购物车结算总价
16 | isTrolleyEdit: false, // 购物车是否处于编辑状态
17 | isTrolleyTotalCheck: false, // 购物车中商品是否全选
18 | },
19 |
20 | onShow() {
21 | util.getUserInfo().then(userInfo => {
22 | this.setData({
23 | userInfo
24 | })
25 | this.getList()
26 | }).catch(err => {
27 | console.log('尚未通过身份验证');
28 | })
29 | },
30 |
31 | onTapLogin(event) {
32 | this.setData({
33 | userInfo: event.detail.userInfo
34 | })
35 | },
36 |
37 | /**
38 | * 获取购物车列表
39 | */
40 | getList() {
41 | let self = this
42 | if (this.data.trolleyList.length == 0)
43 | wx.showLoading({
44 | title: '刷新购物车数据...',
45 | })
46 |
47 | db.getTrolleyList().then(result => {
48 | wx.hideLoading();
49 | const data = result.result;
50 | if (data.length) {
51 | // update the total price for cart
52 | this.setData({
53 | trolleyAccount: util.formatPrice(0),
54 | trolleyList: data
55 | })
56 | }
57 | }).catch(err => {
58 | console.error(err)
59 | wx.hideLoading()
60 | wx.showToast({
61 | icon: 'none',
62 | title: '刷新数据失败'
63 | })
64 | })
65 | },
66 |
67 | onTapCheckSingle(event) {
68 | let checkId = event.currentTarget.dataset.id
69 | let trolleyCheckMap = this.data.trolleyCheckMap
70 | let trolleyList = this.data.trolleyList
71 | let isTrolleyTotalCheck = this.data.isTrolleyTotalCheck
72 | let trolleyAccount = this.data.trolleyAccount
73 | // 单项商品被选中/取消
74 | trolleyCheckMap[checkId] = !trolleyCheckMap[checkId];
75 | isTrolleyTotalCheck = true
76 | trolleyList.forEach(product => {
77 | if (!trolleyCheckMap[product.productId]) {
78 | // not all product selected
79 | isTrolleyTotalCheck = false
80 | }
81 | });
82 | trolleyAccount = this.calcAccount(trolleyList, trolleyCheckMap);
83 | this.setData({
84 | trolleyCheckMap,
85 | isTrolleyTotalCheck,
86 | trolleyAccount
87 | })
88 | },
89 |
90 | onTapCheckTotal() {
91 | let trolleyCheckMap = this.data.trolleyCheckMap
92 | let trolleyList = this.data.trolleyList
93 | let isTrolleyTotalCheck = this.data.isTrolleyTotalCheck
94 | let trolleyAccount = this.data.trolleyAccount
95 |
96 | // 全选按钮被选中/取消
97 | isTrolleyTotalCheck = !isTrolleyTotalCheck
98 |
99 | // 遍历并修改所有商品的状态
100 | trolleyList.forEach(product => {
101 | trolleyCheckMap[product.productId] = isTrolleyTotalCheck
102 | })
103 | trolleyAccount = this.calcAccount(trolleyList, trolleyCheckMap)
104 | this.setData({
105 | isTrolleyTotalCheck,
106 | trolleyCheckMap,
107 | trolleyAccount
108 | })
109 |
110 | },
111 |
112 | calcAccount(trolleyList, trolleyCheckMap) {
113 | let account = 0
114 | trolleyList.forEach(product => {
115 | account = trolleyCheckMap[product.productId] ? account + product.price * product.count : account
116 | })
117 |
118 | return util.formatPrice(account)
119 | },
120 |
121 | onTapEdit() {
122 | let isTrolleyEdit = this.data.isTrolleyEdit
123 |
124 | if (isTrolleyEdit) {
125 | this.updateTrolley()
126 | } else {
127 | this.setData({
128 | isTrolleyEdit: !isTrolleyEdit
129 | })
130 | }
131 | },
132 |
133 | adjustTrolleyCount(event) {
134 | let trolleyCheckMap = this.data.trolleyCheckMap
135 | let trolleyList = this.data.trolleyList
136 | let dataset = event.currentTarget.dataset
137 | let adjustType = dataset.type
138 | let productId = dataset.id
139 | let product
140 | let index
141 |
142 | for (index = 0; index < trolleyList.length; index++) {
143 | if (productId === trolleyList[index].productId) {
144 | product = trolleyList[index]
145 | break
146 | }
147 | }
148 |
149 | if (product) {
150 | if (adjustType === "add") {
151 | product.count++
152 | } else {
153 | if (product.count <= 1) {
154 | // 商品数量不超过1,点击减号相当于删除
155 | delete trolleyCheckMap[productId]
156 | trolleyList.splice(index, 1)
157 | } else {
158 | // 商品数量大于1
159 | product.count--
160 | }
161 | }
162 | }
163 |
164 | // 调整结算总价
165 | let trolleyAccount = this.calcAccount(trolleyList, trolleyCheckMap)
166 |
167 | this.setData({
168 | trolleyAccount,
169 | trolleyList,
170 | trolleyCheckMap
171 | })
172 |
173 | },
174 |
175 | updateTrolley() {
176 | wx.showLoading({
177 | title: '更新购物车数据...',
178 | })
179 | let trolleyList =
180 | db.updateTrolley(this.data.trolleyList).then(result => {
181 | wx.hideLoading();
182 | this.setData({
183 | isTrolleyEdit: false
184 | })
185 | }).catch(err => {
186 | console.error(err)
187 | wx.hideLoading();
188 | wx.showToast({
189 | icon: 'none',
190 | title: '更新购物车失败'
191 | })
192 | })
193 | },
194 |
195 | onTapPay() {
196 |
197 | if (!this.data.trolleyAccount) return
198 |
199 | wx.showLoading({
200 | title: '结算中...',
201 | })
202 |
203 | let self = this
204 | let trolleyCheckMap = this.data.trolleyCheckMap
205 | let trolleyList = this.data.trolleyList
206 |
207 | let needToPayProductList = trolleyList.filter(product => {
208 | return !!trolleyCheckMap[product.productId]
209 | })
210 |
211 | db.addOrder({
212 | list: needToPayProductList,
213 | isCheckout: true
214 | }).then(result => {
215 | wx.hideLoading()
216 | const data = result.result
217 | if (data) {
218 | wx.showToast({
219 | title: '结算成功',
220 | })
221 | self.getList()
222 | }
223 | }).catch(err => {
224 | console.error(err)
225 | wx.hideLoading()
226 |
227 | wx.showToast({
228 | icon: 'none',
229 | title: '结算失败',
230 | })
231 | })
232 | },
233 | })
--------------------------------------------------------------------------------
/miniprogram/pages/trolley/trolley.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "购物车",
3 | "usingComponents": {
4 | "login": "/components/login"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/trolley/trolley.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 购物车是空的
9 | 快添加物品进来吧
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 全选
18 |
19 | {{isTrolleyEdit ? '完成' : '编辑'}}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | {{item.name}}
29 | ¥{{item.price}}
30 |
31 | -
32 | {{item.count}}
33 | +
34 |
35 | x {{item.count}}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | 全选
45 |
46 | 总价
47 | ¥{{ trolleyAccount }}
48 | 结算
49 |
50 |
--------------------------------------------------------------------------------
/miniprogram/pages/trolley/trolley.wxss:
--------------------------------------------------------------------------------
1 | /* pages/trolley/trolley.wxss */
2 |
3 | .trolley-top {
4 | display: flex;
5 | align-items: center;
6 | justify-content: space-between;
7 | padding-left: 24rpx;
8 | }
9 |
10 | .trolley-total {
11 | display: flex;
12 | align-items: center;
13 | padding-left: 35rpx;
14 | font-size: 32rpx;
15 | }
16 |
17 | .trolley-check-wrapper {
18 | flex-shrink: 0;
19 | display: flex;
20 | align-items: center;
21 | justify-content: center;
22 | width: 36rpx;
23 | height: 36rpx;
24 | border-radius: 50%;
25 | background: #ececee;
26 | }
27 |
28 | .trolley-check-wrapper.white {
29 | background: #fff;
30 | }
31 |
32 | .trolley-check-wrapper.check {
33 | background: #f5e069;
34 | }
35 |
36 | .trolley-check {
37 | width: 22rpx;
38 | height: 16rpx;
39 | }
40 |
41 | .trolley-total-text, .trolley-edit, .bottom-text {
42 | margin-left: 18rpx;
43 | margin-right: 33rpx;
44 | color: rgb(52, 55, 61, 0.8);
45 | font-size: 24rpx;
46 | line-height: 33rpx;
47 | }
48 |
49 | .product-list {
50 | position: absolute;
51 | left: 0;
52 | right: 0;
53 | top: 54rpx;
54 | bottom: 100rpx;
55 | padding-bottom: 30rpx;
56 | }
57 |
58 | .product-card {
59 | display: flex;
60 | align-items: center;
61 | margin: 0 26rpx 26rpx;
62 | padding-left: 32rpx;
63 | height: 200rpx;
64 | background: #fff;
65 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.02);
66 | border-radius: 13rpx;
67 | }
68 |
69 | .product-info {
70 | flex: 1;
71 | padding: 38rpx 28rpx 0 36rpx;
72 | height: 100%;
73 | box-sizing: border-box;
74 | font-size: 28rpx;
75 | line-height: 40rpx;
76 | }
77 |
78 | .product-img {
79 | flex-shrink: 0;
80 | margin-left: 31rpx;
81 | width: 160rpx;
82 | height: 160rpx;
83 | }
84 |
85 | .product-name {
86 | color: rgba(29, 29, 38, 0.8);
87 | }
88 |
89 | .product-price {
90 | margin-top: 3rpx;
91 | }
92 |
93 | .product-count {
94 | text-align: right;
95 | }
96 |
97 | .product-count-edit {
98 | display: flex;
99 | align-items: center;
100 | justify-content: flex-end;
101 | }
102 |
103 | .count-minus, .count-add {
104 | width: 36rpx;
105 | height: 36rpx;
106 | line-height: 36rpx;
107 | border-radius: 50%;
108 | border: 3rpx solid #f6e474;
109 | text-align: center;
110 | font-size: 28rpx;
111 | font-weight: 900;
112 | }
113 |
114 | .count-now {
115 | margin: 0 18rpx;
116 | }
117 |
118 | .bottom {
119 | position: fixed;
120 | bottom: 0;
121 | left: 0;
122 | right: 0;
123 | display: flex;
124 | align-items: center;
125 | background: white;
126 | padding-left: 24rpx;
127 | }
128 |
129 | .bottom-pay {
130 | height: 100rpx;
131 | width: 200rpx;
132 | line-height: 100rpx;
133 | text-align: center;
134 | font-size: 30rpx;
135 | background: #f5e069;
136 | color: rgba(52, 55, 61, 0.5);
137 | font-weight: bold;
138 | }
139 |
140 | .bottom-pay.canpay {
141 | color: #34373d
142 | }
143 |
144 | .bottom-text {
145 | flex: 1;
146 | text-align: right;
147 | opacity: 0.5;
148 | margin-right: 5rpx;
149 | }
150 |
151 | .bottom-price {
152 | font-size: 30rpx;
153 | line-height: 42rpx;
154 | margin-right: 20rpx;
155 | }
156 |
--------------------------------------------------------------------------------
/miniprogram/pages/user/user.js:
--------------------------------------------------------------------------------
1 | // pages/user/user.js
2 | const util = require('../../utils/util')
3 |
4 | Page({
5 |
6 | /**
7 | * 页面的初始数据
8 | */
9 | data: {
10 | userInfo: null,
11 | },
12 |
13 | onShow() {
14 | util.getUserInfo().then(userInfo => {
15 | this.setData({
16 | userInfo
17 | })
18 | }).catch(err => {
19 | console.log('尚未通过身份验证');
20 | })
21 | },
22 |
23 | onTapLogin(event) {
24 | this.setData({
25 | userInfo: event.detail.userInfo
26 | })
27 | },
28 |
29 | onTapAddress() {
30 | wx.showToast({
31 | icon: 'none',
32 | title: '此功能暂未开放'
33 | })
34 | },
35 |
36 | onTapService() {
37 | wx.showToast({
38 | icon: 'none',
39 | title: '此功能暂未开放'
40 | })
41 | }
42 | })
--------------------------------------------------------------------------------
/miniprogram/pages/user/user.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "个人中心",
3 | "usingComponents": {
4 | "login": "/components/login"
5 | }
6 | }
--------------------------------------------------------------------------------
/miniprogram/pages/user/user.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | {{userInfo.nickName}}
12 |
13 |
14 |
15 |
16 | 收货地址
17 |
18 |
19 |
20 | 联系客服
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/miniprogram/pages/user/user.wxss:
--------------------------------------------------------------------------------
1 | /* pages/user/user.wxss */
2 | .user-card {
3 | margin: 50rpx 27rpx 0;
4 | background: #FFFFFF;
5 | box-shadow: 0 2rpx 13rpx 5rpx rgba(0, 0, 0, 0.02);
6 | border-radius: 13rpx;
7 | }
8 |
9 | .user-info {
10 | display: flex;
11 | align-items: center;
12 | height: 200rpx;
13 | }
14 |
15 | .user-head {
16 | flex-shrink: 0;
17 | margin-left: 53rpx;
18 | height: 100rpx;
19 | width: 100rpx;
20 | background: #F5E069;
21 | border-radius: 50%;
22 | }
23 |
24 | .user-name {
25 | flex: 1;
26 | margin: 0 31rpx;
27 | font-weight: bold;
28 | white-space: nowrap;
29 | overflow: hidden;
30 | text-overflow: ellipsis;
31 | }
32 |
33 | .user-split {
34 | height: 8rpx;
35 | background: #F9F9F9;
36 | }
37 |
38 | .user-options .option {
39 | display: flex;
40 | align-items: center;
41 | margin-left: 46rpx;
42 | margin-right: 27rpx;
43 | height: 128rpx;
44 | border-bottom: 1px solid rgba(151, 151, 151, 0.2);
45 | }
46 |
47 | .user-options .option:last-child {
48 | border-bottom: none;
49 | }
50 |
51 | .user-options .option-title {
52 | flex: 1;
53 | font-size: 30rpx;
54 | color: rgba(29, 29, 38, 0.8);
55 | }
56 |
57 | .user-options .option-arrow {
58 | width: 11rpx;
59 | height: 18rpx;
60 | }
--------------------------------------------------------------------------------
/miniprogram/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/miniprogram/utils/db.js:
--------------------------------------------------------------------------------
1 | const util = require('./util')
2 |
3 | const db = wx.cloud.database({
4 | env: 'mall-7vt8m'
5 | })
6 |
7 | module.exports = {
8 | getProductList() {
9 | return db.collection('product').get()
10 | },
11 |
12 | getProductDetail(id) {
13 | return wx.cloud.callFunction({
14 | name: 'productDetail',
15 | data: {
16 | id
17 | },
18 | })
19 | },
20 |
21 | getOrderList() {
22 | return wx.cloud.callFunction({
23 | name: 'getOrderList'
24 | })
25 | },
26 |
27 | addOrder(data) {
28 | return util.isAuthenticated()
29 | .then(() => {
30 | return wx.cloud.callFunction({
31 | name: 'addOrder',
32 | data,
33 | })
34 | })
35 | .catch(() => {
36 | wx.showToast({
37 | icon: 'none',
38 | title: '请先登录'
39 | })
40 | return {}
41 | })
42 | },
43 |
44 | getTrolleyList() {
45 | return wx.cloud.callFunction({
46 | name: 'getTrolleyList'
47 | })
48 | },
49 |
50 | addTrolley(data) {
51 | return util.isAuthenticated()
52 | .then(() => {
53 | return wx.cloud.callFunction({
54 | name: 'addTrolley',
55 | data,
56 | })
57 | })
58 | .catch(() => {
59 | wx.showToast({
60 | icon: 'none',
61 | title: '请先登录'
62 | })
63 | return {}
64 | })
65 | },
66 |
67 | updateTrolley(list) {
68 | return util.isAuthenticated()
69 | .then(() => {
70 | return wx.cloud.callFunction({
71 | name: 'updateTrolley',
72 | data: {
73 | list,
74 | },
75 | })
76 | }).catch(() => {
77 | wx.showToast({
78 | icon: 'none',
79 | title: '请先登录'
80 | })
81 | return {}
82 | })
83 | },
84 |
85 | addComment(data) {
86 | return util.isAuthenticated()
87 | .then(() => {
88 | return wx.cloud.callFunction({
89 | name: 'addComment',
90 | data,
91 | })
92 | }).catch(() => {
93 | wx.showToast({
94 | icon: 'none',
95 | title: 'Please Login First'
96 | })
97 | return {}
98 | })
99 | },
100 |
101 | getComments(productId) {
102 | return db.collection('review').where({
103 | productId,
104 | }).get()
105 | },
106 |
107 | uploadImage(imgPath) {
108 | return wx.cloud.uploadFile({
109 | cloudPath: `review/${util.getId()}`,
110 | filePath: imgPath,
111 | })
112 | }
113 |
114 | }
--------------------------------------------------------------------------------
/miniprogram/utils/util.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // make price with 2 digits
3 | formatPrice(price) {
4 | return parseFloat(Math.round(price * 100) / 100).toFixed(2)
5 | },
6 |
7 | getUserInfo() {
8 | return new Promise((resolve, reject) => {
9 | this.isAuthenticated().then(() => {
10 | wx.getUserInfo({
11 | success(res) {
12 | resolve(res.userInfo)
13 | }
14 | })
15 | }).catch(() => {
16 | reject()
17 | })
18 | })
19 | },
20 |
21 | isAuthenticated() {
22 | return new Promise((resolve, reject) => {
23 | wx.getSetting({
24 | success(res) {
25 | if (res.authSetting['scope.userInfo'] === true) {
26 | resolve()
27 | } else {
28 | reject()
29 | }
30 | }
31 | })
32 | })
33 | },
34 |
35 | formatTime(time, reg) {
36 | const date = typeof time === 'string' || typeof time === 'number' ? new Date(time) : time;
37 | const map = {};
38 | map.yyyy = date.getFullYear();
39 | map.yy = ('' + map.yyyy).substr(2);
40 | map.M = date.getMonth() + 1
41 | map.MM = (map.M < 10 ? '0' : '') + map.M;
42 | map.d = date.getDate();
43 | map.dd = (map.d < 10 ? '0' : '') + map.d;
44 | map.H = date.getHours();
45 | map.HH = (map.H < 10 ? '0' : '') + map.H;
46 | map.m = date.getMinutes();
47 | map.mm = (map.m < 10 ? '0' : '') + map.m;
48 | map.s = date.getSeconds();
49 | map.ss = (map.s < 10 ? '0' : '') + map.s;
50 |
51 | return reg.replace(/\byyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s\b/g, $1 => {
52 | return map[$1];
53 | });
54 | },
55 |
56 | getId() {
57 | return Math.floor((1 + Math.random()) * 0x100000000).toString(16).slice(1)
58 | },
59 | }
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "miniprogramRoot": "miniprogram/",
3 | "cloudfunctionRoot": "cloudfunctions/",
4 | "setting": {
5 | "urlCheck": true,
6 | "es6": true,
7 | "postcss": true,
8 | "minified": true,
9 | "newFeature": true
10 | },
11 | "appid": "wx168c62fb8d672fc7",
12 | "projectname": "mall",
13 | "libVersion": "2.2.5",
14 | "simulatorType": "wechat",
15 | "simulatorPluginLibVersion": {},
16 | "condition": {
17 | "search": {
18 | "current": -1,
19 | "list": []
20 | },
21 | "conversation": {
22 | "current": -1,
23 | "list": []
24 | },
25 | "plugin": {
26 | "current": -1,
27 | "list": []
28 | },
29 | "game": {
30 | "list": []
31 | },
32 | "miniprogram": {
33 | "current": 0,
34 | "list": [
35 | {
36 | "id": -1,
37 | "name": "db guide",
38 | "pathName": "pages/databaseGuide/databaseGuide"
39 | }
40 | ]
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------