├── README.md
├── taro-demo
├── .gitignore
├── README.md
├── client
│ ├── .editorconfig
│ ├── .eslintignore
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .prettierrc
│ ├── README.md
│ ├── config
│ │ ├── dev.js
│ │ ├── index.js
│ │ └── prod.js
│ ├── package-lock.json
│ ├── package.json
│ └── src
│ │ ├── actions
│ │ ├── balance.js
│ │ ├── cart.js
│ │ ├── detail.js
│ │ ├── home.js
│ │ ├── order.js
│ │ ├── search.js
│ │ └── shop.js
│ │ ├── app.js
│ │ ├── app.scss
│ │ ├── asset
│ │ ├── add_icon.png
│ │ ├── add_icon_off.png
│ │ ├── area_icon.png
│ │ ├── area_icon_white.png
│ │ ├── arrow_icon.png
│ │ ├── avatar.png
│ │ ├── brand.png
│ │ ├── brand_active.png
│ │ ├── close_icon.png
│ │ ├── emptycart_icon.png
│ │ ├── gift_bag.png
│ │ ├── gift_cover_hand.png
│ │ ├── gift_cover_line.png
│ │ ├── history_icon_off.png
│ │ ├── history_icon_on.png
│ │ ├── home.png
│ │ ├── home_active.png
│ │ ├── ic_del.png
│ │ ├── ic_search.png
│ │ ├── ic_search_leftarrow.png
│ │ ├── ic_search_tips.png
│ │ ├── like_icon_off.png
│ │ ├── like_icon_on.png
│ │ ├── mine.png
│ │ ├── mine_active.png
│ │ ├── minus_icon.png
│ │ ├── minus_icon_off.png
│ │ ├── new_icon.png
│ │ ├── offsale_icon.png
│ │ ├── order_loading.gif
│ │ ├── presents
│ │ │ └── qrcode.png
│ │ ├── radio_off.png
│ │ ├── radio_on.png
│ │ ├── select_icon_off.png
│ │ ├── select_icon_on.png
│ │ ├── selected.png
│ │ ├── service_help_icon.png
│ │ ├── service_right_icon.png
│ │ ├── shopping_cart.png
│ │ ├── shoppingbag.png
│ │ ├── shoppingbag_active.png
│ │ └── tclass
│ │ │ └── presents.gif
│ │ ├── components
│ │ ├── balance
│ │ │ ├── express.js
│ │ │ ├── express.scss
│ │ │ ├── good_list.js
│ │ │ └── good_list.scss
│ │ ├── cart
│ │ │ ├── _mixin.scss
│ │ │ ├── bottom_bar
│ │ │ │ ├── bottom_bar.js
│ │ │ │ └── bottom_bar.scss
│ │ │ ├── commodity
│ │ │ │ ├── commodity.js
│ │ │ │ ├── commodity.scss
│ │ │ │ └── commodity_container.js
│ │ │ ├── edit_box
│ │ │ │ ├── edit_box.js
│ │ │ │ └── edit_box.scss
│ │ │ └── goods
│ │ │ │ ├── goods.js
│ │ │ │ └── goods.scss
│ │ ├── gb
│ │ │ ├── coupon
│ │ │ │ ├── coupon.js
│ │ │ │ └── coupon.scss
│ │ │ ├── modal
│ │ │ │ ├── modal.js
│ │ │ │ └── modal.scss
│ │ │ └── select_panel
│ │ │ │ ├── select_panel.js
│ │ │ │ └── select_panel.scss
│ │ └── search
│ │ │ ├── _mixin.scss
│ │ │ ├── searchBar.js
│ │ │ ├── searchBar.scss
│ │ │ ├── searchFilter
│ │ │ ├── filterMask.js
│ │ │ ├── filterMask.scss
│ │ │ ├── searchFilter.js
│ │ │ └── searchFilter.scss
│ │ │ ├── searchHistory.js
│ │ │ ├── searchHistory.scss
│ │ │ ├── searchHot.js
│ │ │ ├── searchHot.scss
│ │ │ ├── searchInto.js
│ │ │ ├── searchInto.scss
│ │ │ └── searchResult
│ │ │ ├── resultList.js
│ │ │ ├── resultList.scss
│ │ │ ├── searchError.js
│ │ │ └── searchError.scss
│ │ ├── constants
│ │ ├── balance.js
│ │ ├── cart.js
│ │ ├── detail.js
│ │ ├── globalData.js
│ │ ├── home.js
│ │ ├── images.js
│ │ ├── order
│ │ │ ├── detail.js
│ │ │ └── list.js
│ │ ├── search.js
│ │ ├── shop.js
│ │ └── weapp.js
│ │ ├── index.html
│ │ ├── leancloud
│ │ ├── cart
│ │ │ ├── editCart.js
│ │ │ ├── getCart.js
│ │ │ └── utils.js
│ │ ├── dbData.js
│ │ ├── index.js
│ │ ├── order
│ │ │ ├── addOrder.js
│ │ │ ├── cancelOrder.js
│ │ │ ├── getBalance.js
│ │ │ ├── getOrder.js
│ │ │ └── getOrderDetail.js
│ │ ├── search
│ │ │ └── getList.js
│ │ ├── shop
│ │ │ ├── getInformation.js
│ │ │ ├── getShop.js
│ │ │ └── getSku.js
│ │ └── user
│ │ │ ├── addUser.js
│ │ │ └── getUser.js
│ │ ├── pages
│ │ ├── balance
│ │ │ ├── balance.js
│ │ │ └── balance.scss
│ │ ├── cart
│ │ │ ├── cart.js
│ │ │ ├── cart.scss
│ │ │ └── cart_sub.js
│ │ ├── detail
│ │ │ ├── bag.png
│ │ │ ├── detail.js
│ │ │ └── detail.scss
│ │ ├── index
│ │ │ ├── index.js
│ │ │ └── index.scss
│ │ ├── list
│ │ │ ├── list.js
│ │ │ └── list.scss
│ │ ├── shop
│ │ │ ├── shop.js
│ │ │ └── shop.scss
│ │ └── user
│ │ │ └── order
│ │ │ ├── detail
│ │ │ ├── detail.js
│ │ │ └── detail.scss
│ │ │ └── list
│ │ │ ├── list.js
│ │ │ └── list.scss
│ │ ├── reducers
│ │ ├── balance.js
│ │ ├── cart.js
│ │ ├── detail.js
│ │ ├── home.js
│ │ ├── index.js
│ │ ├── order
│ │ │ ├── detail.js
│ │ │ └── list.js
│ │ ├── search.js
│ │ └── shop.js
│ │ ├── store
│ │ └── index.js
│ │ └── utils
│ │ ├── index.js
│ │ ├── util.js
│ │ └── wx.js
├── cloud
│ ├── doc
│ │ ├── cart.json
│ │ ├── commodity.json
│ │ ├── commodity_into.json
│ │ ├── information.json
│ │ ├── order.json
│ │ ├── shop.json
│ │ ├── shop_into.json
│ │ └── user.json
│ └── functions
│ │ ├── cart
│ │ ├── editCart.js
│ │ ├── getCart.js
│ │ ├── index.js
│ │ ├── package.json
│ │ ├── utils.js
│ │ └── yarn.lock
│ │ ├── order
│ │ ├── addOrder.js
│ │ ├── cancelOrder.js
│ │ ├── getBalance.js
│ │ ├── getOrder.js
│ │ ├── getOrderDetail.js
│ │ ├── index.js
│ │ ├── package.json
│ │ └── yarn.lock
│ │ ├── search
│ │ ├── getList.js
│ │ ├── index.js
│ │ ├── package-lock.json
│ │ └── package.json
│ │ ├── shop
│ │ ├── getInformation.js
│ │ ├── getShop.js
│ │ ├── getSku.js
│ │ ├── index.js
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ └── yarn.lock
│ │ └── user
│ │ ├── addUser.js
│ │ ├── getUser.js
│ │ ├── index.js
│ │ ├── package.json
│ │ └── yarn.lock
├── project.config.json
└── tcb.json
├── todoList-Redux
├── .editorconfig
├── .eslintrc
├── .gitignore
├── config
│ ├── dev.js
│ ├── index.js
│ └── prod.js
├── package.json
├── project.config.json
├── src
│ ├── actions
│ │ └── index.js
│ ├── app.js
│ ├── app.scss
│ ├── constants
│ │ └── todos.js
│ ├── index.html
│ ├── pages
│ │ └── index
│ │ │ ├── index.js
│ │ │ └── index.scss
│ ├── reducers
│ │ └── index.js
│ └── store
│ │ └── index.js
└── yarn.lock
└── todoList
├── .editorconfig
├── .eslintrc
├── .gitignore
├── .npmrc
├── config
├── dev.js
├── index.js
└── prod.js
├── package.json
├── project.config.json
└── src
├── app.js
├── app.scss
├── index.html
└── pages
└── index
├── index.js
└── index.scss
/README.md:
--------------------------------------------------------------------------------
1 | # 《Taro 多端开发实现原理与项目实战》源码
2 |
3 | [《Taro 多端开发实现原理与项目实战》](https://juejin.im/book/5b73a131f265da28065fb1cd) 示例代码包含:
4 |
5 | - [《用 Taro 实现一个简单的 Todo 项目》的示例](https://github.com/o2team/taro-ebook-source/tree/master/todoList)
6 | - [《在 Taro 中使用 Redux》的示例](https://github.com/o2team/taro-ebook-source/tree/master/todoList-Redux)
7 | - [实战篇电商平台的示例](https://github.com/o2team/taro-ebook-source/tree/master/taro-demo)
8 |
--------------------------------------------------------------------------------
/taro-demo/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | .temp/
3 | .rn_temp/
4 | node_modules/
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/taro-demo/README.md:
--------------------------------------------------------------------------------
1 | # Taro商城demo
2 |
3 | 本demo的多端适配状态如下:
4 |
5 | - 微信小程序端 --- 后台使用小程序云,已适配
6 | - H5端 --- 后台使用leancloud,已适配
7 | - RN端 --- 后台使用leancloud,适配进行中
8 | - 支付宝小程序端 --- 适配进行中
9 | - 百度小程序端 --- 适配进行中
10 |
11 |
12 |
13 | ### 关于云开发
14 |
15 | 文章中的几个数据集的模拟数据,已上传至`cloud/doc`中,可根据需要自行导入。不过购物车,订单类的数据与openId相关联,所以更多的是可以参考其数据结构。
16 |
17 | 云函数的代码存放在`cloud/functions`中,小册并没有针对此部分进行过多的解读。代码是按模块进行分割,每个模块有一个入口文件和一些执行具体逻辑的文件。各位读者可自行阅读源码进行参考。
18 |
19 |
20 |
21 | ### 关于云函数
22 |
23 | 在使用你自己的云函数环境时,需要将云函数初始化换成你小程序的云环境。有以下几个地方需要注意:
24 |
25 | - `src/app.js`
26 | - `cloud/functions` 下**每个云函数**里的 `index.js`
27 | - `project.config.json` 里的appid需要换成你的小程序的appid
28 |
29 | ```javascript
30 | // src/app.js
31 |
32 | async componentWillMount () {
33 | if (process.env.TARO_ENV === 'weapp') {
34 | wx.cloud.init({
35 | env: 'taro-ebook-23bbcb', // 换成你的云函数环境
36 | traceUser: true // 是否要捕捉每个用户的访问记录。设置为true,用户可在管理端看到用户访问记录
37 | })
38 | const userData = await getWxUserData()
39 | setGlobalData('userData', userData)
40 | }
41 | }
42 |
43 | ```
44 |
45 | ```javascript
46 | // 例: cloud/functions/cart/index.js
47 |
48 | const app = require('tcb-admin-node')
49 |
50 | const { getCart } = require('./getCart.js')
51 | const { editCart } = require('./editCart.js')
52 |
53 | app.init({
54 | envName: 'taro-ebook-23bbcb', // 换成你的云函数环境
55 | mpAppId: 'wx9504f077bdc24ea2' // 换成你的小程序id
56 | })
57 | ```
58 |
59 | 另外,还有值得注意的,本demo在开发的时候,云函数的依赖包是 `tcb-admin-node` ,现在官方文档已改为 `wx-server-sdk`。不过亲测使用 `tcb-admin-node` 依旧能跑通,每个云函数都需要安装依赖后全量上传。
--------------------------------------------------------------------------------
/taro-demo/client/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/taro-demo/client/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/*
2 | lib
3 | node_modules
4 |
--------------------------------------------------------------------------------
/taro-demo/client/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "taro"
4 | ],
5 | "rules": {
6 | "no-unused-vars": [
7 | "error",
8 | {
9 | "varsIgnorePattern": "Taro"
10 | }
11 | ]
12 | },
13 | "parser": "babel-eslint"
14 | }
15 |
--------------------------------------------------------------------------------
/taro-demo/client/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | .temp/
3 | .rn_temp/
4 | node_modules/
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/taro-demo/client/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/taro-demo/client/README.md:
--------------------------------------------------------------------------------
1 | # Taro商城demo
2 |
--------------------------------------------------------------------------------
/taro-demo/client/config/dev.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | NODE_ENV: '"development"'
4 | },
5 | defineConstants: {
6 | },
7 | weapp: {},
8 | h5: {}
9 | }
10 |
--------------------------------------------------------------------------------
/taro-demo/client/config/index.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | projectName: 'toplife-weapp',
3 | date: '2018-4-18',
4 | designWidth: 750,
5 | sourceRoot: 'src',
6 | outputRoot: 'dist',
7 | plugins: {
8 | babel: {
9 | sourceMap: true,
10 | presets: [
11 | 'env'
12 | ],
13 | plugins: [
14 | 'transform-class-properties',
15 | 'transform-decorators-legacy',
16 | 'transform-object-rest-spread'
17 | ]
18 | },
19 | csso: {
20 | enable: true,
21 | config: {
22 | restructure: false
23 | }
24 | }
25 | },
26 | defineConstants: {
27 | },
28 | weapp: {
29 | },
30 | h5: {
31 | publicPath: '/',
32 | staticDirectory: 'static',
33 | module: {
34 | postcss: {
35 | autoprefixer: {
36 | enable: true
37 | }
38 | }
39 | }
40 | }
41 | }
42 |
43 | module.exports = function (merge) {
44 | if (process.env.NODE_ENV === 'development') {
45 | return merge({}, config, require('./dev'))
46 | }
47 | return merge({}, config, require('./prod'))
48 | }
49 |
--------------------------------------------------------------------------------
/taro-demo/client/config/prod.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | NODE_ENV: '"production"'
4 | },
5 | defineConstants: {
6 | },
7 | weapp: {},
8 | h5: {
9 | publicPath: '//labs.qiang.it/toplife_xcx/',
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/taro-demo/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "taro-demo",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "Taro商场",
6 | "main": "index.js",
7 | "scripts": {
8 | "commitmsg": "validate-commit-msg",
9 | "commit": "git-cz",
10 | "dev:weapp": "taro build --type weapp --watch",
11 | "dev:h5": "taro build --type h5 --watch",
12 | "dev:rn": "taro build --type rn --watch",
13 | "dev:alipay": "taro build --type alipay --watch",
14 | "dev:swan": "taro build --type swan --watch",
15 | "build": "cross-env NODE_ENV=production taro build",
16 | "test": "echo \"Error: no test specified\" && exit 1"
17 | },
18 | "config": {
19 | "validate-commit-msg": {
20 | "types": [
21 | "feat",
22 | "fix",
23 | "docs",
24 | "style",
25 | "refactor",
26 | "perf",
27 | "test",
28 | "chore",
29 | "revert",
30 | "ci"
31 | ],
32 | "warnOnFail": false,
33 | "maxSubjectLength": 100,
34 | "helpMessage": ""
35 | }
36 | },
37 | "author": "O2TEAM",
38 | "license": "MIT",
39 | "dependencies": {
40 | "@tarojs/async-await": "1.2.21",
41 | "@tarojs/components": "1.2.21",
42 | "@tarojs/redux": "1.2.21",
43 | "@tarojs/redux-h5": "1.2.21",
44 | "@tarojs/rn-runner": "1.2.21",
45 | "@tarojs/router": "1.2.21",
46 | "@tarojs/taro": "1.2.21",
47 | "@tarojs/taro-alipay": "1.2.21",
48 | "@tarojs/taro-h5": "1.2.21",
49 | "@tarojs/taro-weapp": "1.2.21",
50 | "classnames": "^2.2.5",
51 | "global": "^4.3.2",
52 | "leancloud-realtime": "^4.2.0",
53 | "leancloud-storage": "^3.10.0",
54 | "nerv-redux": "^1.2.18",
55 | "nervjs": "^1.2.17",
56 | "redux": "^4.0.0",
57 | "redux-actions": "^2.3.0",
58 | "redux-logger": "^3.0.6",
59 | "redux-thunk": "^2.2.0",
60 | "tcb-admin-node": "^1.0.21"
61 | },
62 | "devDependencies": {
63 | "@tarojs/plugin-babel": "1.2.21",
64 | "@tarojs/plugin-csso": "1.2.21",
65 | "@tarojs/plugin-sass": "1.2.21",
66 | "@tarojs/plugin-uglifyjs": "1.2.21",
67 | "@tarojs/webpack-runner": "1.2.21",
68 | "babel-eslint": "^10.0.1",
69 | "babel-plugin-transform-class-properties": "^6.24.1",
70 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
71 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
72 | "babel-preset-env": "^1.6.1",
73 | "commitizen": "^2.9.6",
74 | "cross-env": "^5.1.4",
75 | "cz-conventional-changelog": "^2.1.0",
76 | "eslint": "^4.19.1",
77 | "eslint-config-standard": "^11.0.0",
78 | "eslint-config-taro": "1.2.21",
79 | "eslint-plugin-flowtype": "^2.46.1",
80 | "eslint-plugin-import": "^2.9.0",
81 | "eslint-plugin-jest": "^21.15.0",
82 | "eslint-plugin-node": "^6.0.1",
83 | "eslint-plugin-promise": "^3.7.0",
84 | "eslint-plugin-react": "^7.7.0",
85 | "eslint-plugin-standard": "^3.0.1",
86 | "husky": "^0.14.3",
87 | "lint-staged": "^7.0.4",
88 | "validate-commit-msg": "^2.14.0"
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/taro-demo/client/src/actions/detail.js:
--------------------------------------------------------------------------------
1 | import Taro from '@tarojs/taro'
2 | import { operate } from '../constants/cart'
3 | import { createAction } from 'redux-actions'
4 | import { getOpenId, getH5UniqueId } from '../utils/index'
5 | import {
6 | REQUEST_DETAIL_CART,
7 | RECEIVE_DETAIL_CART,
8 | REQUEST_DETAIL_SKU,
9 | RECEIVE_DETAIL_SKU,
10 | REQUEST_DETAIL_ADD_CART,
11 | RECEIVE_DETAIL_ADD_CART
12 | } from '../constants/detail'
13 |
14 | const aMap = {
15 | REQUEST_DETAIL_CART: createAction(REQUEST_DETAIL_CART, data => data),
16 | RECEIVE_DETAIL_CART: createAction(RECEIVE_DETAIL_CART, data => data),
17 | REQUEST_DETAIL_SKU: createAction(REQUEST_DETAIL_SKU, data => data),
18 | RECEIVE_DETAIL_SKU: createAction(RECEIVE_DETAIL_SKU, data => data),
19 | REQUEST_DETAIL_ADD_CART: createAction(REQUEST_DETAIL_ADD_CART, data => data),
20 | RECEIVE_DETAIL_ADD_CART: createAction(RECEIVE_DETAIL_ADD_CART, data => data)
21 | }
22 |
23 | export function fetchCart () {
24 | return async (dispatch, getState) => {
25 | dispatch(aMap[REQUEST_DETAIL_CART]())
26 | let res
27 | if (process.env.TARO_ENV === 'weapp') {
28 | const _openId = await getOpenId()
29 | res = await wx.cloud.callFunction({
30 | name: 'cart',
31 | data: {
32 | func: 'getCart',
33 | data: {
34 | _id: _openId
35 | }
36 | }
37 | }).catch(err => {
38 | console.log(err)
39 | dispatch(aMap[RECEIVE_DETAIL_CART](getState().detail))
40 | })
41 | } else if (process.env.TARO_ENV === 'h5' || 'rn') {
42 | const h5Id = await getH5UniqueId()
43 | const getCart = require('../leancloud/cart/getCart').getCart
44 | res = await getCart(h5Id)
45 | }
46 | const data = res.result.data
47 | if (data.length !== 0) {
48 | dispatch(aMap[RECEIVE_DETAIL_CART](data))
49 | } else {
50 | dispatch(aMap[RECEIVE_DETAIL_CART](getState().detail))
51 | data.code !== 3 && Taro.showToast({
52 | icon: 'none',
53 | title: '服务器繁忙'
54 | })
55 | }
56 | }
57 | }
58 |
59 | export function fetchSkuData (skuId) {
60 | return async dispatch => {
61 | try {
62 | dispatch(aMap[REQUEST_DETAIL_SKU]())
63 | let res
64 | if (process.env.TARO_ENV === 'weapp') {
65 | res = await wx.cloud.callFunction({
66 | name: 'shop',
67 | data: {
68 | func: 'getSku',
69 | data: skuId
70 | }
71 | })
72 | } else if (process.env.TARO_ENV === 'h5' || 'rn') {
73 | const getSku = require('../leancloud/shop/getSku').getSku
74 | res = await getSku(skuId)
75 | }
76 | if (res.result) {
77 | let skuData = res.result.data
78 | dispatch(aMap[RECEIVE_DETAIL_SKU](skuData))
79 | } else {
80 | Taro.redirectTo({url: '/pages/404/404'})
81 | }
82 | } catch (err) {
83 | console.log(err)
84 | Taro.redirectTo({url: '/pages/404/404'})
85 | }
86 | }
87 | }
88 |
89 | export function fetchAddCart (skus) {
90 | return async (dispatch, getState) => {
91 | dispatch(aMap[REQUEST_DETAIL_ADD_CART]())
92 | let res
93 | if (process.env.TARO_ENV === 'weapp') {
94 | const _openId = await getOpenId()
95 | res = await wx.cloud.callFunction({
96 | name: 'cart',
97 | data: {
98 | func: 'editCart',
99 | data: {
100 | _id: _openId,
101 | type: operate['ADD'],
102 | skus
103 | }
104 | }
105 | }).catch(err => {
106 | console.log(err)
107 | dispatch(aMap[RECEIVE_DETAIL_ADD_CART](getState().detail))
108 | })
109 | } else if (process.env.TARO_ENV === 'h5' || 'rn') {
110 | const h5Id = await getH5UniqueId()
111 | const editCart = require('../leancloud/cart/editCart').editCart
112 | const editData = {
113 | h5Id,
114 | type: operate['ADD'],
115 | skus
116 | }
117 | res = await editCart(editData)
118 | }
119 | const data = res.result.data
120 | if (data.length !== 0) {
121 | dispatch(aMap[RECEIVE_DETAIL_ADD_CART](data))
122 | Taro.showToast({
123 | title: '添加购物车成功'
124 | })
125 | } else {
126 | dispatch(aMap[RECEIVE_DETAIL_CART](getState().detail))
127 | data.code !== 3 && Taro.showToast({
128 | icon: 'none',
129 | title: '服务器繁忙'
130 | })
131 | }
132 | }
133 | }
134 |
135 |
--------------------------------------------------------------------------------
/taro-demo/client/src/actions/search.js:
--------------------------------------------------------------------------------
1 | import Taro from '@tarojs/taro'
2 | import { createAction } from 'redux-actions'
3 | import {
4 | SHOW_SEARCH_BAR,
5 | REQUEST_SEARCH_RESULT,
6 | RECEIVE_SEARCH_RESULT,
7 | RECEIVE_SEARCH_ERROR,
8 | SHOW_RESULT,
9 | CHANGE_HISTORY,
10 | SHOW_NOT_FIND,
11 | RESET_STATE
12 | } from '../constants/search'
13 |
14 | export const triggerShowSearchBar = createAction(SHOW_SEARCH_BAR)
15 | export const showResult = createAction(SHOW_RESULT, data => data)
16 | export const changeHistory = createAction(CHANGE_HISTORY, data => data)
17 | export const restState = createAction(RESET_STATE)
18 |
19 | const actionMap = {
20 | requestSearch: createAction(REQUEST_SEARCH_RESULT, (data) => data),
21 | receiveSearch: createAction(RECEIVE_SEARCH_RESULT, (data) => data),
22 | receiveSearchError: createAction(RECEIVE_SEARCH_ERROR, (data) => data),
23 | receiveShowNotFind: createAction(SHOW_NOT_FIND)
24 | }
25 |
26 | export function setSearchHistory (data = {}) {
27 |
28 | return async dispatch => {
29 | try {
30 | const res = await Taro.getStorage({key: 'search_history'})
31 | let history = res.data
32 | if (data.value && data.type && data.type === 'add' && history.indexOf(data.value) === -1) {
33 | history.unshift(data.value)
34 |
35 | } else if (data.value && data.type && data.type === 'add' && history.indexOf(data.value) > -1) {
36 | history.splice(history.indexOf(data.value), 1)
37 | history.unshift(data.value)
38 |
39 | } else if (history && data.value && data.type && data.type === 'delete' && history.indexOf(data.value) > -1) {
40 | history.splice(data.value, 1)
41 | }
42 | if (history.length > 50) {
43 | history = history.splice(0, 50)
44 | }
45 |
46 | Taro.setStorage({
47 | key: 'search_history',
48 | data: history,
49 | success: () => {
50 | dispatch(changeHistory(history))
51 | }
52 | })
53 | } catch (e) {
54 | console.log('操作历史搜索失败')
55 | }
56 | }
57 | }
58 |
59 | export function fetchSearchData (data) {
60 | Taro.showLoading({title: '加载中...'})
61 | data.page = data.page || 1
62 | data['pageSize'] = 10
63 | console.log(data)
64 | return async dispatch => {
65 | try {
66 | dispatch(actionMap['requestSearch']())
67 | let res
68 | if (process.env.TARO_ENV === 'weapp') {
69 | res = await wx.cloud.callFunction({
70 | name: 'search',
71 | data: {
72 | func: 'getList',
73 | data
74 | }
75 | })
76 | } else if (process.env.TARO_ENV === 'h5' || 'rn') {
77 | const getList = require('../leancloud/search/getList').getList
78 | res = await getList(data)
79 | }
80 | if (res.result.data && res.result.data.count) {
81 | dispatch(actionMap['receiveSearch'](res.result.data))
82 | } else {
83 | dispatch(actionMap['receiveShowNotFind']())
84 | }
85 | Taro.hideLoading()
86 | } catch (err) {
87 | console.log(err)
88 | dispatch(actionMap['receiveSearchError']())
89 | Taro.hideLoading()
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/taro-demo/client/src/actions/shop.js:
--------------------------------------------------------------------------------
1 | import Taro from '@tarojs/taro'
2 | import { createAction } from 'redux-actions'
3 |
4 | import {
5 | REQUEST_SHOP,
6 | RECEIVE_SHOP
7 | } from '../constants/shop'
8 |
9 | export const actionMap = {
10 | shopRequest: createAction(REQUEST_SHOP),
11 | shop: createAction(RECEIVE_SHOP, (data) => data)
12 | }
13 |
14 | export function fetchShopData (data) {
15 | const venderId = data.venderId
16 | return async dispatch => {
17 | try {
18 | dispatch(actionMap['shopRequest']())
19 | let res
20 | if (process.env.TARO_ENV === 'weapp') {
21 | res = await wx.cloud.callFunction({
22 | name: 'shop',
23 | data: {
24 | func: 'getShop',
25 | data: venderId
26 | }
27 | })
28 | } else if (process.env.TARO_ENV === 'h5' || 'rn') {
29 | const getShop = require('../leancloud/shop/getShop').getShop
30 | res = await getShop(venderId)
31 | }
32 | if (res.result) {
33 | let shopData = res.result.data
34 | dispatch(actionMap['shop'](shopData))
35 | } else {
36 | Taro.redirectTo({url: '/pages/404/404'})
37 | }
38 | } catch (err) {
39 | console.log(err)
40 | Taro.redirectTo({url: '/pages/404/404'})
41 | }
42 | }
43 | }
44 |
45 | // async function getShop (params) {
46 | // const db = wx.cloud.database()
47 | // const _ = db.command
48 | // const shopColl = db.collection('shop')
49 | // const res = await shopColl.get()
50 | // console.log(JSON.stringify(res.data, 4))
51 | // }
52 |
53 | // getShop()
54 |
--------------------------------------------------------------------------------
/taro-demo/client/src/app.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { Provider } from '@tarojs/redux'
3 | import '@tarojs/async-await'
4 | import configStore from './store'
5 | import Index from './pages/index'
6 |
7 | import { setGlobalData } from './constants/globalData'
8 | import { getWxUserData } from './utils/wx'
9 |
10 | import './app.scss'
11 |
12 | const store = configStore()
13 |
14 | class App extends Component {
15 | config = {
16 | pages: [
17 | 'pages/index/index',
18 | 'pages/shop/shop',
19 | 'pages/user/order/list/list',
20 | 'pages/user/order/detail/detail',
21 | 'pages/cart/cart',
22 | 'pages/cart/cart_sub',
23 | 'pages/detail/detail',
24 | 'pages/list/list',
25 | 'pages/balance/balance'
26 | ],
27 | window: {
28 | backgroundTextStyle: 'light',
29 | navigationBarBackgroundColor: '#ffffff',
30 | navigationBarTitleText: 'TARO商城',
31 | navigationBarTextStyle: 'black'
32 | },
33 | tabBar: {
34 | color: '#7b7b7a',
35 | selectedColor: '#c0a369',
36 | backgroundColor: '#222222',
37 | list: [
38 | {
39 | pagePath: 'pages/index/index',
40 | text: '首页',
41 | iconPath: 'asset/home.png',
42 | selectedIconPath: 'asset/home_active.png'
43 | },{
44 | pagePath: 'pages/cart/cart',
45 | text: '购物车',
46 | iconPath: 'asset/shoppingbag.png',
47 | selectedIconPath: 'asset/shoppingbag_active.png'
48 | }, {
49 | pagePath: 'pages/user/order/list/list',
50 | text: '订单',
51 | iconPath: 'asset/mine.png',
52 | selectedIconPath: 'asset/mine_active.png'
53 | }]
54 | },
55 | cloud: true,
56 | networkTimeout: {
57 | request: 6000,
58 | connectSocket: 10000,
59 | uploadFile: 10000,
60 | downloadFile: 10000
61 | }
62 | }
63 |
64 | constructor () {
65 | super(...arguments)
66 | }
67 |
68 | async componentWillMount () {
69 | if (process.env.TARO_ENV === 'weapp') {
70 | wx.cloud.init({
71 | env: 'taro-ebook-23bbcb', // 前往云控制台获取环境id
72 | traceUser: true // 是否要捕捉每个用户的访问记录。设置为true,用户可在管理端看到用户访问记录
73 | })
74 | const userData = await getWxUserData()
75 | setGlobalData('userData', userData)
76 | }
77 | }
78 |
79 | render() {
80 | return (
81 |
82 |
83 |
84 | )
85 | }
86 | }
87 |
88 | Taro.render(, document.getElementById('app'))
89 |
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/add_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/add_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/add_icon_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/add_icon_off.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/area_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/area_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/area_icon_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/area_icon_white.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/arrow_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/arrow_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/avatar.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/brand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/brand.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/brand_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/brand_active.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/close_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/close_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/emptycart_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/emptycart_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/gift_bag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/gift_bag.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/gift_cover_hand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/gift_cover_hand.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/gift_cover_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/gift_cover_line.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/history_icon_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/history_icon_off.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/history_icon_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/history_icon_on.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/home.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/home_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/home_active.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/ic_del.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/ic_del.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/ic_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/ic_search.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/ic_search_leftarrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/ic_search_leftarrow.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/ic_search_tips.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/ic_search_tips.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/like_icon_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/like_icon_off.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/like_icon_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/like_icon_on.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/mine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/mine.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/mine_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/mine_active.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/minus_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/minus_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/minus_icon_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/minus_icon_off.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/new_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/new_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/offsale_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/offsale_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/order_loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/order_loading.gif
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/presents/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/presents/qrcode.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/radio_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/radio_off.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/radio_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/radio_on.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/select_icon_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/select_icon_off.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/select_icon_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/select_icon_on.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/selected.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/service_help_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/service_help_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/service_right_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/service_right_icon.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/shopping_cart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/shopping_cart.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/shoppingbag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/shoppingbag.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/shoppingbag_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/shoppingbag_active.png
--------------------------------------------------------------------------------
/taro-demo/client/src/asset/tclass/presents.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/asset/tclass/presents.gif
--------------------------------------------------------------------------------
/taro-demo/client/src/components/balance/express.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Text, Image } from '@tarojs/components'
3 | import './express.scss'
4 |
5 | export default class Express extends Component {
6 | render () {
7 | return (
8 |
9 |
10 | {/**/}
11 |
12 |
13 |
14 | 收货人A
15 | 123456789
16 | 默认
17 |
18 | 广东省深圳市宝安区龙光世纪大厦
19 |
20 |
21 |
22 |
23 |
24 | 配送
25 |
26 |
27 | TARO商城配送
28 |
29 | ¥
30 | {this.props.freightPrice}
31 |
32 |
33 | TARO商城配送默认时间
34 |
35 |
36 |
37 |
38 | )
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/balance/express.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | .balance_box {
4 | overflow: hidden;
5 | box-sizing: border-box;
6 | box-shadow: 2px 0 30px rgba(0, 0, 0, 0.06);
7 | }
8 |
9 | .balance_good .total {
10 | color: #232321;
11 | font-family: "toplifeCustomEn";
12 | }
13 |
14 | .balance_good .addr_detail .addr_text {
15 | word-break: break-all;
16 | word-wrap: break-word;
17 | overflow: hidden;
18 | -o-text-overflow: ellipsis;
19 | text-overflow: ellipsis;
20 | display: -webkit-box;
21 | -webkit-box-orient: vertical;
22 | -webkit-line-clamp: 2;
23 | }
24 |
25 | .balance_good_express .express_fee {
26 | font-family: "toplifeCustomEn";
27 | }
28 |
29 | .balance_good_express .val_time {
30 | font-family: "toplifeCustomEn";
31 | }
32 |
33 | /*postcss-pxtransform rn eject disable*/
34 |
35 | .balance_box {
36 | font-size: 24px;
37 | font-weight: 300;
38 | background-color: #fff;
39 | margin: 0 20px 20px;
40 | padding: 40px;
41 | }
42 |
43 | .balance_box:last-child {
44 | margin-bottom: 0;
45 | }
46 |
47 | .addr_default {
48 | color: #fff;
49 | background-color: #232321;
50 | margin-left: 10px;
51 | padding: 0 5px;
52 | }
53 |
54 | .addr_detail {
55 | flex: 1;
56 | }
57 |
58 | .addr_detail_header {
59 | display: flex;
60 | flex-direction: row;
61 | }
62 |
63 | .addr_detail_grey {
64 | color: #999;
65 | }
66 |
67 | .addr_text {
68 | color: #999;
69 | margin-top: 20px;
70 | font-size: 24px;
71 | width: 100%;
72 | }
73 |
74 | .balance_good_addr {
75 | display: flex;
76 | flex-direction: row;
77 | }
78 |
79 | .balance_good_addr_icon {
80 | width: 46px;
81 | height: 60px;
82 | position: relative;
83 | top: 30px;
84 | margin-right: 65px;
85 | }
86 |
87 | .balance_good_addr, .balance_good_express {
88 | padding: 0 30px;
89 | height: 125px;
90 | }
91 |
92 | .balance_box_arrow {
93 | width: 48px;
94 | height: 48px;
95 | }
96 |
97 | .balance_good_express {
98 | display: flex;
99 | flex-direction: row;
100 | align-items: center;
101 | background-color: #f8f8f8;
102 | margin-top: 40px;
103 | }
104 |
105 | .balance_good_label {
106 | width: 110px;
107 | color: #999;
108 | }
109 |
110 | .val_wrap {
111 | display: flex;
112 | flex-direction: column;
113 | flex: 1;
114 | }
115 |
116 | .expredd_grey {
117 | color: #999;
118 | }
119 |
120 | .val_express {
121 | display: flex;
122 | flex-direction: row;
123 | }
124 |
125 | .express_fee {
126 | color: #999;
127 | margin-left: 20px;
128 | }
129 |
130 | .val_time {
131 | margin-top: 10px;
132 | color: #999;
133 | }
134 |
135 | .balance_good .count,
136 | .balance_good .total {
137 | margin-top: 40px;
138 | }
139 |
140 | .balance_good .count {
141 | color: #999;
142 | }
143 |
144 | .balance_good .count text {
145 | margin-right: 10px;
146 | }
147 |
148 | .balance_good .total {
149 | color: #232321;
150 | font-family: "toplifeCustomEn";
151 | }
152 |
153 | .balance_good .good_tip {
154 | background-color: rgba(35, 35, 33, 0.8);
155 | color: #fff;
156 | padding-left: 30px;
157 | height: 50px;
158 | line-height: 50px;
159 | margin-top: -10px;
160 | }
161 |
162 | .balance_slice {
163 | margin-top: 30px;
164 | height: 2px;
165 | background-color: #ddd;
166 | width: 100%;
167 | }
168 |
169 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/balance/good_list.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Text, Image } from '@tarojs/components'
3 | import { parseMoney } from '../../utils/util'
4 | import './good_list.scss'
5 |
6 | export default class GoodList extends Component {
7 | navigateTo (id) {
8 | let url = `/pages/shop/shop?venderId=${id}`
9 | jumpUrl(url)
10 | }
11 |
12 | render () {
13 | let {payCommodities = []} = this.props
14 |
15 | payCommodities = payCommodities.map(item => {
16 | let totalNum = 0
17 | let totalPrice = 0
18 | const newSkus = item.skus.map(skuItem => {
19 | totalNum += parseInt(skuItem.num)
20 | totalPrice += totalNum * parseInt(skuItem.main.price)
21 | if (!/http:\/\/|https:\/\//.test(skuItem.main.images[0])) {
22 | skuItem.imgUrl = `https://${skuItem.main.images[0]}`
23 | } else {
24 | skuItem.imgUrl = skuItem.main.images[0]
25 | }
26 | return skuItem
27 | })
28 | item.skus = newSkus
29 | item.totalNum = totalNum
30 | item.totalPrice = parseMoney(totalPrice)
31 | return item
32 | })
33 |
34 | return (
35 |
36 | {
37 | payCommodities.map(item => {
38 | return (
39 |
40 |
41 |
42 |
43 |
44 | {item.skus.map((sku) => {
45 | console.log(1)
46 | return
47 |
48 |
49 |
50 |
51 |
52 |
53 | {sku.main.skuName}
54 | {sku.sizeInfo.name}: {sku.sizeInfo.value}
55 | {sku.colorInfo.name}: {sku.colorInfo.value}
56 | 支持7天无理由退换
57 |
58 |
59 | ¥{sku.main.price}
60 | X{sku.num}
61 |
62 |
63 |
64 |
65 | })}
66 |
67 |
68 | 共 {item.totalNum} 件商品
69 | 小计:¥{item.totalPrice}
70 |
71 |
72 | )
73 | })
74 | }
75 |
76 | )
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/balance/good_list.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 | .balance_good_items .info_support::before {
3 | display: inline-block;
4 | content: "";
5 | width: 20px;
6 | height: 20px;
7 | background: url("https://static.360buyimg.com/tp-statics/2018-4-20/m/img/ic_7days@2x.png") no-repeat;
8 | background-size: 100% 100%;
9 | position: relative;
10 | top: 2px;
11 | margin-right: 8px;
12 | }
13 |
14 | .balance_good_items .info_support.nosupport::before {
15 | background: url("https://static.360buyimg.com/tp-statics/2018-4-20/m/img/ic_no7days@2x.png") no-repeat;
16 | background-size: 100% 100%;
17 | }
18 |
19 | /*postcss-pxtransform rn eject disable*/
20 |
21 | .balance_box {
22 | font-size: 24px;
23 | font-weight: 300;
24 | background-color: #fff;
25 | margin: 0 20px 20px;
26 | padding: 40px;
27 | }
28 |
29 | .balance_good_shop {
30 | display: flex;
31 | flex-direction: row;
32 | justify-content: center;
33 | height: 60px;
34 | }
35 |
36 | .balance_good_shop_image {
37 | width: 180px;
38 | height: 60px;
39 | }
40 |
41 | .balance_slice {
42 | margin-top: 30px;
43 | height: 2px;
44 | background-color: #ddd;
45 | width: 100%;
46 | }
47 |
48 | .balance_good_items {
49 | overflow: hidden;
50 | margin-bottom: 40px;
51 | }
52 |
53 | .balance_good_item {
54 | display: flex;
55 | flex-direction: row;
56 | margin-top: 60px;
57 | overflow: hidden;
58 | }
59 |
60 | .balance_good_items_pic {
61 | width: 200px;
62 | margin-right: 40px;
63 | position: relative;
64 | }
65 |
66 | .balance_good_items_pic_image {
67 | width: 200px;
68 | height: 200px;
69 | }
70 |
71 | .balance_good_items .pic_count {
72 | width: 200px;
73 | height: 50px;
74 | background-color: rgba(35, 35, 33, 0.8);
75 | position: absolute;
76 | bottom: 0;
77 | left: 0;
78 | text-align: center;
79 | line-height: 50px;
80 | color: #fff;
81 | }
82 |
83 | .balance_good_items .item_count {
84 | line-height: 200px;
85 | color: #999;
86 | }
87 |
88 | .balance_good_items .item_count text {
89 | color: #232321;
90 | margin-right: 10px;
91 | }
92 |
93 | .balance_good_items .arrow {
94 | top: 75px;
95 | }
96 |
97 | .info_wrap {
98 | flex: 1;
99 | }
100 |
101 | .info {
102 | display: flex;
103 | flex-direction: column;
104 | }
105 |
106 | .info_name {
107 | color: #232321;
108 | margin-bottom: 30px;
109 | }
110 |
111 | .balance_good_items .price_val {
112 | font-weight: 400;
113 | font-family: "toplifeCustomEn";
114 | }
115 |
116 | .price {
117 | display: flex;
118 | flex-direction: row;
119 | align-items: baseline;
120 | margin-top: 40px;
121 | }
122 |
123 | .balance_good_items .price_val text {
124 | font-size: 32px;
125 | }
126 |
127 | .price_num {
128 | flex: 1;
129 | text-align: right;
130 | }
131 |
132 | .balance_grey {
133 | color: #999;
134 | }
135 |
136 | .balance_good_count {
137 | margin-top: 20px;
138 | display: flex;
139 | flex-direction: row;
140 | }
141 |
142 | .count_text, .count_total_text {
143 | color: #999;
144 | }
145 |
146 | .count_total_text{
147 | flex: 1;
148 | text-align: right;
149 | }
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/cart/_mixin.scss:
--------------------------------------------------------------------------------
1 | @mixin image-background($url) {
2 | background: url($url) no-repeat center center;
3 | background-size: 100% 100%;
4 | width: width($url, 3);
5 | height: height($url, 3);
6 | }
7 |
8 | @mixin img-bg ($url, $width, $height) {
9 | display: inline-block;
10 | background-image: url($url);
11 | background-size: 100% 100%;
12 | width: ($width);
13 | height: ($height);
14 | }
--------------------------------------------------------------------------------
/taro-demo/client/src/components/cart/bottom_bar/bottom_bar.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 | .del_popup {
3 | position: fixed;
4 | width: 100%;
5 | height: 100%;
6 | left: 0;
7 | top: 0;
8 | background-color: rgba(0, 0, 0, 0.8);
9 | z-index: 10;
10 | }
11 |
12 | .del_popup_content {
13 | position: absolute;
14 | left: 50%;
15 | top: 50%;
16 | width: 600px;
17 | height: 320px;
18 | transform: translate(-50%, -50%);
19 | background-color: #fff;
20 | color: #232321;
21 | text-align: center;
22 | border-radius: 30px;
23 | }
24 |
25 | .del_popup_title {
26 | margin-top: 40px;
27 | font-size: 32px;
28 | }
29 |
30 | .del_popup_text {
31 | margin-top: 40px;
32 | font-size: 24px;
33 | }
34 |
35 | .del_popup_btn {
36 | position: absolute;
37 | bottom: 0;
38 | left: 0;
39 | width: 100%;
40 | height: 88px;
41 | border-top: 2px solid #eee;
42 | }
43 |
44 | .del_popup_btn_cancel {
45 | color: #8c8c8c;
46 | border-right: 2px solid #eee;
47 | }
48 |
49 | .del_popup_btn_confirm {
50 | color: #666;
51 | }
52 |
53 | .del_popup_btn text {
54 | display: block;
55 | float: left;
56 | width: 50%;
57 | height: 88px;
58 | text-align: center;
59 | line-height: 88px;
60 | font-size: 32px;
61 | box-sizing: border-box;
62 | }
63 |
64 | /*postcss-pxtransform rn eject disable*/
65 |
66 |
67 | .bottom_bar_wp {
68 | flex-direction: row;
69 | flex-shrink: 0;
70 | width: 100%;
71 | height: 100px;
72 | position: relative;
73 | background-color: #232321;
74 | // position: fixed;
75 | // left: 0;
76 | // bottom: 0;
77 | // margin-bottom: 100px;
78 | }
79 |
80 | .bottom_bar{
81 | display: flex;
82 | flex-direction: row;
83 | width: 100%;
84 | }
85 |
86 | .bottom_bar_select_wp{
87 | display: flex;
88 | flex-direction: row;
89 | align-items: center;
90 | }
91 |
92 | .bottom_bar_select {
93 | display: flex;
94 | justify-content: center;
95 | align-items: center;
96 | width: 170px;
97 | height: 100px;
98 | }
99 |
100 | .select_radio_img{
101 | width: 24px;
102 | height: 24px;
103 | }
104 |
105 | .select_radio_text {
106 | font-size: 24px;
107 | color: #fff;
108 | }
109 |
110 | .bottom_bar_select .select_radio_real {
111 | position: absolute;
112 | left: 58px;
113 | visibility: hidden;
114 | }
115 |
116 | .bottom_bar_total {
117 | display: flex;
118 | flex-direction: column;
119 | justify-content: center;
120 | height: 100px;
121 | color: #fff;
122 | }
123 |
124 | .bottom_bar_total_text {
125 | display: flex;
126 | flex-direction: row;
127 | align-items: baseline;
128 | color: white;
129 | font-size: 24px;
130 | }
131 |
132 | .bottom_bar_total_small {
133 | color: white;
134 | font-size: 16px;
135 | }
136 |
137 | .bottom_bar_total_big {
138 | color: white;
139 | font-size: 32px;
140 | }
141 |
142 | .bottom_bar_total_desc {
143 | color: white;
144 | font-size: 18px;
145 | }
146 |
147 | .bottom_bar_btn {
148 | position: absolute;
149 | display: flex;
150 | height: 100px;
151 | width: 228px;
152 | right: 0;
153 | top: 0;
154 | align-items: center;
155 | justify-content: center;
156 | color: #232321;
157 | background-color: #bfa36c;
158 | font-size: 32px;
159 | }
160 |
161 | .bottom_bar_btn.del {
162 | background-color: #000000;
163 | color: #fff;
164 | }
165 |
166 | .bottom_bar_btn_none {
167 | background-color: #999999;
168 | }
169 |
170 | .bottom_bar_wp.hide {
171 | display: none;
172 | }
173 |
174 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/cart/commodity/commodity_container.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { connect } from '@tarojs/redux'
3 | import { View } from '@tarojs/components'
4 |
5 | import Commondity from './commodity'
6 | import {
7 | fetchCheckCart,
8 | fetchInvertCheckCart,
9 | checkDelCart,
10 | inverseCheckDelCart,
11 | showEditBox,
12 | fetchCart,
13 | fetchChangeCartNum,
14 | fetchDelCart,
15 | changeCouponStatus,
16 | changeEditStatus
17 | } from '../../../actions/cart'
18 |
19 | class CommondityContainer extends Component {
20 | constructor (...args) {
21 | super(...args)
22 | }
23 |
24 | render () {
25 | const {
26 | isFixedBar,
27 | commoditys,
28 | editSkuData,
29 | isEditStatus,
30 | isFetching,
31 | fetchCheckCart,
32 | fetchInvertCheckCart,
33 | checkDelCart,
34 | inverseCheckDelCart,
35 | showEditBox,
36 | fetchCart,
37 | fetchChangeCartNum,
38 | fetchDelCart,
39 | changeEditStatus
40 | } = this.props
41 | return (
42 |
43 |
59 |
60 | )
61 | }
62 | }
63 |
64 | export default connect(({
65 | cart
66 | }) => {
67 | return {
68 | editSkuData: cart.editSkuData,
69 | commoditys: cart.commoditys,
70 | isEditStatus: cart.isEditStatus,
71 | isFetching: cart.isFetching
72 | }
73 | }, (dispatch) => ({
74 | fetchCart (...args) {
75 | dispatch(fetchCart(...args))
76 | },
77 | fetchCheckCart (...args) {
78 | dispatch(fetchCheckCart(...args))
79 | },
80 | fetchInvertCheckCart (...args) {
81 | dispatch(fetchInvertCheckCart(...args))
82 | },
83 | checkDelCart (...args) {
84 | dispatch(checkDelCart(...args))
85 | },
86 | inverseCheckDelCart (...args) {
87 | dispatch(inverseCheckDelCart(...args))
88 | },
89 | showEditBox (...args) {
90 | dispatch(showEditBox(...args))
91 | },
92 | fetchChangeCartNum (...args) {
93 | dispatch(fetchChangeCartNum(...args))
94 | },
95 | fetchDelCart (...args) {
96 | dispatch(fetchDelCart(...args))
97 | },
98 | changeCouponStatus (...args) {
99 | dispatch(changeCouponStatus(...args))
100 | },
101 | changeEditStatus (...args) {
102 | dispatch(changeEditStatus(...args))
103 | }
104 | }))(CommondityContainer)
105 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/cart/edit_box/edit_box.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Image, Text } from '@tarojs/components'
3 | import { connect } from '@tarojs/redux'
4 | import classnames from 'classnames'
5 |
6 | import {
7 | hideEditBox,
8 | fetchChangeAttr
9 | } from '../../../actions/cart'
10 |
11 | import './edit_box.scss'
12 |
13 | class EditBox extends Component {
14 | constructor () {
15 | super(...arguments)
16 | this.state = {
17 | showColorValue: '',
18 | showSizeValue: '',
19 | isClose: false
20 | }
21 | }
22 |
23 | onAnimationEnd = () => {
24 | const {isClose} = this.state
25 | if (isClose) {
26 | this.setState({isClose: false})
27 | this.props.hideEditBox()
28 | }
29 | }
30 |
31 | runCloseAni = () => {
32 | this.setState({isClose: true})
33 | }
34 |
35 | selectAttr = (type, value) => {
36 | if (type === 'color') {
37 | this.setState({showColorValue: value})
38 | } else if (type === 'size') {
39 | this.setState({showSizeValue: value})
40 | }
41 | }
42 |
43 | changeCartAttr = () => {
44 | const { editSkuData, onFetchChangeAttr } = this.props
45 | const {showColorValue, showSizeValue} = this.state
46 | const {sku} = editSkuData
47 | const newSku = [
48 | {
49 | skuId: sku.skuId,
50 | color: showColorValue || sku.colorInfo.value,
51 | size: showSizeValue || sku.sizeInfo.value
52 | }]
53 |
54 | this.runCloseAni()
55 | if (showColorValue || showSizeValue) {
56 | onFetchChangeAttr(newSku)
57 | }
58 | }
59 |
60 | render () {
61 | const {isClose, showColorValue, showSizeValue} = this.state
62 | const {editSkuData} = this.props
63 | const {showEidtBox, sku} = editSkuData
64 | const {colorInfo, sizeInfo} = sku || {}
65 |
66 | const colorValue = showColorValue || colorInfo.value
67 | const sizeValue = showSizeValue || sizeInfo.value
68 |
69 | const wpClass = classnames('editbox bg_shade', {'show': showEidtBox}, {'fade': isClose})
70 | const aniClass = classnames('editbox_content', {'show_wp': !isClose && showEidtBox}, {'hide_wp': isClose})
71 | return (
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | ¥{sku.main.price}
80 | 商品编号:{sku.skuId}
81 |
82 |
83 |
84 |
85 | {colorInfo.name}:
86 |
87 | {colorInfo.all.map((value, idx) => {
88 | return {value}
93 | })}
94 |
95 |
96 |
97 | {colorInfo.name}:
98 |
99 | {sizeInfo.all.map((value, idx) => {
100 | return {value}
105 | })}
106 |
107 |
108 | {sku.isOutOfStock ? 该商品补货中 : 确定}
109 |
110 |
111 | )
112 | }
113 | }
114 |
115 | export default connect(({
116 | cart
117 | }) => ({
118 | editSkuData: cart.editSkuData
119 | }), (dispatch) => ({
120 | hideEditBox (...args) {
121 | dispatch(hideEditBox(...args))
122 | },
123 | onFetchChangeAttr (...args) {
124 | dispatch(fetchChangeAttr(...args))
125 | }
126 | }))(EditBox)
127 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/cart/edit_box/edit_box.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | @import '../_mixin.scss';
4 |
5 | .editbox {
6 | display: none;
7 | font-family: '-apple-system-font,Helvetica Neue,Helvetica,sans-serif';
8 | z-index: 10;
9 | &_content {
10 | position: absolute;
11 | bottom: 0;
12 | padding-bottom: 150px;
13 | width: 100%;
14 | background-color: #fff;
15 | }
16 | &_header {
17 | position: relative;
18 | height: 180px;
19 | &_img {
20 | position: absolute;
21 | left: 40px;
22 | top: -60px;
23 | width: 200px;
24 | height: 200px;
25 | border: 2px solid #ddd;
26 | .taro-img,
27 | image {
28 | width: 100%;
29 | height: 100%;
30 | }
31 | }
32 | &_text {
33 | position: absolute;
34 | top: 60px;
35 | left: 270px;
36 | &_price {
37 | font-family: 'toplifeCustomEn';
38 | font-size: 32px;
39 | color: #232321;
40 | }
41 | &_desc {
42 | display: block;
43 | font-size: 24px;
44 | line-height: 1.5;
45 | color: #999999;
46 | }
47 | .small {
48 | font-size: 16px;
49 | }
50 | }
51 | &_close {
52 | position: absolute;
53 | right: 35px;
54 | top: 30px;
55 | @include img-bg('http://storage.jd.com/o2images/close_icon.png', 40px, 40px);
56 | }
57 | }
58 | &_option {
59 | margin-bottom: 40px;
60 | padding: 0 40px;
61 | color: #232321;
62 | &_title {
63 | font-size: 28px;
64 | }
65 | &_wp {
66 | margin-top: 20px;
67 | }
68 | &_item {
69 | display: inline-block;
70 | margin-right: 34px;
71 | margin-bottom: 30px;
72 | padding: 30px 40px;
73 | font-size: 24px;
74 | text-align: center;
75 | border: 2px solid #ddd;
76 | &.on {
77 | color: #fff;
78 | background-color: #000;
79 | }
80 | }
81 | &.size {
82 | .editbox_option_item {
83 | padding-left: 20px;
84 | padding-right: 20px;
85 | font-size: 32px;
86 | box-sizing: border-box;
87 | }
88 | }
89 | }
90 | &_btn {
91 | position: absolute;
92 | bottom: 0;
93 | width: 100%;
94 | height: 100px;
95 | line-height: 100px;
96 | color: #fff;
97 | background-color: #222;
98 | text-align: center;
99 | font-size: 32px;
100 | }
101 | &_offsale {
102 | position: absolute;
103 | bottom: 0;
104 | width: 100%;
105 | height: 76px;
106 | line-height: 76px;
107 | color: #fff;
108 | background-color: rgba(0,0,0,.7);
109 | text-align: center;
110 | font-size: 32px;
111 | }
112 | }
113 |
114 | .bg_shade {
115 | position: fixed;
116 | left: 0;
117 | right: 0;
118 | top: 0;
119 | bottom: 0;
120 | background-color: rgba($color: #232321, $alpha: 0.8);
121 | z-index: 999;
122 | }
123 |
124 |
125 | .show {
126 | display: block!important;
127 | }
128 |
129 | .show_wp {
130 | animation: slide_in .3s ease-out forwards;
131 | }
132 |
133 | .hide_wp {
134 | animation: slide_out .3s ease-in forwards;
135 | }
136 |
137 | .fade {
138 | animation: fade_out .3s ease-in-out forwards;
139 | }
140 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/cart/goods/goods.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Text, Image } from '@tarojs/components'
3 | import { connect } from '@tarojs/redux'
4 |
5 | import {
6 | fetchDiviner
7 | } from '../../../actions/cart'
8 |
9 | import { jumpUrl, log } from '../../../utils/util'
10 | import './goods.scss'
11 |
12 | class Goods extends Component {
13 | constructor () {
14 | super(...arguments)
15 | this.state = {
16 | showDiviner: true
17 | }
18 | }
19 |
20 | tabHandle = (type) => {
21 | if (type === 'diviner') {
22 | if (!this.state.showDiviner) this.setState({showDiviner: true})
23 | } else {
24 | if (this.state.showDiviner) this.setState({showDiviner: false})
25 | }
26 | }
27 |
28 | componentWillMount () {}
29 |
30 | gotoDetail = (skuId, e) => {
31 | jumpUrl(`../detail/detail?skuId=${skuId}`)
32 | log.autoClick(e)
33 | }
34 |
35 | render () {
36 | const { footmark, isSub } = this.props
37 | const hasNofootmark = !footmark || footmark.length === 0
38 | return (
39 |
40 |
41 |
42 |
43 |
44 | 最近浏览
45 |
46 |
47 | {hasNofootmark
48 | ?
49 | 暂无最近浏览商品
50 |
51 | :
52 | {footmark.map((good, index) => {
53 | return (
54 |
62 |
63 |
64 | {good.stockState === 34 || good.stockState === 0 || good.price === '-1'
65 | ?
66 | 补货中
67 | : null}
68 |
69 |
70 | {good.brandName}
71 | {good.shortName}
72 | {good.price === '-1'
73 | ? 暂无报价
74 | : ¥{good.price}}
75 | {/* ¥32,700 */}
76 |
77 |
78 | )
79 | })}
80 | }
81 |
82 |
83 | )
84 | }
85 | }
86 |
87 | export default connect(({
88 | cart
89 | }) => ({
90 | diviner: cart.diviner,
91 | footmark: cart.footmark
92 | }), (dispatch) => ({
93 | fetchDiviner (...args) {
94 | dispatch(fetchDiviner(...args))
95 | }
96 | }))(Goods)
97 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/cart/goods/goods.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | /*postcss-pxtransform rn eject disable*/
4 | .goods {
5 | margin: 20px auto 0 auto;
6 | width: 710px;
7 | background-color: #fff;
8 | }
9 |
10 | .goods_wp {
11 | padding-bottom: 20px;
12 | }
13 |
14 | .goods_tab {
15 | height: 100px;
16 | display: flex;
17 | align-items: center;
18 | justify-content: center;
19 | //border-bottom: 2px solid #ddd;
20 | }
21 |
22 | .goods_tab_item {
23 | display: flex;
24 | flex-direction: row;
25 | align-items: center;
26 | justify-content: center;
27 | width: 270px;
28 | font-size: 28px;
29 | color: #999;
30 | }
31 |
32 | .goods_tab_item .like {
33 | display: inline-block;
34 | background-image: url("//storage.jd.com/o2images/like_icon_off.png");
35 | background-size: 100% 100%;
36 | width: 37px;
37 | height: 32px;
38 | }
39 |
40 | //.goods_tab_item .history {
41 | // display: inline-block;
42 | // background-image: url("//storage.jd.com/o2images/history_icon_off.png");
43 | // background-size: 100% 100%;
44 | // width: 28px;
45 | // height: 32px;
46 | //}
47 |
48 | .goods_tab_item.on {
49 | color: #232321;
50 | }
51 |
52 | .goods_tab_item.on .like {
53 | background-image: url("//storage.jd.com/o2images/like_icon_on.png");
54 | }
55 |
56 | //.goods_tab_item.on .history {
57 | // background-image: url("//storage.jd.com/o2images/history_icon_on.png");
58 | //}
59 |
60 | .goods_tab_icon {
61 | width: 28px;
62 | height: 32px;
63 | margin-right: 10px;
64 | }
65 |
66 | .goods_content {
67 | display: flex;
68 | flex-wrap: wrap;
69 | }
70 |
71 | .goods_content_item {
72 | width: 50%;
73 | height: 700px;
74 | padding-top: 35px;
75 | }
76 |
77 | .goods_content_item_img {
78 | position: relative;
79 | display: flex;
80 | align-items: center;
81 | justify-content: center;
82 | width: 355px;
83 | height: 455px;
84 | }
85 |
86 | .goods_content_item_img image {
87 | width: 355px;
88 | height: 455px;
89 | }
90 |
91 | .goods_content_item_img .item_img_none {
92 | position: absolute;
93 | display: flex;
94 | align-items: center;
95 | justify-content: center;
96 | left: 0;
97 | top: 0;
98 | width: 100%;
99 | height: 100%;
100 | background-color: rgba(255, 255, 255, 0.5);
101 | }
102 |
103 | .goods_content_item_img .item_img_none_text {
104 | display: block;
105 | width: 50%;
106 | height: 42px;
107 | line-height: 42px;
108 | text-align: center;
109 | font-size: 22px;
110 | color: #fff;
111 | background-color: rgba(0, 0, 0, 0.5);
112 | }
113 |
114 | .goods_content_item .gciw {
115 | padding: 0 40px;
116 | color: #232321;
117 | line-height: 1.5;
118 | }
119 |
120 | .goods_content_item .gciw_brand {
121 | display: block;
122 | margin-top: 20px;
123 | font-size: 26px;
124 | overflow: hidden;
125 | text-overflow: ellipsis;
126 | white-space: nowrap;
127 | }
128 |
129 | .goods_content_item .gciw_name {
130 | display: block;
131 | font-size: 24px;
132 | height: 72px;
133 | overflow: hidden;
134 | text-overflow: ellipsis;
135 | display: -webkit-box;
136 | }
137 |
138 | .goods_content_item .gciw_none {
139 | display: block;
140 | height: 48px;
141 | line-height: 48px;
142 | font-size: 24px;
143 | }
144 |
145 | .goods_content_item .gciw_price {
146 | display: block;
147 | font-size: 32px;
148 | }
149 |
150 | .goods_content_item .gciw_overdue {
151 | display: block;
152 | font-size: 24px;
153 | color: #999;
154 | text-decoration: line-through;
155 | }
156 |
157 | .goods_content_item .gciw .small {
158 | font-size: 16px;
159 | }
160 |
161 | .goods_content_item .gciw .new_icon {
162 | margin-right: 10px;
163 | display: inline-block;
164 | background-image: url("//storage.jd.com/o2images/new_icon.png");
165 | background-size: 100% 100%;
166 | width: 60px;
167 | height: 26px;
168 | }
169 |
170 | .goods_none {
171 | display: flex;
172 | justify-content: center;
173 | align-items: center;
174 | width: 100%;
175 | height: 500px;
176 | background-color: #ffffff;
177 | font-size: 24px;
178 | color: #999;
179 | }
180 |
181 | .goods .hide {
182 | display: none;
183 | }
184 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/gb/coupon/coupon.js:
--------------------------------------------------------------------------------
1 | import Taro, {Component} from '@tarojs/taro'
2 | import {View, Text, Image} from '@tarojs/components'
3 | import {getUuid, getLoginStatus, getAreas, jumpUrl, log} from '../../../utils/util'
4 |
5 | export class CouponItem extends Component {
6 | state = {}
7 | constructor () {
8 | super(...arguments)
9 | }
10 |
11 | toUseCoupon (coupon, cantUse, e) {
12 | let parseCantUse = typeof cantUse === 'boolean' && cantUse
13 | if (parseCantUse) return
14 | let couponBatch = coupon.batchId
15 | let couponInfo = `${coupon.quota}-${coupon.discount}`
16 | jumpUrl(`../list/list?couponBatch=${couponBatch}&couponInfo=${couponInfo}`)
17 | log.autoClick(e)
18 | }
19 |
20 | async selectCoupon (coupon, isBalance, cantUse) {
21 | let parseCantUse = typeof cantUse === 'boolean' && cantUse
22 | if (!isBalance || parseCantUse) return
23 | let cantSelect = coupon.showDesc
24 | if (cantSelect) {
25 | Taro.showToast({
26 | icon: 'none',
27 | title: '请先取消选中的优惠券'
28 | })
29 | return
30 | }
31 | let balanceCoupon = this.$parent
32 | let {fetchCouponInfo, balanceInfo} = balanceCoupon.props
33 | let {cachedCoupons} = balanceCoupon.state
34 | let newCachedCoupons = {}
35 |
36 | if (coupon.selected) {
37 | for (let i in cachedCoupons) {
38 | if (coupon.id !== i) {
39 | newCachedCoupons[i] = coupon.discount
40 | }
41 | }
42 | } else {
43 | newCachedCoupons = cachedCoupons || {}
44 | newCachedCoupons[coupon.id] = coupon.discount
45 | }
46 |
47 | balanceCoupon.setState({
48 | cachedCoupons: newCachedCoupons
49 | }, async () => {
50 | let body = JSON.stringify({"cachedCoupons": newCachedCoupons})
51 | let uuid = await getUuid()
52 | let ptKey = await getLoginStatus()
53 | let areas = await getAreas()
54 | areas = areas ? areas.areas : null
55 | let address = balanceInfo.address
56 | areas = areas
57 | ? areas
58 | : (address ? `${address.provinceId}-${address.cityId}-${address.countyId}-${address.townId}`: null)
59 |
60 | fetchCouponInfo({
61 | uuid,
62 | areas,
63 | body
64 | }, {
65 | 'cookie': `pt_key=${ptKey}`
66 | })
67 | })
68 | log.autoClick(e)
69 | }
70 |
71 | render () {
72 | const {coupon, cantSelect, isBalance, elevel, eid, eparam} = this.props
73 | let curCantSelect = cantSelect || (isBalance && coupon && coupon.showDesc)
74 | let useText = '立即使用'
75 | if (coupon && cantSelect) {
76 | switch (coupon.state) {
77 | case 3:
78 | useText = '已使用'
79 | break
80 | case 1000:
81 | useText = '已过期'
82 | break
83 | }
84 | }
85 | return (
86 |
87 |
88 | {isBalance && !cantSelect && }
89 | ¥
90 | {coupon && coupon.discount}
91 |
92 |
93 | 满{coupon && coupon.quota}元使用
94 |
95 | {coupon && coupon.limitStr}
96 | {coupon && coupon.timeStr}
97 | {!isBalance && {useText}}
98 | {isBalance && curCantSelect && *{coupon && coupon.showDesc}}
99 |
100 | )
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/gb/coupon/coupon.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | .coupon {
4 | &_item {
5 | width: 670px;
6 | height: 360px;
7 | padding-top: 36px;
8 | background-color: #fff;
9 | background-repeat: no-repeat;
10 | background-image: url('https://static.360buyimg.com/tp-statics/2018-4-17/m/img/coupon_bg.png');
11 | background-size: 100% 100%;
12 | margin: 0 auto 20px;
13 | text-align: center;
14 |
15 | &.cantSelect {
16 | background-color: #fff;
17 | background-repeat: no-repeat;
18 | background-image: url('https://static.360buyimg.com/tp-statics/2018-4-17/m/img/gray_coupon_bg.png');
19 | background-size: 100% 100%;
20 |
21 | view {
22 | color: #ccc;
23 | }
24 | .coupon_tit {
25 | background-repeat: no-repeat;
26 | background-image: url('https://static.360buyimg.com/tp-statics/2018-4-17/m/img/uncoupon_toplife.png');
27 | background-size: 100% 100%;
28 | }
29 | .coupon_need_money {
30 | &::before,
31 | &::after {background-color: #ccc;}
32 | }
33 | .coupon_btn_use {background-color: #999;color: #fff;}
34 | }
35 | }
36 | &_tit {
37 | width: 129px;
38 | height: 10px;
39 | margin: 0 auto;
40 | background: url('https://static.360buyimg.com/tp-statics/2018-4-17/m/img/coupon_toplife.png') no-repeat;
41 | background-size: 100% 100%;
42 | }
43 | &_value {
44 | color: #c4a66a;
45 | font-size: 30px;
46 | font-style: italic;
47 | font-weight: 300;
48 | margin-top: 35px;
49 |
50 | text {font-size: 70px;font-weight: 400;}
51 | }
52 | &_need_money,
53 | &_limit,
54 | &_time,
55 | &_btn_use {
56 | font-size: 24px;
57 | font-weight: 300;
58 | }
59 | &_need_money {
60 | color: #c4a66a;
61 | text {
62 | padding: 0 16px;
63 | }
64 | &::before,
65 | &::after {
66 | width: 7px;
67 | height: 7px;
68 | background-color: #c4a66a;
69 | display: inline-block;
70 | content: "";
71 | vertical-align: middle;
72 | transform: rotate(45deg);
73 | }
74 | }
75 | &_limit,
76 | &_time {
77 | transform: scale(0.8);
78 | }
79 | &_limit {
80 | margin-top: 30px;
81 | }
82 | &_btn_use {
83 | width: 200px;
84 | height: 50px;
85 | line-height: 50px;
86 | margin: 0 auto;
87 | background-color: #232321;
88 | color: #fff;
89 | position: relative;
90 | top: 36px;
91 | }
92 | &_btn_check {
93 | text-align: center;
94 | font-size: 26px;
95 | font-weight: 300;
96 | color: #232321;
97 | margin: 60px 0 30px;
98 | &::after {
99 | width: 26px;
100 | height: 16px;
101 | display: inline-block;
102 | content: '';
103 | background-repeat: no-repeat;
104 | background-image: url('https://static.360buyimg.com/tp-statics/2018-4-17/m/img/ic_coupon_downarrow_black@2x.png');
105 | background-size: 100% 100%;
106 | margin-left: 10px;
107 | }
108 |
109 | &.open {
110 | &::after {
111 | background-repeat: no-repeat;
112 | background-image: url('https://static.360buyimg.com/tp-statics/2018-4-17/m/img/ic_coupon_uparrow_black@2x.png');
113 | background-size: 100% 100%;
114 | }
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/gb/modal/modal.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Button } from '@tarojs/components'
3 |
4 | import './modal.scss'
5 |
6 | class Modal extends Component {
7 | constructor() {
8 | super(...arguments)
9 | this.state = {}
10 | }
11 |
12 | onConfirmClick = () => {
13 | this.props.onConfirmCallback()
14 | }
15 |
16 | onCancelClick = () => {
17 | this.props.onCancelCallback()
18 | }
19 |
20 | onAuthConfirmClick = (e) => {
21 | this.props.onConfirmCallback(e.detail)
22 | }
23 |
24 | preventTouchMove = (e) => {
25 | e.stopPropagation()
26 | }
27 |
28 | render() {
29 | const { title, contentText, cancelText, confirmText, isAuth } = this.props
30 | return (
31 |
32 |
33 | {title}
34 | {contentText}
35 |
36 |
37 | {!isAuth ?
38 | :
39 | }
40 |
41 |
42 |
43 | )
44 | }
45 | }
46 |
47 | Modal.defaultProps = {
48 | title: '',
49 | contentText: '',
50 | cancelText: '取消',
51 | confirmText: '确定',
52 | isAuth: false,
53 | onCancelCallback: () => {},
54 | onConfirmCallback: () => {}
55 | }
56 |
57 | export default Modal
58 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/gb/modal/modal.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | .toplife_modal {
4 | position: fixed;
5 | width: 100%;
6 | height: 100%;
7 | left: 0;
8 | top: 0;
9 | background-color: rgba(0,0,0,.8);
10 | z-index: 100;
11 | &_content {
12 | position: absolute;
13 | left: 50%;
14 | top: 50%;
15 | width: 600px;
16 | height: 320px;
17 | transform: translate(-50%, -50%);
18 | background-color: #fff;
19 | color: #232321;
20 | text-align: center;
21 | border-radius: 30px;
22 | }
23 | &_title {
24 | margin-top: 40px;
25 | font-size: 32px;
26 | }
27 | &_text{
28 | margin-top: 40px;
29 | font-size: 24px;
30 | }
31 | &_btn {
32 | position: absolute;
33 | bottom: 0;
34 | left: 0;
35 | width: 100%;
36 | height: 88px;
37 | border-top: 2px solid #eee;
38 | &_cancel {
39 | color: #8c8c8c;
40 | border-radius: 0;
41 | border: 0;
42 | border-right: 2px solid #eee;
43 | border-bottom-left-radius: 30px;
44 | }
45 | &_confirm {
46 | color: #666;
47 | border-radius: 0;
48 | border: 0;
49 | border-bottom-right-radius: 30px;
50 | }
51 | button {
52 | display: block;
53 | float: left;
54 | width: 50%;
55 | height: 88px;
56 | text-align: center;
57 | line-height: 88px;
58 | font-size: 32px;
59 | box-sizing: border-box;
60 | background-color: #fff;
61 | &::after {
62 | border: 0;
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/gb/select_panel/select_panel.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Text, Button } from '@tarojs/components'
3 | import classnames from 'classnames'
4 |
5 | import './select_panel.scss'
6 |
7 | export default class SelectPanel extends Component {
8 | constructor () {
9 | super(...arguments)
10 | this.state = {
11 | isShow: true,
12 | selectedIndex: -1,
13 | selectedDetail: null
14 | }
15 | }
16 |
17 | closePanel = () => {
18 | this.setState({
19 | isShow: false
20 | })
21 | }
22 |
23 | confirmSelect = () => {
24 | if (this.state.selectedIndex !== -1) {
25 | this.setState({
26 | isShow: false
27 | }, () => {
28 | this.props.onSelected && this.props.onSelected(this.state.selectedDetail)
29 | })
30 | }
31 | }
32 |
33 | seleted (index, item) {
34 | this.setState({
35 | selectedIndex: index,
36 | selectedDetail: item
37 | })
38 | }
39 |
40 | onAnimationEnd = () => {
41 | if (!this.state.isShow) {
42 | this.setState({
43 | isShow: true,
44 | selectedIndex: -1,
45 | selectedDetail: null
46 | })
47 | this.props.onClose && this.props.onClose()
48 | }
49 | }
50 |
51 | touchMove = (e) => {
52 | e && e.stopPropagation()
53 | }
54 |
55 | render () {
56 | const { detail = [], title, tips, subTitle, cancelBtnText, confirmBtnText } = this.props
57 | const selectPanelClassName = classnames('select_panel', !this.state.isShow && 'hide')
58 | const confirmDisable = this.state.selectedIndex === -1
59 |
60 | return (
61 |
62 |
63 |
64 |
65 | {title}
66 |
67 |
68 |
69 |
70 | {tips.map(item => {
71 | return {item}
72 | })}
73 |
74 |
75 |
76 | {subTitle}
77 |
78 |
79 | {detail.map((item, index) => {
80 | return (
81 |
82 |
83 | {item.desc}
84 |
85 |
86 | )
87 | })}
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | )
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/gb/select_panel/select_panel.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | .select_panel {
4 | position: fixed;
5 | top: 0;
6 | left: 0;
7 | z-index: 10;
8 | width: 100%;
9 | height: 100%;
10 | &.hide {
11 | .select_panel_mask {
12 | animation-name: hidePanelMask;
13 | }
14 | .select_panel_wrapper {
15 | animation-name: hideDetailWrapper;
16 | }
17 | }
18 | &_mask {
19 | position: fixed;
20 | top: 0;
21 | left: 0;
22 | width: 100%;
23 | height: 100%;
24 | background-color: rgba(0,0,0,.6);
25 | z-index: 11;
26 | opacity: 0;
27 | animation-name: showPanelMask;
28 | animation-duration: .3s;
29 | animation-timing-function: ease-in-out;
30 | animation-fill-mode: forwards;
31 | }
32 | &_wrapper {
33 | position: fixed;
34 | bottom: 0;
35 | left: 0;
36 | width: 100%;
37 | background-color: #FFFFFF;
38 | padding-bottom: 100px;
39 | z-index: 12;
40 | box-sizing: border-box;
41 | transform: translateY(100%);
42 | opacity: 0;
43 | animation-name: showDetailWrapper;
44 | animation-duration: .3s;
45 | animation-timing-function: ease-in-out;
46 | animation-fill-mode: forwards;
47 | }
48 | &_hd {
49 | line-height: 112px;
50 | text-align: center;
51 | font-size: 32px;
52 | color: #666;
53 | }
54 | &_tip {
55 | padding: 14px 35px;
56 | background-color: #ddd3b3;
57 | color: #fff;
58 | line-height: 42px;
59 | font-size: 24px;
60 | margin: 0 40px;
61 | }
62 | &_sub {
63 | height: 106px;
64 | border-bottom: 2px solid #ddd;
65 | font-size: 28px;
66 | margin: 0 40px;
67 | &_tit {
68 | display: inline-block;
69 | border-bottom: 4px solid #232321;
70 | line-height: 102px;
71 | }
72 | }
73 | &_detail {
74 | max-height: 546px;
75 | overflow-y: auto;
76 | padding-bottom: 20px;
77 | &_item {
78 | font-size: 24px;
79 | line-height: 74px;
80 | &.selected {
81 | background-color: #232321;
82 | color: #FFFFFF
83 | }
84 | }
85 | &_inner {
86 | padding: 0 40px;
87 | }
88 | }
89 | &_ft {
90 | display: flex;
91 | background: #232321;
92 | position: absolute;
93 | left: 0;
94 | bottom: 0;
95 | width: 100%;
96 | &_btn {
97 | width: 100%;
98 | flex: 1;
99 | line-height: 100px;
100 | font-size: 28px;
101 | color: #FFFFFF;
102 | background: #232321;
103 | border: 0;
104 | border-radius: 0;
105 | &.disabled {
106 | color: rgba(255, 255, 255, .4);
107 | }
108 | }
109 | &_split {
110 | width: 1px;
111 | height: 30px;
112 | background: #3b3b3b;
113 | margin-top: 35px;
114 | }
115 | }
116 | }
117 |
118 | @keyframes showPanelMask {
119 | 0% { opacity: 0; }
120 | 100% { opacity: 1; }
121 | }
122 |
123 | @keyframes showDetailWrapper {
124 | 0% { opacity: 0; transform: translateY(100%) }
125 | 100% { opacity: 1; transform: translateY(0) }
126 | }
127 |
128 | @keyframes hidePanelMask {
129 | 0% { opacity: 1; }
130 | 100% { opacity: 0; }
131 | }
132 |
133 | @keyframes hideDetailWrapper {
134 | 0% { opacity: 1; transform: translateY(0) }
135 | 100% { opacity: 0; transform: translateY(100%) }
136 | }
137 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/_mixin.scss:
--------------------------------------------------------------------------------
1 | .search_not_see{
2 | display: none;
3 | }
4 | .search_not_see_ani{
5 | opacity: 0;
6 | }
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchBar.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Input, Text, Image } from '@tarojs/components'
3 |
4 | import searchIcon from '../../asset/ic_search.png'
5 | import cartIcon from '../../asset/shopping_cart.png'
6 | import searchDel from '../../asset/ic_del.png'
7 | import './searchBar.scss'
8 | import { jumpUrl } from '../../utils/util'
9 |
10 | export default class SearchBar extends Component {
11 |
12 | state = {
13 | words: '',
14 | focusSearch: false
15 | }
16 |
17 | componentWillReceiveProps (nextProps) {
18 | if (this.props.keyWords !== nextProps.keyWords || this.state.words === '') {
19 | this.setState({
20 | words: nextProps.keyWords
21 | })
22 | }
23 | }
24 |
25 | onSearchInput = ({detail = {}}) => {
26 | if (!detail.value) {
27 | return
28 | }
29 | this.setState({
30 | words: detail.value
31 | })
32 | }
33 |
34 | onH5Enter = (e) => {
35 | const key = e.key
36 | const value = e.target.value
37 | if (key === 'Enter') {
38 | this.props.onAddHistory({value: value, type: 'add'})
39 | this.props.onSearchWords({keyWords: value})
40 | }
41 | }
42 |
43 | onFocusSearch = () => {
44 | this.props.onShowSearchResult({type: 'result', isShow: false})
45 | }
46 |
47 | deleteHandler = () => {
48 | this.setState({
49 | words: ''
50 | })
51 | }
52 | cancelSearch = () => {
53 | this.props.onShowSearchResult({type: 'result', isShow: true})
54 | }
55 | goSearch = ({detail}) => {
56 | if (detail.value !== '') {
57 | this.props.onAddHistory({value: detail.value, type: 'add'})
58 | this.props.onSearchWords({keyWords: detail.value})
59 | }
60 | }
61 |
62 | goCart () {
63 | jumpUrl('../cart/cart_sub')
64 | }
65 |
66 | render () {
67 | const {showSearchResult = false} = this.props
68 | const {words} = this.state
69 | const carNumber = 99
70 | return (
71 |
72 |
73 |
74 |
75 |
76 |
77 |
88 |
92 |
93 |
94 |
95 |
96 |
97 |
98 | {carNumber}
99 |
100 |
101 |
105 | 取消
106 |
107 |
108 |
109 | )
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchBar.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 | /*postcss-pxtransform rn eject disable*/
3 | @import './_mixin.scss';
4 |
5 | .search_container {
6 | display: flex;
7 | flex-shrink: 0;
8 | background-color: #fff;
9 | height: 80px;
10 | overflow: hidden;
11 | width: 100%;
12 | }
13 |
14 | .search_container_box {
15 | display: flex;
16 | flex: 1;
17 | flex-direction: row;
18 | padding: 0 40px;
19 | background-color: #fff;
20 | height: 80px;
21 | align-items: center;
22 | z-index: 100;
23 | }
24 |
25 | .search_container_box-search_box {
26 | display: flex;
27 | flex: 1;
28 | flex-direction: row;
29 | position: relative;
30 | height: 60px;
31 | align-items: center;
32 | background-color: #eee;
33 | opacity: 0.5;
34 | }
35 |
36 | .search_container_box-search_icon-wrap {
37 | display: flex;
38 | margin: 0 16px;
39 | }
40 |
41 | .search_container_box-search_icon {
42 | width: 30px;
43 | height: 30px;
44 | }
45 |
46 | .search_container_box-search_input {
47 | display: flex;
48 | flex: 1;
49 | height: 60px;
50 | border: 0;
51 | font-size: 24px;
52 | z-index: 20;
53 | background-color: #eee;
54 | }
55 |
56 | .search_container_box-search_del {
57 | position: absolute;
58 | right: 0;
59 | top: 0;
60 | z-index: 101;
61 | display: flex;
62 | align-items: center;
63 | background-color: #eee;
64 | justify-content: center;
65 | width: 100px;
66 | height: 60px;
67 | }
68 |
69 | .search_container_box-search_del_icon {
70 | display: flex;
71 | width: 30px;
72 | height: 30px;
73 | }
74 |
75 | .search_container_box-search_show_cancel {
76 | //font-size: 32px;
77 | //color: #232321;
78 | padding-left: 20px;
79 | }
80 |
81 | .search_container_box-search_show_cart {
82 | position: relative;
83 | margin-left: 20px;
84 | }
85 |
86 | .search_container_box-cart_icon {
87 | width: 48px;
88 | height: 48px;
89 | display: flex;
90 | }
91 |
92 | .search_container_box-cart_num_wrap {
93 | display: flex;
94 | position: absolute;
95 | top: -10px;
96 | right: -10px;
97 | width: 34px;
98 | height: 30px;
99 | background-color: #c0a369;
100 | border-radius: 50px;
101 | align-items: center;
102 | justify-content: center;
103 | }
104 |
105 | .search_container_box-cart_num {
106 | line-height: 30px;
107 | font-size: 18px;
108 | color: #fff;
109 | }
110 |
111 |
112 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchFilter/searchFilter.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Text } from '@tarojs/components'
3 |
4 | import FilterMask from './filterMask'
5 | import './searchFilter.scss'
6 |
7 | export default class SearchFilter extends Component {
8 |
9 | constructor () {
10 | super(...arguments)
11 | this.state = {
12 | isClick: true,
13 | sortContent: [
14 | {
15 | label: '综合',
16 | value: 1,
17 | cName: 'result_filter_btn'
18 | },
19 | {
20 | label: '最新',
21 | value: 4,
22 | cName: 'result_filter_btn'
23 | },
24 | {
25 | label: '价格',
26 | value: 2,
27 | cName: 'result_filter_btn price_btn'
28 | }
29 | ],
30 | sortType: 1,
31 | showFilterMask: false,
32 | currentIndex: 0,
33 | filterObj: {}
34 | }
35 | this.allListData = []
36 | }
37 |
38 | selectFilter = async (index, value) => {
39 |
40 | Taro.pageScrollTo({
41 | scrollTop: 0
42 | })
43 | let {sortContent, isClick, currentIndex} = this.state
44 | let currentValue = parseInt(value, 10)
45 | if (currentValue === 2 || currentValue === 3) {
46 | currentIndex = 2
47 | if (isClick) {
48 | this.setState({
49 | isClick: false
50 | })
51 | } else {
52 | currentValue = currentValue === 2 ? 3 : 2
53 | sortContent[2].value = currentValue
54 | }
55 | } else {
56 | currentIndex = parseInt(index, 10)
57 | sortContent[2].value = 2
58 | this.setState({
59 | isClick: true,
60 | sortContent
61 | })
62 | }
63 | this.setState({
64 | sortType: currentValue,
65 | currentIndex,
66 | sortContent
67 | })
68 | this.goSearchContent()
69 | }
70 |
71 | confirmSelect = (data = {}) => {
72 | this.setState({
73 | filterObj: data
74 | })
75 | this.goSearchContent()
76 | }
77 |
78 | goSearchContent = () => {
79 | const {filterObj, sortType} = this.state
80 | this.props.onGoSearchContent({sortType, ...filterObj})
81 | }
82 |
83 | showFilterMask = () => {
84 | console.log('showFilterMask')
85 | this.setState({
86 | showFilterMask: !this.state.showFilterMask
87 | })
88 | }
89 |
90 | render () {
91 | const {
92 | sortContent,
93 | sortType,
94 | currentIndex,
95 | showFilterMask
96 | } = this.state
97 | const list = sortContent.map((item) => {
98 | const cNameItem = sortType === 2 ? (item.cName + ' top') : (sortType === 3 ? (item.cName + ' bottom') : item.cName)
99 | return {
100 | ...item,
101 | cName: cNameItem
102 | }
103 | })
104 | return (
105 |
106 |
107 | {
108 | list.map((item, index) => {
109 | return (
110 |
115 | {item.label}
116 |
117 | )
118 | })
119 | }
120 | 筛选
121 |
122 | {
123 |
128 | }
129 |
130 | )
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchFilter/searchFilter.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | .search_filter_content .price_btn::after {
4 | content: "";
5 | display: block;
6 | width: 0;
7 | height: 0;
8 | background: rgba(0, 0, 0, 0);
9 | border-left: 8px solid transparent;
10 | border-right: 8px solid transparent;
11 | border-bottom: 8px solid #bbb;
12 | position: absolute;
13 | right: 32px;
14 | top: 26px;
15 | }
16 |
17 | .search_filter_content .price_btn::before {
18 | content: "";
19 | display: block;
20 | width: 0;
21 | height: 0;
22 | background: rgba(0, 0, 0, 0);
23 | border-left: 8px solid transparent;
24 | border-right: 8px solid transparent;
25 | border-top: 8px solid #bbb;
26 | position: absolute;
27 | right: 32px;
28 | top: 40px;
29 | }
30 |
31 | .search_filter_content .top::after {
32 | border-bottom: 8px solid #c0a369;
33 | }
34 |
35 | /*postcss-pxtransform rn eject disable*/
36 |
37 | .search_filter {
38 | border-width: 0 0 2px 0;
39 | border-bottom-color: #eee;
40 | border-style: solid;
41 | }
42 |
43 | .search_filter_content {
44 | height: 80px;
45 | display: flex;
46 | align-items: center;
47 | background-color: #fff;
48 | flex-direction: row;
49 | justify-content: center;
50 | }
51 |
52 | .search_filter {
53 | height: 80px;
54 | }
55 |
56 | .result_filter_btn {
57 | height: 80px;
58 | line-height: 80px;
59 | background-color: #fff;
60 | font-size: 24px;
61 | flex: 1;
62 | text-align: center;
63 | position: relative;
64 | }
65 |
66 | .search_filter_content_active {
67 | color: #c0a369;
68 | }
69 |
70 | .search_filter_content .bottom::before {
71 | border-top: 8px solid #c0a369;
72 | }
73 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchHistory.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Image, Text } from '@tarojs/components'
3 |
4 | import delIcon from '../../asset/ic_del.png'
5 | import './searchHistory.scss'
6 |
7 | export default class SearchHistory extends Component {
8 |
9 | componentDidMount () {
10 |
11 | }
12 |
13 | goSearch (value = '') {
14 | if (value) {
15 | this.props.onChangeHistory({value, type: 'add'})
16 | this.props.onSearchWords({keyWords: value})
17 | }
18 | // let url = `../list/list?words=${value}`
19 | // jumpUrl(url, {method: 'redirectTo'})
20 |
21 | }
22 |
23 | deleteSearch (value) {
24 | this.props.onChangeHistory({value, type: 'delete'})
25 | }
26 |
27 | render () {
28 | const {historyWords = []} = this.props
29 | return (
30 | historyWords.length > 0 &&
31 |
32 |
33 | 历史搜索
34 |
35 |
36 | {
37 | historyWords.map((item, index) => {
38 | return (
39 |
40 |
44 | {item}
45 |
46 |
53 |
54 |
55 | )
56 | })
57 | }
58 |
59 |
60 | )
61 | }
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchHistory.scss:
--------------------------------------------------------------------------------
1 | .history {
2 | margin-top: 20px;
3 | background-color: #fff;
4 | }
5 |
6 | .history_title {
7 | padding: 40px;
8 | border-width: 0 0 1px 0;
9 | border-style: solid;
10 | border-bottom-color: #ddd;
11 | }
12 |
13 | .history_title_content {
14 | color: #232321;
15 | font-size: 28px;
16 | font-weight: 600;
17 | display: flex;
18 | }
19 |
20 | .history_word {
21 | display: flex;
22 | flex-direction: row;
23 | border-style: solid;
24 | border-bottom-color: #ddd;
25 | border-width: 0 0 1px 0;
26 | }
27 |
28 | .history_word_info {
29 | font-size: 28px;
30 | padding: 40px;
31 | flex: 1;
32 | }
33 |
34 | .history_word_del {
35 | margin: 48px 40px 0;
36 | width: 26px;
37 | height: 26px;
38 | display: flex;
39 | }
40 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchHot.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Text } from '@tarojs/components'
3 |
4 | import './searchHot.scss'
5 |
6 | const DEFAULT_TITLE = '热门搜索'
7 | export default class SearchHot extends Component {
8 |
9 | goSearch = (value = '') => {
10 | if (value) {
11 | this.props.onAddHistory({value, type: 'add'})
12 | this.props.onSearchWords({keyWords: value})
13 | }
14 | }
15 |
16 | render () {
17 | const {hotWords, titleName} = this.props
18 | return (
19 | hotWords.length > 0 &&
20 |
21 | {titleName}
22 |
23 | {
24 | hotWords.map((item, index) => {
25 | return (
26 |
31 | {item}
32 |
33 | )
34 | })
35 | }
36 |
37 |
38 | )
39 | }
40 | }
41 | SearchHot.defaultProps = {
42 | hotWords: [],
43 | titleName: DEFAULT_TITLE
44 | }
45 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchHot.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 | .hot_word-keyword {
3 | text-overflow: ellipsis;
4 | white-space: nowrap;
5 | }
6 |
7 | /*postcss-pxtransform rn eject disable*/
8 |
9 | .hot_word {
10 | margin-top: 20px;
11 | background-color: #fff;
12 | }
13 |
14 | .hot_word-title {
15 | padding: 40px 40px 30px;
16 | color: #232321;
17 | font-size: 28px;
18 | font-weight: 600;
19 | display: flex;
20 | }
21 |
22 | .hot_word-list {
23 | padding: 0 40px 40px;
24 | display: flex;
25 | flex-direction: row;
26 | }
27 |
28 | .hot_word-keyword {
29 | color: #191919;
30 | font-size: 28px;
31 | border: 1px solid #ddd;
32 | height: 52px;
33 | line-height: 52px;
34 | padding: 0 30px;
35 | margin: 0 16px 16px 0;
36 | display: flex;
37 | max-width: 100%;
38 | overflow: hidden;
39 | }
40 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchInto.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Text, Image } from '@tarojs/components'
3 | import searchIcon from '../../asset/ic_search.png'
4 | import './searchInto.scss'
5 | import { jumpUrl } from '../../utils/util'
6 |
7 | const DEFAULT_PLACEHOLDER = '探索你的精致生活'
8 |
9 | export default class SearchInto extends Component {
10 | handler = () => {
11 | console.log('类型:' + this.props.type)
12 | }
13 | goSearch = () => {
14 | console.log('goSearch')
15 | jumpUrl(`/pages/list/list`)
16 | }
17 |
18 | render () {
19 | const {placeholder} = this.props
20 | return (
21 |
22 |
23 | {placeholder}
24 |
25 | )
26 | }
27 | }
28 |
29 | SearchInto.defaultProps = {
30 | placeholder: DEFAULT_PLACEHOLDER
31 | }
32 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchInto.scss:
--------------------------------------------------------------------------------
1 | .search_into {
2 | display: flex;
3 | flex-direction: row;
4 | height: 60px;
5 | background-color: #f6f6f6;
6 | width: 610px;
7 | justify-content: center;
8 | align-items: center;
9 | }
10 |
11 | .search_box {
12 | height: 60px;
13 | background-color: #f6f6f6;
14 | display: flex;
15 | flex: 1;
16 | flex-direction: row;
17 | justify-content: center;
18 | align-items: center;
19 | }
20 |
21 | .search_icon {
22 | width: 30px;
23 | height: 30px;
24 | }
25 |
26 | .search_text {
27 | height: 60px;
28 | line-height: 60px;
29 | color: #999;
30 | font-size: 28px;
31 | }
32 |
33 | .search_not_show {
34 | display: none;
35 | }
36 |
37 | .small.search_into {
38 | padding: 0 0 0 40px;
39 | width: 600px;
40 | }
41 |
42 | .small.search_into .search_box {
43 | text-align: left;
44 | }
45 |
46 | .small.search_into .search_icon {
47 | margin: 0 23px 0 28px;
48 | }
49 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchResult/resultList.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Image, Text, ScrollView } from '@tarojs/components'
3 |
4 | import { jumpUrl } from '../../../utils/util'
5 | import './resultList.scss'
6 |
7 | export default class ResultList extends Component {
8 |
9 | constructor () {
10 | super(...arguments)
11 |
12 | this.state = {
13 | list: []
14 | }
15 | this.allListData = []
16 | this.currentMaxPage = 1 //当前大分页
17 | }
18 |
19 | componentDidMount () {
20 | Taro.getSystemInfo({
21 | success: (res) => {
22 | console.log(res)
23 | }
24 | })
25 | }
26 |
27 | componentWillReceiveProps (nextProps) {
28 | const {searchResult, scrollTop} = nextProps
29 | if (searchResult.page < 10) {
30 | this.allListData = searchResult.wares
31 | this.setState({
32 | list: searchResult.wares
33 | })
34 | } else if (searchResult.page > 9 && nextProps.searchResult.page !== searchResult.page) {
35 | this.allListData = this.allListData.concat(searchResult.wares)
36 | let list = this.allListData
37 | if (searchResult.page % 10 === 0) {
38 | this.currentMaxPage = page
39 | }
40 | if (searchResult.page > 9) {
41 | list = this.allListData.slice((this.currentMaxPage - 2) * 10, (searchResult.page + 8) * 10)
42 | }
43 | this.setState({
44 | list
45 | })
46 | } else if (scrollTop < 1000 && searchResult.page > 9) {
47 | this.setState({
48 | list: this.allListData.slice((this.currentMaxPage - 9) * 10, (searchResult.page) * 10)
49 | })
50 | } else if (scrollTop > 1500 * 10 && searchResult.page > 9) {
51 | this.setState({
52 | list: this.allListData.slice((this.currentMaxPage - 2) * 10, (searchResult.page + 10) * 10)
53 | })
54 | }
55 | }
56 |
57 | doJump (skuid) {
58 | jumpUrl(`/pages/detail/detail?skuid=${skuid}`)
59 | }
60 |
61 | srollToTop () {
62 | Taro.pageScrollTo({
63 | scrollTop: 0,
64 | duration: 400
65 | })
66 | }
67 |
68 | showFilter = () => {
69 | this.props.onShowFilter({type: 'filter', isShow: true})
70 | }
71 |
72 | render () {
73 | const {
74 | list
75 | } = this.state
76 | const {searchResult = {}, showGoTop = false} = this.props
77 | const resultList = list.map((item, index) => {
78 | return (
79 |
84 |
85 |
91 |
92 | {item.skuName || ''}
93 | {item.name}
94 |
95 | {
96 | item.price && item.price !== '-1' &&
97 | ¥
98 | }
99 | {item.price && item.price !== '-1' ? item.price : '暂无报价'}
100 |
101 |
102 | )
103 | })
104 |
105 | return list.length > 0 && (
106 |
107 |
108 |
109 | {resultList}
110 |
111 |
112 |
113 |
114 | 没有更多商品了~
115 | searchResult.page * 10 ? 'has_not_more' : 'search_not_see'}>正在加载中...
116 |
117 |
118 | )
119 | }
120 | }
121 |
122 | ResultList.defaultProps = {
123 | searchResult: {
124 | wares: [],
125 | page: 1
126 | },
127 | showGoTop: false
128 | }
129 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchResult/resultList.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | .result_content-item_subtitle {
4 | overflow: hidden;
5 | text-overflow: ellipsis;
6 | display: -webkit-box;
7 | word-break: break-all;
8 | }
9 |
10 | .search_result-go_top {
11 | background: #232321;
12 | opacity: 0.8;
13 | width: 86px;
14 | height: 86px;
15 | position: fixed;
16 | z-index: 100;
17 | right: 30px;
18 | bottom: 150px;
19 | border-radius: 50%;
20 | transition: opacity 0.3s ease-in-out;
21 | display: flex;
22 | align-items: center;
23 | justify-content: center;
24 | }
25 |
26 | .search_result-go_to_arrow {
27 | width: 20px;
28 | height: 20px;
29 | border-right: 2px solid #fff;
30 | border-bottom: 2px solid #fff;
31 | transform: rotate(-135deg);
32 | margin-top: 11px;
33 | }
34 |
35 | /*postcss-pxtransform rn eject disable*/
36 |
37 | @import '../_mixin.scss';
38 |
39 | .search_result-scroll {
40 | flex-grow: 1;
41 | }
42 |
43 | .search_result-result_content {
44 | background-color: #fff;
45 | }
46 |
47 | .result_content_list {
48 | display: flex;
49 | flex-direction: row;
50 | flex-wrap: wrap;
51 | }
52 |
53 | .result_content-item {
54 | display: flex;
55 | flex: 1;
56 | flex-basis: 50%;
57 | flex-direction: column;
58 | margin: 30px 0;
59 | height: 610px;
60 | position: relative;
61 | }
62 |
63 | .result_content-item_img {
64 | width: 310px;
65 | height: 390px;
66 | overflow: hidden;
67 | position: relative;
68 | margin: 0 30px;
69 | }
70 |
71 | .item_img_info {
72 | width: 310px;
73 | height: 390px;
74 | }
75 |
76 | .search_result .result_content .result_content_item .item_img .item_sold_out {
77 | position: absolute;
78 | top: 0;
79 | left: 0;
80 | width: 100%;
81 | height: 100%;
82 | z-index: 5;
83 | background-color: #fff;
84 | opacity: 0.75;
85 | display: flex;
86 | justify-content: center;
87 | align-items: center;
88 | }
89 |
90 | .search_result .result_content .result_content_item .item_img .item_sold_out .sold_out_text {
91 | background-color: #000;
92 | opacity: 0.75;
93 | color: #fff;
94 | text-align: center;
95 | width: 35%;
96 | font-size: 24px;
97 | height: 40px;
98 | line-height: 40px;
99 | }
100 |
101 | .result_content-item_title {
102 | padding: 0 30px;
103 | font-size: 26px;
104 | height: 80px;
105 | line-height: 80px;
106 | overflow: hidden;
107 | }
108 |
109 | .result_content-item_subtitle {
110 | padding: 0 30px;
111 | height: 84px;
112 | line-height: 42px;
113 | font-size: 24px;
114 | color: #322d2d;
115 | }
116 |
117 | .result_content-item_price {
118 | font-size: 32px;
119 | padding: 0 30px;
120 | height: 50px;
121 | line-height: 50px;
122 | color: #222;
123 | overflow: hidden;
124 | }
125 |
126 | .result_content-item_price_unit {
127 | font-size: 16px;
128 | }
129 |
130 | .search_result .result_content .result_content_item .item_price_old {
131 | color: #aaa;
132 | }
133 |
134 | .search_result .result_content .result_content_item .item_price_old .price_old_num {
135 | text-decoration: line-through;
136 | }
137 |
138 | .search_result .show_current_page {
139 | position: fixed;
140 | bottom: 170px;
141 | text-align: center;
142 | z-index: 100;
143 | width: 100%;
144 | animation: slide_in 0.3s ease-in-out;
145 | }
146 |
147 | .search_result .show_current_page .current_page_text {
148 | font-size: 28px;
149 | background: #232321;
150 | opacity: 0.8;
151 | color: #fff;
152 | display: block;
153 | height: 44px;
154 | line-height: 44px;
155 | width: 104px;
156 | margin: 0 auto;
157 | }
158 |
159 | .search_result .slide_out {
160 | display: none;
161 | }
162 |
163 | .not_see_go {
164 | opacity: 0;
165 | }
166 |
167 | .has_not_more {
168 | background-color: #fff;
169 | text-align: center;
170 | display: flex;
171 | justify-content: center;
172 | width: 100%;
173 | padding-bottom: 40px;
174 | font-size: 24px;
175 | color: #322d2d;
176 | }
177 |
178 | @keyframes slide_in {
179 | 0% {
180 | opacity: 0;
181 | }
182 | 100% {
183 | opacity: 1;
184 | }
185 | }
186 |
187 | @keyframes slide_out {
188 | 0% {
189 | opacity: 1;
190 | }
191 | 100% {
192 | opacity: 0;
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchResult/searchError.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Image, Text } from '@tarojs/components'
3 |
4 | import './searchError.scss'
5 | import errIcon from '../../../asset/ic_search_tips.png'
6 |
7 | export default class SearchError extends Component {
8 |
9 | async refresh () {
10 | this.props.onGoSearchContent()
11 | }
12 |
13 | render () {
14 | const {showNotFind, keyWords, showErrorProblem} = this.props
15 | const words = /^.*[,].*$/.test(keyWords) ? '' : keyWords
16 | const showWordsTips = `没有找到与“${words} 相关的商品`
17 |
18 | return (
19 |
20 |
21 | 很抱歉
22 | {
23 | !showErrorProblem && showNotFind &&
24 | {showWordsTips}
25 | }
26 | {
27 | showErrorProblem &&
28 |
29 | 程序员可能送货去了
30 | 刷新试试
31 |
32 | }
33 |
34 | )
35 | }
36 | }
37 | SearchError.defaultProps = {
38 | showNotFind: false,
39 | keyWords: '',
40 | showErrorProblem: false
41 | }
42 |
--------------------------------------------------------------------------------
/taro-demo/client/src/components/search/searchResult/searchError.scss:
--------------------------------------------------------------------------------
1 | .search_not_found {
2 | display: flex;
3 | flex: 1;
4 | flex-direction: column;
5 | align-items: center;
6 | justify-content: center;
7 | width: 100%;
8 | background-color: #f4f1f1;
9 | }
10 |
11 | .not_found_img {
12 | width: 160px;
13 | height: 160px;
14 | margin-top: -40%;
15 | }
16 |
17 | .not_found_text {
18 | font-size: 28px;
19 | margin-top: 20px;
20 | color: #666;
21 | }
22 |
23 | .not_found_word {
24 | font-size: 24px;
25 | margin-top: 10px;
26 | color: #999;
27 | }
28 |
29 | .not_found_btn {
30 | font-size: 24px;
31 | color: #232321;
32 | width: 204px;
33 | height: 48px;
34 | line-height: 48px;
35 | text-align: center;
36 | margin: 30px auto 0;
37 | border: 1px solid #232321;
38 | }
39 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/balance.js:
--------------------------------------------------------------------------------
1 | export const REQUEST_BALANCE_INFO = 'REQUEST_BALANCE_INFO'
2 | export const RECEIVE_BALANCE_INFO = 'RECEIVE_BALANCE_INFO'
3 |
4 | export const REQUEST_BALANCE_ORDER = 'REQUEST_BALANCE_ORDER'
5 | export const RECEIVE_BALANCE_ORDER = 'RECEIVE_BALANCE_ORDER'
6 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/cart.js:
--------------------------------------------------------------------------------
1 | export const REQUEST_CART = 'REQUEST_CART'
2 | export const RECEIVE_CART = 'RECEIVE_CART'
3 |
4 | export const REQUEST_DEL_CART = 'REQUEST_DEL_CART'
5 | export const RECEIVE_DEL_CART = 'RECEIVE_DEL_CART'
6 |
7 | export const REQUEST_CHANGE_NUM = 'REQUEST_CHANGE_NUM'
8 | export const RECEIVE_CHANGE_NUM = 'RECEIVE_CHANGE_NUM'
9 |
10 | export const REQUEST_CHECK_CART = 'REQUEST_CHECK_CART'
11 | export const RECEIVE_CHECK_CART = 'RECEIVE_CHECK_CART'
12 |
13 | export const REQUEST_INVERSE_CHECK = 'REQUEST_INVERSE_CHECK'
14 | export const RECEIVE_INVERSE_CHECK = 'RECEIVE_INVERSE_CHECK'
15 |
16 | export const REQUEST_SKU_ATTR = 'REQUEST_SKU_ATTR'
17 | export const RECEIVE_SKU_ATTR = 'RECEIVE_SKU_ATTR'
18 |
19 | export const REQUEST_CHANGE_ATTR = 'REQUEST_CHANGE_ATTR'
20 | export const RECEIVE_CHANGE_ATTR = 'RECEIVE_CHANGE_ATTR'
21 |
22 | export const CHECK_DEL = 'CHECK_DEL'
23 | export const INVERSE_CHECK_DEL = 'INVERSE_CHECK_DEL'
24 |
25 | export const SHOW_ATTR_BOX = 'SHOW_ATTR_BOX'
26 | export const HIDE_ATTR_BOX = 'HIDE_ATTR_BOX'
27 |
28 | export const CHANGE_EDIT_STATUS = 'CHANGE_EDIT_STATUS'
29 |
30 | export const operate = {
31 | QUERY: '1',
32 | ADD: '2',
33 | CHANGE_NUM: '3',
34 | DEL: '4',
35 | CHECK: '5',
36 | INVERT_CHECK: '6',
37 | CHANGE_ATTR: '8',
38 | GET_NUM: '9'
39 | }
40 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/detail.js:
--------------------------------------------------------------------------------
1 | export const REQUEST_DETAIL_CART = 'REQUEST_DETAIL_CART'
2 | export const RECEIVE_DETAIL_CART = 'RECEIVE_DETAIL_CART'
3 |
4 | export const REQUEST_DETAIL_SKU = 'REQUEST_DETAIL_SKU'
5 | export const RECEIVE_DETAIL_SKU = 'RECEIVE_DETAIL_SKU'
6 |
7 | export const REQUEST_DETAIL_ADD_CART = 'REQUEST_DETAIL_ADD_CART'
8 | export const RECEIVE_DETAIL_ADD_CART = 'RECEIVE_DETAIL_ADD_CART'
9 |
10 | // export const REQUEST_CART = 'REQUEST_CART'
11 | // export const RECEIVE_CART = 'RECEIVE_CART'
12 |
13 | // export const REQUEST_CART = 'REQUEST_CART'
14 | // export const RECEIVE_CART = 'RECEIVE_CART'
15 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/globalData.js:
--------------------------------------------------------------------------------
1 | const globalData = {}
2 |
3 | export function setGlobalData (key, val) {
4 | globalData[key] = val
5 | }
6 |
7 | export function getGlobalData (key) {
8 | return globalData[key]
9 | }
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/home.js:
--------------------------------------------------------------------------------
1 | export const REQUEST_HOME = 'REQUEST_HOME'
2 | export const RECEIVE_HOME = 'RECEIVE_HOME'
3 | export const RECEIVE_HOME_ERROR = 'RECEIVE_HOME_ERROR'
4 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/images.js:
--------------------------------------------------------------------------------
1 | export const SEARCH_BAR_LIST_IMAGE = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAaElEQVRIx2NUVlb0ZGBgmMsAAcl3797fzkBHwAK1XBLKn8vAwCAFk1RWVvxPawcwofEZ6el7WAikQH3+l4GBIQ1Z8u7d+3R30CgYBSMPMI6WhOghQk/fw0JgtCQcBaNgQMFoSThaEgIAiY8mmPwztG0AAAAASUVORK5CYII='
2 | export const SEARCH_BAR_MORE_IMAGE = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAGCAYAAADUtS5UAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAlklEQVQoz8WRsQ6CMBRFD5X4S4Z/kTK5QjARWJyJ8gtO8jGELyJhAAeeSdOUIpNnvD19vekLouh0BBpAAxPQAkXX9SMODP8MBOLfNvwnEJt+KGFquJkUuOLmYfmp+PmKX8tM0x+UNLHRrKN3+okjuyj+hGL5c5vWc+f9Y+Y7e4VAwbJ0DczyaOkZVErh74q2/Ao4WP79A14CJJ7qixoSAAAAAElFTkSuQmCC'
3 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/order/detail.js:
--------------------------------------------------------------------------------
1 | export const REQUEST_ORDER_DETAIL = 'REQUEST_ORDER_DETAIL'
2 | export const RECEIVE_ORDER_DETAIL = 'RECEIVE_ORDER_DETAIL'
3 | export const RESET_ORDER_DETAIL = 'RESET_ORDER_DETAIL'
4 |
5 | export const REQUEST_ORDER_CANCEL = 'REQUEST_ORDER_CANCEL'
6 | export const RECEIVE_ORDER_CANCEL = 'RECEIVE_ORDER_CANCEL'
7 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/order/list.js:
--------------------------------------------------------------------------------
1 | export const REQUEST_ORDER_LIST = 'REQUEST_ORDER_LIST'
2 | export const RECEIVE_ORDER_LIST = 'RECEIVE_ORDER_LIST'
3 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/search.js:
--------------------------------------------------------------------------------
1 |
2 | export const SHOW_SEARCH_BAR = 'SHOW_SEARCH_BAR'
3 | export const REQUEST_SEARCH_RESULT = 'REQUEST_SEARCH_RESULT'
4 | export const RECEIVE_SEARCH_RESULT = 'RECEIVE_SEARCH_RESULT'
5 | export const RECEIVE_SEARCH_ERROR = 'RECEIVE_SEARCH_ERROR'
6 | export const SHOW_RESULT = 'SHOW_RESULT'
7 | export const CHANGE_HISTORY = 'CHANGE_HISTORY'
8 | export const SHOW_NOT_FIND = 'SHOW_NOT_FIND'
9 | export const RESET_STATE = 'RESET_STATE'
10 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/shop.js:
--------------------------------------------------------------------------------
1 | export const REQUEST_SHOP = 'REQUEST_SHOP'
2 | export const RECEIVE_SHOP = 'RECEIVE_SHOP'
3 | export const RESET_SHOP = 'RESET_SHOP'
4 | export const REQUEST_SUB_SHOP = 'REQUEST_SUB_SHOP'
5 | export const RECEIVE_SUB_SHOP = 'RECEIVE_SUB_SHOP'
6 | export const RESET_SUB_SHOP = 'RESET_SUB_SHOP'
7 | export const REQUEST_ACT = 'REQUEST_ACT'
8 | export const RECEIVE_ACT = 'RECEIVE_ACT'
9 | export const RESET_ACT = 'RESET_ACT'
10 | export const REQUEST_SHOP_CATE = 'REQUEST_SHOP_CATE'
11 | export const RECEIVE_SHOP_CATE = 'RECEIVE_SHOP_CATE '
12 | export const RESET_SHOP_CATE = 'RESET_SHOP_CATE '
13 |
--------------------------------------------------------------------------------
/taro-demo/client/src/constants/weapp.js:
--------------------------------------------------------------------------------
1 | export const APP_ID = 'wx5c394ae0cf4d8e32'
2 |
--------------------------------------------------------------------------------
/taro-demo/client/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | TARO商城
12 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/cart/editCart.js:
--------------------------------------------------------------------------------
1 | const AV = require('../index').default
2 | const { typeMap, getNewCartData } = require('./utils')
3 |
4 | function changCartNum (oldCartInfo, skus) {
5 | // 更新购物车中的商品数据
6 | const newCartInfo = oldCartInfo.map((item) => {
7 | const temp = skus.filter(sku => item.skuId === sku.skuId)[0]
8 | if (temp) {
9 | item.num = temp.num
10 | item.isCheck = true
11 | }
12 | return item
13 | })
14 |
15 | return newCartInfo
16 | }
17 |
18 | function addCart (oldCartInfo, skus) {
19 | skus.forEach((sku) => { sku.isCheck = true })
20 | let spliceIdx
21 | // 更新购物车中的商品数据
22 | let newCartInfo = oldCartInfo.map((item) => {
23 | const temp = skus.filter((sku, idx) => {
24 | if (item.skuId === sku.skuId) {
25 | spliceIdx = idx
26 | return true
27 | }
28 | })[0]
29 | if (temp) {
30 | skus.splice(spliceIdx, 1)
31 | item.num += temp.num
32 | item.isCheck = temp.isCheck
33 | item.size = temp.size
34 | item.color = temp.color
35 | }
36 |
37 | return item
38 | })
39 |
40 | return newCartInfo.concat(skus)
41 | }
42 |
43 | function delCart (oldCartInfo, skus) {
44 | const newCartInfo = oldCartInfo.filter((item) => {
45 | const temp = skus.filter(sku => { return item.skuId === sku.skuId })[0]
46 | return !temp
47 | })
48 |
49 | return newCartInfo
50 | }
51 |
52 | function checkCart (oldCartInfo, skus) {
53 | // 更新购物车中的商品数据
54 | const newCartInfo = oldCartInfo.map((item) => {
55 | const temp = skus.filter(sku => item.skuId === sku.skuId)[0]
56 | if (temp) {
57 | item.isCheck = true
58 | }
59 | return item
60 | })
61 |
62 | return newCartInfo
63 | }
64 |
65 | function inverseCheckCart (oldCartInfo, skus) {
66 | // 更新购物车中的商品数据
67 | const newCartInfo = oldCartInfo.map((item) => {
68 | const temp = skus.filter(sku => item.skuId === sku.skuId)[0]
69 | if (temp) {
70 | item.isCheck = false
71 | }
72 | return item
73 | })
74 |
75 | return newCartInfo
76 | }
77 |
78 | function changeAttr (oldCartInfo, skus) {
79 | // 更新购物车中的商品数据
80 | const newCartInfo = oldCartInfo.map((item) => {
81 | const temp = skus.filter(sku => item.skuId === sku.skuId)[0]
82 | if (temp) {
83 | item.info.colorInfo.value = temp.color
84 | item.info.sizeInfo.value = temp.size
85 | }
86 | return item
87 | })
88 |
89 | return newCartInfo
90 | }
91 |
92 | async function editCart (data) {
93 | const { h5Id, skus, type } = data
94 | const CartQuery = new AV.Query('Cart')
95 |
96 | // 补存num字段
97 | skus.forEach((sku) => {
98 | sku.skuId = sku.skuId + ''
99 | if(!sku.num) { sku.num = 1 }
100 | })
101 |
102 | // 获取当前购物车
103 | CartQuery.equalTo('h5Id', h5Id)
104 | CartQuery.select(['cartInfo', 'shopMap'])
105 | const findRes = await CartQuery.find()
106 | const cartRes = findRes[0].toJSON()
107 | const shopMap = cartRes.shopMap[0]
108 | const oldCartInfo = cartRes.cartInfo
109 | const cartObjectId = cartRes.objectId
110 | let newCartInfo
111 |
112 | // 根据type进行相应的购物车操作
113 | switch (type) {
114 | case typeMap['CHANGE_NUM']:
115 | newCartInfo = changCartNum(oldCartInfo, skus)
116 | break
117 | case typeMap['ADD']:
118 | newCartInfo = addCart(oldCartInfo, skus)
119 | break
120 | case typeMap['DEL']:
121 | newCartInfo = delCart(oldCartInfo, skus)
122 | break
123 | case typeMap['CHECK']:
124 | newCartInfo = checkCart(oldCartInfo, skus)
125 | break
126 | case typeMap['INVERT_CHECK']:
127 | newCartInfo = inverseCheckCart(oldCartInfo, skus)
128 | break
129 | case typeMap['CHANGE_ATTR']:
130 | newCartInfo = changeAttr(oldCartInfo, skus)
131 | break
132 | default:
133 | break
134 | }
135 |
136 | // 得到新的购物车数据
137 | const cartData = await getNewCartData({cartInfo: newCartInfo, shopMap})
138 | // 更新数据
139 | const newCart = AV.Object.createWithoutData('Cart', cartObjectId)
140 | for (let key in cartData) {
141 | newCart.set(key, cartData[key])
142 | }
143 | await newCart.save()
144 |
145 | return { result: { data: cartData }}
146 | }
147 |
148 | exports.editCart = editCart
149 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/cart/getCart.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | export async function getCart (h5Id) {
4 | const Cart = AV.Object.extend('Cart')
5 | const CartQuery = new AV.Query('Cart')
6 | let cartData = {
7 | h5Id,
8 | cartNum: 0,
9 | totalPrice: 0,
10 | cartInfo: [],
11 | shopMap: [{}]
12 | }
13 | CartQuery.equalTo('h5Id', h5Id)
14 | const res = await CartQuery.find()
15 | if (res.length === 0) {
16 | const cartItem = new Cart()
17 | for(let key in cartData) {
18 | cartItem.set(key, cartData[key])
19 | }
20 | await cartItem.save()
21 | } else {
22 | cartData = res[0].toJSON()
23 | }
24 | return { result: { data: cartData } }
25 | }
26 |
27 | export default getCart
28 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/cart/utils.js:
--------------------------------------------------------------------------------
1 | const AV = require('../index').default
2 |
3 | const typeMap = {
4 | ADD: '2',
5 | CHANGE_NUM: '3',
6 | DEL: '4',
7 | CHECK: '5',
8 | INVERT_CHECK: '6',
9 | CHANGE_ATTR: '8'
10 | }
11 |
12 | async function getNewCartData ({cartInfo, shopMap}) {
13 | const ComQuery = new AV.Query('commodity')
14 | const ShopQuery = new AV.Query('shop')
15 |
16 | const newShopMap = {}
17 | const allCartInfoData = await Promise.all(cartInfo.map(async (item) => {
18 | let newItem = item
19 |
20 | // 如果没有商品的具体信息
21 | if (!item.info) {
22 | // 获得商品的具体信息
23 | ComQuery.equalTo('skuId', parseInt(item.skuId))
24 | let allItemData = await ComQuery.find()
25 | allItemData = allItemData[0].toJSON()
26 |
27 | // 加上venderId
28 | if (!item.venderId) { item.venderId = allItemData.venderId }
29 | item.venderId += ''
30 |
31 | // 更改尺寸
32 | if (item.size) {
33 | allItemData.sizeInfo.value = item.size
34 | }
35 |
36 | // 更改颜色
37 | if (item.color) {
38 | allItemData.colorInfo.value = item.color
39 | }
40 |
41 | // 判定是否被选中
42 | if (!item.isCheck) { item.isCheck = false }
43 |
44 | newItem = Object.assign({}, item, { info: allItemData })
45 | }
46 |
47 | // 获得商店的具体信息
48 | if (!newShopMap[newItem.venderId]) {
49 | // 先找下有没有缓存,不用再查数据库
50 | if (!shopMap[newItem.venderId]) {
51 | ShopQuery.equalTo('venderId', parseInt(newItem.venderId))
52 | ShopQuery.select(['thumbnail', 'title', 'venderId'])
53 | let shopInfo = await ShopQuery.find()
54 | shopInfo = shopInfo[0].toJSON()
55 | newShopMap[newItem.venderId] = shopInfo
56 | } else {
57 | newShopMap[newItem.venderId] = shopMap[newItem.venderId]
58 | }
59 | }
60 |
61 | return newItem
62 | }))
63 |
64 | const cartData = {
65 | cartNum: 0,
66 | totalPrice: 0,
67 | cartInfo: allCartInfoData,
68 | shopMap: [newShopMap]
69 | }
70 |
71 | allCartInfoData.forEach((item) => {
72 | cartData.cartNum += item.num
73 | if (item.isCheck) {
74 | cartData.totalPrice += item.num * parseInt(item.info.price)
75 | }
76 | })
77 |
78 | return cartData
79 | }
80 |
81 | module.exports = {
82 | typeMap,
83 | getNewCartData
84 | }
85 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/index.js:
--------------------------------------------------------------------------------
1 | import AV from 'leancloud-storage/dist/av-min'
2 |
3 | AV.init('YqcEnvTSXLpEiFq3JNwgBzhL-gzGzoHsz', 'Sl7Ylgav79ETm65WRCXB6d0a')
4 |
5 | export default AV
6 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/order/addOrder.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | async function addOrder (data) {
4 | const { h5Id, freightPrice = 14, payType = 4 } = data
5 | let returnData
6 | const CartQuery = new AV.Query('Cart')
7 |
8 | const Order = AV.Object.extend('Order')
9 |
10 | CartQuery.equalTo('h5Id', h5Id)
11 | const res = await CartQuery.find()
12 | const cartData = res[0].toJSON()
13 | const cartObjectId = cartData.objectId
14 |
15 | // 获取购物车中被选中的数据
16 | const payInfo = cartData.cartInfo.filter((item) => {
17 | return item.isCheck
18 | })
19 |
20 | // 使用新的商品map
21 | const oldShopMap = cartData.shopMap[0]
22 | const newShop = {}
23 | payInfo.forEach(item => {
24 | newShop[item.venderId] = oldShopMap[item.venderId]
25 | })
26 |
27 | if (payInfo.length === 0) {
28 | returnData = {
29 | code: -1,
30 | msg: '购物车中没有勾选物品'
31 | }
32 | }
33 |
34 | const orderId = Math.random().toString(36).substr(2)
35 |
36 | const orderData = {
37 | dateSubmit: new Date().toString(),
38 | orderId,
39 | orderState: 1,
40 | ownerId: h5Id,
41 | payType,
42 | shopInfo: newShop,
43 | shouldPayPrice: cartData.totalPrice + freightPrice,
44 | skuInfoList: payInfo,
45 | cancelReasonText: '提交申请'
46 | }
47 |
48 | // 新插入订单
49 | const orderItem = new Order()
50 | for (let key in orderData) {
51 | orderItem.set(key, orderData[key])
52 | }
53 | await orderItem.save().catch(err => console.log(err))
54 |
55 | // 购物车中除移生成了订单的商品
56 | let newCartNum = 0
57 | let newCartShopMap = {}
58 | const newCartInfo = cartData.cartInfo.filter((item) => {
59 | if (!item.isCheck) {
60 | newCartShopMap[item.venderId] = oldShopMap[item.venderId]
61 | newCartNum += item.num
62 | return true
63 | }
64 | return false
65 | })
66 |
67 | // 更新数据
68 | const newCart = AV.Object.createWithoutData('Cart', cartObjectId)
69 | newCart.set('cartInfo', newCartInfo)
70 | newCart.set('cartNum', newCartNum)
71 | newCart.set('shopMap', [newCartShopMap])
72 | newCart.set('totalPrice', 0)
73 | await newCart.save()
74 |
75 | returnData = {
76 | code: 0,
77 | msg: '成功生成订单',
78 | data: orderData
79 | }
80 |
81 | return { result: { data: returnData } }
82 | }
83 |
84 | exports.addOrder = addOrder
85 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/order/cancelOrder.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | async function cancelOrder (data) {
4 | const { orderId, cancelReasonText } = data
5 | const OrderQuery = new AV.Query('Order')
6 |
7 | OrderQuery.equalTo('orderId', orderId)
8 | const res = await OrderQuery.find()
9 | const orderData = res[0].toJSON()
10 | const orderObjectId = orderData.objectId
11 |
12 | const newOrder = AV.Object.createWithoutData('Order', orderObjectId)
13 | newOrder.set('orderState', -1)
14 | newOrder.set('cancelReasonText', cancelReasonText)
15 | await newOrder.save()
16 |
17 | const returnData = {
18 | code: 0,
19 | msg: '成功取消订单'
20 | }
21 |
22 | return { result: { data: returnData } }
23 | }
24 |
25 | exports.cancelOrder = cancelOrder
26 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/order/getBalance.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | async function getBalance (data) {
4 | const { h5Id } = data
5 | const CartQuery = new AV.Query('Cart')
6 | CartQuery.equalTo('h5Id', h5Id)
7 | const res = await CartQuery.find()
8 | const cartData = res[0].toJSON()
9 | const payInfo = cartData.cartInfo.filter((item) => {
10 | return item.isCheck
11 | })
12 |
13 | const balanceData = {
14 | isNeedBanlance: payInfo.length !== 0,
15 | payInfo,
16 | shopMap: cartData.shopMap,
17 | totalPrice: cartData.totalPrice
18 | }
19 |
20 | return { result: { data: balanceData } }
21 | }
22 |
23 | exports.getBalance = getBalance
24 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/order/getOrder.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | async function getOrder (data) {
4 | const { h5Id } = data
5 | const OrderQuery = new AV.Query('Order')
6 |
7 | OrderQuery.equalTo('ownerId', h5Id)
8 | OrderQuery.descending('createdAt')
9 | const res = await OrderQuery.find()
10 | const orderData = res.map(item => {
11 | return item.toJSON()
12 | })
13 |
14 | return { result: { data: orderData } }
15 | }
16 |
17 | exports.getOrder = getOrder
18 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/order/getOrderDetail.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | async function getOrderDetail (data) {
4 | const { h5Id, orderId } = data
5 | const OrderQuery = new AV.Query('Order')
6 |
7 | OrderQuery.equalTo('ownerId', h5Id)
8 | OrderQuery.equalTo('orderId', orderId)
9 | const res = await OrderQuery.find()
10 |
11 | const orderData = res[0].toJSON()
12 |
13 | return { result: { data: orderData } }
14 | }
15 |
16 | exports.getOrderDetail = getOrderDetail
17 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/search/getList.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | async function getList (data) {
4 | const CommodityQuery = new AV.Query('commodity')
5 |
6 | let allGoods = await CommodityQuery.find()
7 | allGoods = allGoods.map(item => {
8 | return item.toJSON()
9 | })
10 | let res = {}
11 | let searchGoods = allGoods.filter(item => {
12 | return item.skuName.indexOf(data.keyWords) > -1
13 | })
14 |
15 | res.wares = searchGoods
16 | res.count = searchGoods.length
17 | res.page = data.page
18 | return { result: { data: res } }
19 | }
20 |
21 | exports.getList = getList
22 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/shop/getInformation.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | export async function getInformation () {
4 | const InfomationQuery = new AV.Query('Infomation')
5 | const findRes = await InfomationQuery.find()
6 | const result = findRes.map(item => {
7 | return item.toJSON()
8 | })
9 | return { result: { data: result } }
10 | }
11 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/shop/getShop.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | async function getShop (venderId) {
4 | const shopQuery = new AV.Query('shop')
5 | shopQuery.equalTo('venderId', Number(venderId))
6 | const findRes = await shopQuery.find()
7 | let result = findRes[0].toJSON()
8 | const floors = await Promise.all(result.floors.map(async (floor) => {
9 | const objectIds = floor.commodities.map((item) => {
10 | const comObject = AV.Object.createWithoutData('commodity', item.objectId)
11 | return comObject
12 | })
13 | const commodities = await AV.Object.fetchAll(objectIds)
14 | floor.commodities = commodities.map(com => com.toJSON())
15 | return floor
16 | }))
17 | result.floors = floors
18 | return { result: { data: result } }
19 | }
20 |
21 | exports.getShop = getShop
22 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/shop/getSku.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | export async function getSku (skuId) {
4 | const CommodityQuery = new AV.Query('commodity')
5 | CommodityQuery.equalTo('skuId', Number(skuId))
6 | const findRes = await CommodityQuery.find()
7 | const result = findRes[0].toJSON()
8 | return { result: { data: [result] } }
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/user/addUser.js:
--------------------------------------------------------------------------------
1 | import AV from '../index'
2 |
3 | export async function addUser (h5Id) {
4 | const Man = AV.Object.extend('Man')
5 | const man = new Man()
6 | man.set('h5Id', h5Id)
7 | const res = await man.save()
8 | return res
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/taro-demo/client/src/leancloud/user/getUser.js:
--------------------------------------------------------------------------------
1 | async function getUser (db, _openid) {
2 | const _ = db.command
3 | const collection = db.collection('user')
4 | const user = await collection.where({
5 | _openid: _.eq(_openid)
6 | })
7 |
8 | return user
9 | }
10 |
11 | exports.getUser = getUser
12 |
--------------------------------------------------------------------------------
/taro-demo/client/src/pages/cart/cart.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, ScrollView } from '@tarojs/components'
3 | import { connect } from '@tarojs/redux'
4 | import classnames from 'classnames'
5 |
6 | import CommondityContainer from '../../components/cart/commodity/commodity_container'
7 | import Goods from '../../components/cart/goods/goods'
8 | import BottomBar from '../../components/cart/bottom_bar/bottom_bar'
9 | import EditBox from '../../components/cart/edit_box/edit_box'
10 |
11 | import { fetchCart } from '../../actions/cart'
12 |
13 | import { throttle, getSystemInfo } from '../../utils/util'
14 |
15 | import './cart.scss'
16 |
17 | class Cart extends Component {
18 | config = {
19 | navigationBarTitleText: '购物车',
20 | backgroundColor: '#f2efef',
21 | disableScroll: true
22 | }
23 |
24 | constructor () {
25 | super(...arguments)
26 | this.state = {
27 | isLogin: true,
28 | isFixedBar: false,
29 | systemInfo: {}
30 | }
31 |
32 | this.scrollTop = 0
33 | this.pageScrollFn = throttle(this.isNeedFixedBar, 200, this)
34 | }
35 |
36 | componentDidShow () {
37 | const isLogin = true
38 | this.props.onFetchCart()
39 | this.setState({
40 | isLogin,
41 | systemInfo: getSystemInfo()
42 | })
43 | }
44 |
45 | onViewScroll = (e) => {
46 | this.pageScrollFn(e.detail.scrollTop)
47 | }
48 |
49 | isNeedFixedBar (top) {
50 | const {isFixedBar} = this.state
51 | this.scrollTop = top
52 | let needTop = 45
53 | if (top > needTop) {
54 | !isFixedBar && this.setState({isFixedBar: true})
55 | } else {
56 | isFixedBar && this.setState({isFixedBar: false})
57 | }
58 | }
59 |
60 | render () {
61 | const {isLogin, isFixedBar, systemInfo} = this.state
62 | const {commoditys, editSkuData, isFetching} = this.props
63 |
64 | const showEidtBox = editSkuData.showEidtBox
65 |
66 | const hasCommodity = commoditys.length !== 0
67 |
68 | const cartClass = classnames('cart-scroll', {'no_bottom': !hasCommodity && !isLogin})
69 |
70 | const newSystemInfo = getSystemInfo()
71 |
72 | let windowHeight = systemInfo.windowHeight
73 | if (newSystemInfo.windowHeight > windowHeight && windowHeight) {
74 | windowHeight = newSystemInfo.windowHeight
75 | }
76 |
77 | if (isFetching) {
78 | Taro.showLoading({title: '请求加载中...'})
79 | } else {
80 | Taro.hideLoading()
81 | }
82 |
83 | return (
84 |
85 |
91 |
92 |
93 | {/* */}
94 |
95 | {showEidtBox && }
96 |
97 |
98 | )
99 | }
100 | }
101 |
102 | export default connect(
103 | ({cart, home}) => ({
104 | floorData: home.floorData || {},
105 | commoditys: cart.commoditys,
106 | editSkuData: cart.editSkuData,
107 | isFetching: cart.isFetching
108 | }), (dispatch) => ({
109 | onFetchCart (...args) {
110 | dispatch(fetchCart(...args))
111 | }
112 | }))(Cart)
113 |
--------------------------------------------------------------------------------
/taro-demo/client/src/pages/cart/cart.scss:
--------------------------------------------------------------------------------
1 | /*postcss-pxtransform rn eject enable*/
2 |
3 | page {
4 | overflow-y: hidden;
5 | }
6 |
7 | @keyframes slide_in {
8 | 0% {
9 | opacity: 0;
10 | transform: translateY(130%);
11 | }
12 | 100% {
13 | opacity: 1;
14 | transform: translateY(0);
15 | }
16 | }
17 |
18 | @keyframes slide_out {
19 | 0% {
20 | opacity: 1;
21 | transform: translateY(0);
22 | }
23 | 100% {
24 | opacity: 0;
25 | transform: translateY(130%);
26 | }
27 | }
28 |
29 | @keyframes fade_out {
30 | 0% {
31 | opacity: 1;
32 | }
33 | 100% {
34 | opacity: 0;
35 | }
36 | }
37 |
38 | .show {
39 | display: block !important;
40 | }
41 |
42 | .show_wp {
43 | animation: slide_in 0.3s ease-out forwards;
44 | }
45 |
46 | .hide_wp {
47 | animation: slide_out 0.3s ease-in forwards;
48 | }
49 |
50 | .fade {
51 | animation: fade_out 0.3s ease-in-out forwards;
52 | }
53 |
54 | /*postcss-pxtransform rn eject disable*/
55 |
56 | .cart {
57 | height: 100%;
58 | display: flex;
59 | flex-direction: column;
60 | background-color: #f2efef;
61 | overflow: hidden;
62 | }
63 |
64 | .cart-scroll {
65 | flex-grow: 1;
66 | -webkit-overflow-scrolling: touch;
67 | }
68 |
69 | .cart.no_bottom {
70 | padding-bottom: 0;
71 | }
72 |
--------------------------------------------------------------------------------
/taro-demo/client/src/pages/cart/cart_sub.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, ScrollView } from '@tarojs/components'
3 | import { connect } from '@tarojs/redux'
4 | import classnames from 'classnames'
5 |
6 | import CommondityContainer from '../../components/cart/commodity/commodity_container'
7 | import Goods from '../../components/cart/goods/goods'
8 | import BottomBar from '../../components/cart/bottom_bar/bottom_bar'
9 | import EditBox from '../../components/cart/edit_box/edit_box'
10 |
11 | import {
12 | fetchCart
13 | } from '../../actions/cart'
14 |
15 | import { getLoginStatus, throttle, getSystemInfo } from '../../utils/util'
16 |
17 | import './cart.scss'
18 |
19 | class CartSub extends Component {
20 | config = {
21 | navigationBarTitleText: '购物车',
22 | backgroundColor: '#f2efef',
23 | disableScroll: true
24 | }
25 |
26 | constructor () {
27 | super(...arguments)
28 | this.state = {
29 | isLogin: Boolean(getLoginStatus()),
30 | isFixedBar: false,
31 | systemInfo: {}
32 | }
33 |
34 | this.scrollTop = 0
35 | this.pageScrollFn = throttle(this.isNeedFixedBar, 200, this)
36 | }
37 |
38 | componentDidShow () {
39 | const isLogin = Boolean(getLoginStatus())
40 | this.props.fetchCart()
41 | this.setState({
42 | isLogin,
43 | systemInfo: getSystemInfo()
44 | })
45 | }
46 |
47 | onViewScroll = (e) => {
48 | this.pageScrollFn && this.pageScrollFn(e.detail.scrollTop)
49 | }
50 |
51 | isNeedFixedBar (top) {
52 | const {isFixedBar} = this.state
53 | this.scrollTop = top
54 | let needTop = 45
55 | if (top > needTop) {
56 | !isFixedBar && this.setState({isFixedBar: true})
57 | } else {
58 | isFixedBar && this.setState({isFixedBar: false})
59 | }
60 | }
61 |
62 | render () {
63 | const {isLogin, isFixedBar, systemInfo} = this.state
64 | const {commoditys, editSkuData, isFetching} = this.props
65 |
66 | const showEidtBox = editSkuData.showEidtBox
67 |
68 | const hasCommodity = commoditys.length !== 0
69 |
70 | const cartClass = classnames('cart-scroll', {'no_bottom': !hasCommodity && !isLogin})
71 |
72 | const newSystemInfo = getSystemInfo()
73 |
74 | let windowHeight = systemInfo.windowHeight
75 | if (newSystemInfo.windowHeight > windowHeight && windowHeight) {
76 | windowHeight = newSystemInfo.windowHeight
77 | }
78 |
79 | if (isFetching) {
80 | Taro.showLoading({title: '请求加载中...'})
81 | } else {
82 | Taro.hideLoading()
83 | }
84 |
85 | return (
86 |
87 |
94 |
95 |
96 | {/* */}
97 |
98 | {showEidtBox ? : null}
99 |
100 |
101 | )
102 | }
103 | }
104 |
105 | export default connect((
106 | {
107 | cart,
108 | home
109 | }) => ({
110 | floorData: home.floorData || {},
111 | commoditys: cart.commoditys,
112 | editSkuData: cart.editSkuData,
113 | isFetching: cart.isFetching
114 | }), (dispatch) => ({
115 | fetchCart (...args) {
116 | dispatch(fetchCart(...args))
117 | }
118 | }))(CartSub)
119 |
--------------------------------------------------------------------------------
/taro-demo/client/src/pages/detail/bag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/taro-demo/client/src/pages/detail/bag.png
--------------------------------------------------------------------------------
/taro-demo/client/src/pages/index/index.scss:
--------------------------------------------------------------------------------
1 | page, body {
2 | height: 100%;
3 | }
4 |
5 | .index {
6 | background-color: #ffffff;
7 | height: 100%;
8 | display: flex;
9 | flex-direction: column;
10 | overflow: hidden;
11 | }
12 |
13 | .index-search_into {
14 | padding: 30px 40px;
15 | position: relative;
16 | display: flex;
17 | height: 120px;
18 | background: #ffffff;
19 | }
20 |
21 | .index-search_box {
22 | width: 88%;
23 | margin: 0 auto;
24 | }
25 |
26 | .index_list.hidden {
27 | height: 100%;
28 | overflow: hidden;
29 | }
30 |
31 | .index_list {
32 | //flex: 1;
33 | flex-grow: 1;
34 | overflow: scroll;
35 | -webkit-overflow-scrolling: touch;
36 | }
37 |
38 | .index_item {
39 | position: relative;
40 | display: flex;
41 | flex-direction: column;
42 | align-items: center;
43 | width: 100%;
44 | margin: -1px 0 0;
45 | overflow: hidden;
46 | }
47 |
48 | .index_item_in {
49 | width: 100%;
50 | height: 100%;
51 | }
52 |
53 | .index_item_img {
54 | width: 100%;
55 | }
56 |
57 | .index_item_brand {
58 | position: absolute;
59 | top: 300px;
60 | left: 0;
61 | width: 100%;
62 | font-size: 38px;
63 | font-weight: bold;
64 | text-align: center;
65 | color: #fff;
66 | letter-spacing: 4px;
67 | //transition: top 2s ease-in;
68 | }
69 |
70 | .index_item_desc {
71 | position: absolute;
72 | top: 358px;
73 | left: 0;
74 | width: 100%;
75 | font-size: 24px;
76 | font-weight: bold;
77 | text-align: center;
78 | letter-spacing: 8px;
79 | color: #fff;
80 | //transition: top 2s ease-in;
81 | }
82 |
83 | .index_item_type {
84 | position: absolute;
85 | top: 40px;
86 | right: 30px;
87 | text-align: right;
88 | color: #fff;
89 | font-size: 18px;
90 | }
91 |
92 | .index_item_title {
93 | position: absolute;
94 | top: 300px;
95 | left: 0;
96 | width: 100%;
97 | font-size: 42px;
98 | font-weight: bold;
99 | text-align: center;
100 | color: #fff;
101 | letter-spacing: 4px;
102 | //transition: top 2s ease-in;
103 | }
104 |
105 | .index_item_more {
106 | position: absolute;
107 | top: 406px;
108 | left: 50%;
109 | width: 228px;
110 | height: 42px;
111 | margin-left: -114px;
112 | border: 1px solid #fff;
113 | text-align: center;
114 | line-height: 42px;
115 | font-size: 24px;
116 | color: #fff;
117 | //transition: top 2s ease-in;
118 | }
119 |
120 | .index_item_avatar {
121 | position: absolute;
122 | bottom: 128px;
123 | left: 50%;
124 | margin-left: -25px;
125 | width: 50px;
126 | height: 50px;
127 | overflow: hidden;
128 | border-radius: 100px;
129 | //transition: bottom 2s ease-in;
130 | }
131 |
132 | .index_item_athor {
133 | position: absolute;
134 | bottom: 74px;
135 | left: 0;
136 | width: 100%;
137 | text-align: center;
138 | font-size: 20px;
139 | color: #fff;
140 | //transition: bottom 2s ease-in;
141 | }
142 |
143 | .animation .index_item {
144 | animation: home_move 0.5s ease-in forwards;
145 | }
146 |
147 | @keyframes home_move {
148 | 0% {
149 | transform: translateY(50px);
150 | }
151 | 100% {
152 | transform: translateY(0px);
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/taro-demo/client/src/pages/list/list.scss:
--------------------------------------------------------------------------------
1 | .list {
2 | position: relative;
3 | height: 100%;
4 | overflow: hidden;
5 | background-color: white;
6 | display: flex;
7 | flex-direction: column;
8 | }
9 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/balance.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import {
3 | REQUEST_BALANCE_INFO,
4 | RECEIVE_BALANCE_INFO,
5 | RECEIVE_BALANCE_ORDER,
6 | REQUEST_BALANCE_ORDER
7 | } from '../constants/balance'
8 |
9 | import { parseMoney } from '../utils/util'
10 |
11 | const balanceData = {
12 | isNeedBanlance: true,
13 | payCommodities: [],
14 | freightPrice: 14,
15 | totalPrice: 0,
16 | allPrice: 0,
17 | payNum: 0,
18 | isFetching: false
19 | }
20 |
21 | export default handleActions({
22 | [REQUEST_BALANCE_INFO] (state) {
23 | return {
24 | ...state,
25 | isFetching: true
26 | }
27 | },
28 | [RECEIVE_BALANCE_INFO] (state, action) {
29 | const { payCommodities, isNeedBanlance, payNum } = action.payload
30 | let totalPrice = action.payload.totalPrice
31 | const allPrice = parseMoney(totalPrice + state.freightPrice)
32 | totalPrice = parseMoney(totalPrice)
33 | return {
34 | ...state,
35 | isNeedBanlance,
36 | payCommodities,
37 | totalPrice,
38 | allPrice,
39 | payNum,
40 | isFetching: false
41 | }
42 | },
43 | [REQUEST_BALANCE_ORDER](state) {
44 | return Object.assign({}, state, {
45 | isFetching: true
46 | })
47 | },
48 |
49 | [RECEIVE_BALANCE_ORDER](state) {
50 | return Object.assign({}, state, {
51 | isFetching: false
52 | })
53 | }
54 | }, {...balanceData})
55 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/cart.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import {
3 | REQUEST_CART,
4 | RECEIVE_CART,
5 | REQUEST_DEL_CART,
6 | RECEIVE_DEL_CART,
7 | REQUEST_CHANGE_NUM,
8 | RECEIVE_CHANGE_NUM,
9 | REQUEST_ADD_CART,
10 | RECEIVE_ADD_CART,
11 | REQUEST_CHECK_CART,
12 | RECEIVE_CHECK_CART,
13 | REQUEST_INVERSE_CHECK,
14 | RECEIVE_INVERSE_CHECK,
15 | REQUEST_CHANGE_ATTR,
16 | RECEIVE_CHANGE_ATTR,
17 | REQUEST_SKU_ATTR,
18 | RECEIVE_SKU_ATTR,
19 | CHECK_DEL,
20 | INVERSE_CHECK_DEL,
21 | SHOW_ATTR_BOX,
22 | HIDE_ATTR_BOX,
23 | CHANGE_EDIT_STATUS
24 | } from '../constants/cart'
25 |
26 | const INITIAL_STATE = {
27 | commoditys: [],
28 | offSales: [],
29 | editSkuData: {
30 | showEidtBox: false
31 | },
32 | diviner: [],
33 | footmark: [],
34 | couponData: {
35 | showCouponList: false
36 | },
37 | checkCartNum: 0,
38 | totalPrice: 0,
39 | checkAll: false,
40 | checkDelAll: false,
41 | isEditStatus: false,
42 | isFetching: false
43 | }
44 |
45 | function genarateFetchActions () {
46 | const actionsMap = {}
47 |
48 | const fetchActionType = [
49 | REQUEST_CART,
50 | REQUEST_DEL_CART,
51 | REQUEST_CHANGE_NUM,
52 | REQUEST_ADD_CART,
53 | REQUEST_CHECK_CART,
54 | REQUEST_INVERSE_CHECK,
55 | REQUEST_CHANGE_ATTR,
56 | REQUEST_SKU_ATTR,
57 | ]
58 |
59 | const receiveActionType = [
60 | RECEIVE_CART,
61 | RECEIVE_DEL_CART,
62 | RECEIVE_CHANGE_NUM,
63 | RECEIVE_ADD_CART,
64 | RECEIVE_CHECK_CART,
65 | RECEIVE_INVERSE_CHECK,
66 | RECEIVE_CHANGE_ATTR
67 | ]
68 |
69 | fetchActionType.forEach((type) => {
70 | actionsMap[type] = function(state){
71 | return {
72 | ...state,
73 | isFetching: true
74 | }
75 | }
76 | })
77 | receiveActionType.forEach((type) => {
78 | actionsMap[type] = function (state, action) {
79 | const {
80 | commoditys = [],
81 | offSales = [],
82 | checkCartNum = 0,
83 | totalPrice = 0,
84 | checkAll = false
85 | } = action.payload
86 |
87 | return {
88 | ...state,
89 | commoditys,
90 | offSales,
91 | checkCartNum,
92 | totalPrice,
93 | checkAll,
94 | isFetching: false
95 | }
96 | }
97 | })
98 |
99 | return actionsMap
100 | }
101 |
102 | export default handleActions({
103 | ...genarateFetchActions(),
104 | [CHECK_DEL](state, action) {
105 | const { commoditys, checkDelAll } = action.payload
106 | return {
107 | ...state,
108 | commoditys,
109 | checkDelAll
110 | }
111 | },
112 | [INVERSE_CHECK_DEL](state, action) {
113 | const { commoditys, checkDelAll } = action.payload
114 | return {
115 | ...state,
116 | commoditys,
117 | checkDelAll
118 | }
119 | },
120 | [RECEIVE_SKU_ATTR](state, action) {
121 | const { editSkuData } = action.payload
122 | return {
123 | ...state,
124 | editSkuData,
125 | isFetching: false
126 | }
127 | },
128 | [SHOW_ATTR_BOX](state, action) {
129 | const { editSkuData } = action.payload
130 | return {
131 | ...state,
132 | editSkuData
133 | }
134 | },
135 | [HIDE_ATTR_BOX](state, action) {
136 | const { editSkuData } = action.payload
137 | return {
138 | ...state,
139 | editSkuData
140 | }
141 | },
142 | [CHANGE_EDIT_STATUS](state, action) {
143 | const { isEditStatus } = action.payload
144 | return {
145 | ...state,
146 | isEditStatus
147 | }
148 | }
149 | }, { ...INITIAL_STATE })
150 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/detail.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import {
3 | REQUEST_DETAIL_CART,
4 | RECEIVE_DETAIL_CART,
5 | REQUEST_DETAIL_SKU,
6 | RECEIVE_DETAIL_SKU,
7 | REQUEST_DETAIL_ADD_CART,
8 | RECEIVE_DETAIL_ADD_CART
9 | } from '../constants/detail'
10 |
11 | const detailData = {
12 | sku: {},
13 | cartInfo: [],
14 | cartNum: 0,
15 | isFetching: false
16 | }
17 |
18 | export default handleActions({
19 | [REQUEST_DETAIL_CART](state) {
20 | return {
21 | ...state,
22 | isFetching: true
23 | }
24 | },
25 | [RECEIVE_DETAIL_CART](state, action) {
26 | const { cartNum } = action.payload
27 | return {
28 | ...state,
29 | cartNum,
30 | isFetching: false
31 | }
32 | },
33 | [REQUEST_DETAIL_SKU](state) {
34 | return {
35 | ...state,
36 | isFetching: true
37 | }
38 | },
39 | [RECEIVE_DETAIL_SKU](state, action) {
40 | const sku = action.payload
41 | return {
42 | ...state,
43 | sku,
44 | isFetching: false
45 | }
46 | },
47 | [REQUEST_DETAIL_ADD_CART](state) {
48 | return {
49 | ...state,
50 | isFetching: true
51 | }
52 | },
53 | [RECEIVE_DETAIL_ADD_CART](state, action) {
54 | const { cartNum } = action.payload
55 | return {
56 | ...state,
57 | cartNum,
58 | isFetching: false
59 | }
60 | },
61 | }, {...detailData})
62 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/home.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import {
3 | REQUEST_HOME,
4 | RECEIVE_HOME,
5 | RECEIVE_HOME_ERROR
6 | } from '../constants/home'
7 |
8 | const homeData = {
9 | loading: false,
10 | floorData: []
11 | }
12 |
13 | export default handleActions({
14 | [REQUEST_HOME] (state) {
15 | return {
16 | ...state,
17 | loading: true
18 | }
19 | },
20 | [RECEIVE_HOME] (state, action) {
21 | const { data } = action.payload
22 | return {
23 | ...state,
24 | loading: false,
25 | floorData: data
26 | }
27 | },
28 | [RECEIVE_HOME_ERROR] (state) {
29 | return {
30 | ...state
31 | }
32 | }
33 | }, {...homeData})
34 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux'
2 | import detail from './detail'
3 | import home from './home'
4 | import shop from './shop'
5 | import search from './search'
6 | import cart from './cart'
7 | import balance from './balance'
8 |
9 | import orderDetail from './order/detail'
10 | import orderList from './order/list'
11 |
12 | export default combineReducers({
13 | detail,
14 | home,
15 | shop,
16 | search,
17 | orderDetail,
18 | orderList,
19 | cart,
20 | balance
21 | })
22 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/order/detail.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import {
3 | REQUEST_ORDER_DETAIL,
4 | RECEIVE_ORDER_DETAIL,
5 | RECEIVE_ORDER_CANCEL,
6 | REQUEST_ORDER_CANCEL
7 | } from '../../constants/order/detail'
8 |
9 | const detail = {
10 | isFetchingDetail: false,
11 | all: {}
12 | }
13 |
14 | export default handleActions({
15 | [REQUEST_ORDER_DETAIL] (state) {
16 | return Object.assign({
17 | isFetchingDetail: true
18 | }, state)
19 | },
20 |
21 | [RECEIVE_ORDER_DETAIL] (state, action) {
22 | const res = action.payload
23 | return {
24 | ...state,
25 | isFetchingDetail: false,
26 | all: res
27 | }
28 | },
29 |
30 | [REQUEST_ORDER_CANCEL] (state) {
31 | return {
32 | ...state,
33 | isFetchingDetail: true
34 | }
35 | },
36 |
37 | [RECEIVE_ORDER_CANCEL] (state) {
38 | return {
39 | ...state,
40 | isFetchingDetail: false
41 | }
42 | },
43 | }, {
44 | ...detail
45 | })
46 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/order/list.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import {
3 | REQUEST_ORDER_LIST,
4 | RECEIVE_ORDER_LIST
5 | } from '../../constants/order/list'
6 |
7 | const list = {
8 | isFetchingList: false,
9 | orderList: []
10 | }
11 |
12 | export default handleActions({
13 | [REQUEST_ORDER_LIST] (state) {
14 | return Object.assign({}, state, {
15 | isFetchingList: true
16 | })
17 | },
18 |
19 | [RECEIVE_ORDER_LIST] (state, action) {
20 | const data = action.payload
21 | return Object.assign({}, state, {
22 | isFetchingList: false,
23 | orderList: data
24 | })
25 | },
26 | }, { ...list })
27 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/search.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 |
3 | import {
4 | SHOW_SEARCH_BAR,
5 | REQUEST_SEARCH_RESULT,
6 | RECEIVE_SEARCH_RESULT,
7 | RECEIVE_SEARCH_ERROR,
8 | SHOW_RESULT,
9 | CHANGE_HISTORY,
10 | SHOW_NOT_FIND,
11 | RESET_STATE
12 | } from '../constants/search'
13 | const searchData = {
14 | historyWords: ['品牌', '衣服'],
15 | hotWords: ['品牌', '衣服'],
16 | searchResult: {
17 | wares: []
18 | },
19 | loading: false,
20 | cart: null,
21 | showSearchBar: true,
22 | showSearchResult: false,
23 | showSearchHot: true,
24 | showSearchHistory: true,
25 | showErrorProblem: false,
26 | showNotFind: false
27 | }
28 | export default handleActions({
29 | [SHOW_SEARCH_BAR] (state) {
30 | return {
31 | ...state,
32 | showSearchBar: !state.showSearchBar
33 | }
34 | },
35 | [REQUEST_SEARCH_RESULT] (state, action) {
36 | if (state.searchResult.page && state.searchResult.page === 1) {
37 | state.searchResult = {
38 | wares: []
39 | }
40 | }
41 | return {
42 | ...state,
43 | loading: true,
44 | showSearchBar: true,
45 | showSearchResult: true,
46 | showSearchHot: false,
47 | showSearchHistory: false,
48 | showErrorProblem: false,
49 | showNotFind: false
50 | }
51 | },
52 | [RECEIVE_SEARCH_RESULT] (state, action) {
53 | return {
54 | ...state,
55 | searchResult: action.payload
56 | }
57 | },
58 | [RECEIVE_SEARCH_ERROR] (state) {
59 | return {
60 | ...state,
61 | showErrorProblem: true
62 | }
63 | },
64 | [CHANGE_HISTORY] (state, action) {
65 | return {
66 | ...state,
67 | historyWords: action.payload
68 | }
69 | },
70 | [SHOW_RESULT] (state, action) {
71 | let isShow = action.payload
72 | return {
73 | ...state,
74 | showSearchResult: isShow,
75 | showSearchHot: !isShow,
76 | showSearchHistory: !isShow
77 | }
78 | },
79 | [SHOW_NOT_FIND] (state) {
80 | return {
81 | ...state,
82 | showNotFind: true
83 | }
84 | },
85 | [RESET_STATE] () {
86 | return searchData
87 | }
88 | }, { ...searchData })
89 |
--------------------------------------------------------------------------------
/taro-demo/client/src/reducers/shop.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import {
3 | REQUEST_SHOP,
4 | RECEIVE_SHOP,
5 | RESET_SHOP
6 | } from '../constants/shop'
7 |
8 | const INITIAL_STATE = {
9 | title: '',
10 | floors: []
11 | }
12 |
13 | export default handleActions({
14 | [REQUEST_SHOP](state) {
15 | return { ...state }
16 | },
17 | [RECEIVE_SHOP](state, action) {
18 | const data = action.payload
19 | return {
20 | ...state,
21 | ...data
22 | }
23 | },
24 | [RESET_SHOP](state) {
25 | return {
26 | title: '',
27 | floors: []
28 | }
29 | }
30 | }, { ...INITIAL_STATE })
31 |
--------------------------------------------------------------------------------
/taro-demo/client/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux'
2 | import thunkMiddleware from 'redux-thunk'
3 | import { createLogger } from 'redux-logger'
4 | import rootReducer from '../reducers'
5 |
6 | const middlewares = [
7 | thunkMiddleware,
8 | createLogger()
9 | ]
10 |
11 | export default function configStore () {
12 | const store = createStore(rootReducer, applyMiddleware(...middlewares))
13 | return store
14 | }
15 |
--------------------------------------------------------------------------------
/taro-demo/client/src/utils/index.js:
--------------------------------------------------------------------------------
1 | import Taro from '@tarojs/taro'
2 | import { getGlobalData } from '../constants/globalData'
3 |
4 | const appid = 'wx9504f077bdc24ea2'
5 | const secret = 'a98c03055579cfd517a45fb4771377e9'
6 |
7 | async function getUserInfo () {
8 | const userData = getGlobalData('userData')
9 | if (userData) {
10 | return userData
11 | }
12 | try {
13 | const userData = await Taro.getUserInfo()
14 | return userData
15 | } catch (err) {
16 | console.log(err)
17 | console.log('微信登录或用户接口故障')
18 | return {}
19 | }
20 | }
21 |
22 | async function getOpenId () {
23 | let openId
24 | try {
25 | openId = Taro.getStorageSync('taro_demo_openid')
26 | } catch (error) {
27 | console.log(error)
28 | }
29 | if (openId) {
30 | return openId
31 | } else {
32 | const res = await Taro.cloud.callFunction({
33 | name: 'user',
34 | data: {
35 | func: 'getOpenId'
36 | }
37 | })
38 | const openId = res.result.data.openId
39 | Taro.setStorage({key: 'taro_demo_openid', data: openId})
40 | return openId
41 | }
42 | }
43 |
44 | async function getIsAuth () {
45 | const openid = await getOpenId()
46 | let {userInfo} = await getUserInfo()
47 | let isAuth = false
48 | if (userInfo) {
49 | userInfo.isAuth = true
50 | userInfo._id = openid
51 | isAuth = true
52 | } else {
53 | userInfo = {
54 | _id: openid,
55 | isAuth: false
56 | }
57 | }
58 | await wx.cloud.callFunction({
59 | name: 'user',
60 | data: {
61 | func: 'addUser',
62 | data: userInfo
63 | },
64 | success: (res) => {
65 | // console.log(res)
66 | },
67 | fail: (res) => {
68 | // console.log(res)
69 | }
70 | })
71 |
72 | return isAuth
73 | }
74 |
75 | function getH5UniqueId () {
76 | if (process.env.TARO_ENV !== 'weapp') {
77 | return new Promise((resolve, reject) => {
78 | Taro.getStorage({
79 | key: 'Taro_h5_demo_uid',
80 | success({ data }) {
81 | if (!data) {
82 | const h5Id = `user_${Math.random().toString(36).substr(2)}`
83 | Taro.setStorage({ key: 'Taro_h5_demo_uid', data: h5Id })
84 | const addUser = require('../leancloud/user/addUser').addUser
85 | addUser(h5Id).then((res) => {
86 | Taro.setStorage({ key: 'Taro_h5_demo_objectId', data: res.id })
87 | resolve(h5Id)
88 | }).catch(reject)
89 | } else {
90 | resolve(data)
91 | }
92 | },
93 | fail() {
94 | const h5Id = `user_${Math.random().toString(36).substr(2)}`
95 | Taro.setStorage({ key: 'Taro_h5_demo_uid', data: h5Id })
96 | const addUser = require('../leancloud/user/addUser').addUser
97 | addUser(h5Id).then((res) => {
98 | Taro.setStorage({ key: 'Taro_h5_demo_objectId', data: res.id })
99 | resolve(h5Id)
100 | }).catch(reject)
101 | }
102 | })
103 | })
104 | } else {
105 | return null
106 | }
107 | }
108 |
109 | export {
110 | getUserInfo,
111 | getOpenId,
112 | getIsAuth,
113 | getH5UniqueId
114 | }
115 |
--------------------------------------------------------------------------------
/taro-demo/client/src/utils/wx.js:
--------------------------------------------------------------------------------
1 | import Taro from '@tarojs/taro'
2 |
3 | import { getGlobalData } from '../constants/globalData'
4 | import { isEmptyObject } from './util'
5 |
6 | export async function getWxUserData () {
7 | const userData = getGlobalData('userData')
8 | if (userData) {
9 | return userData
10 | }
11 | try {
12 | const userData = await Taro.getUserInfo()
13 | return userData
14 | } catch (err) {
15 | console.log(err)
16 | console.log('微信登录或用户接口故障')
17 | return null
18 | }
19 | }
20 |
21 | export async function checkSettingStatus (scope, { title, content }) {
22 | const setting = await Taro.getSetting()
23 | const authSetting = setting.authSetting
24 | if (!isEmptyObject(authSetting)) {
25 | if (authSetting[scope] === false) {
26 | const res = await Taro.showModal({
27 | title: title,
28 | content: content,
29 | showCancel: true
30 | })
31 | if (res.confirm) {
32 | const setting = await Taro.openSetting()
33 | const authSetting = setting.authSetting
34 | if (!isEmptyObject(authSetting)) {
35 | if (authSetting[scope] === true) {
36 | return await getWxUserData()
37 | }
38 | }
39 | }
40 | }
41 | }
42 | return null
43 | }
44 |
--------------------------------------------------------------------------------
/taro-demo/cloud/doc/information.json:
--------------------------------------------------------------------------------
1 | {"_id":"W2pgbeqC-opZcR0z","desc":"店铺1","venderId":{"$numberLong":"1"},"image":"http://img20.360buyimg.com/ling/jfs/t1/1161/40/5220/256660/5b9f125cE063f3457/6e4dcd832773a0e2.jpg"}
2 | {"_id":"W3DpRxp0j_S6QBTN","venderId":{"$numberLong":"2"},"desc":"店铺2","image":"http://img12.360buyimg.com/ling/jfs/t1/1550/16/5171/266341/5b9f1b09E428298ba/d586bfc13f02a332.jpg"}
3 | {"_id":"W3DqDOqC-opZc_xv","venderId":{"$numberLong":"3"},"desc":"店铺3","image":"http://img14.360buyimg.com/ling/jfs/t1/2576/31/5323/251933/5b9f1b20E11657686/c2f74978d2db0300.jpg"}
4 | {"_id":"W3DqZ-qC-opZc_yv","desc":"店铺4","image":"http://img14.360buyimg.com/ling/jfs/t1/5916/27/5150/265659/5b9f1b36E270b1d18/c3f5c638e3bef241.jpg","venderId":{"$numberLong":"4"}}
5 |
--------------------------------------------------------------------------------
/taro-demo/cloud/doc/shop.json:
--------------------------------------------------------------------------------
1 | {"_id":"1","floors":[{"commodities":[{"$numberLong":"1"},{"$numberLong":"2"},{"$numberLong":"3"},{"$numberLong":"4"}],"desc":"http://img13.360buyimg.com/ling/jfs/t1/351/8/5598/360623/5b9f2d78E2ae9ff61/716a483125913fd9.jpg","title":"//img12.360buyimg.com/tuangou/s750x170_jfs/t15316/209/1136705664/8030/71099545/5a4626ebN8fea2205.png"},{"commodities":[{"$numberLong":"1"},{"$numberLong":"3"},{"$numberLong":"4"},{"$numberLong":"5"}],"desc":"http://img10.360buyimg.com/ling/jfs/t1/1657/27/5346/245880/5b9f2d78E85f0c8c7/1dc51ecf4e25b6d0.jpg","title":"//img10.360buyimg.com/tuangou/s750x170_jfs/t15328/270/809894122/7669/cc12bee5/5a38bbd7Nd9f338f0.png"}],"thumbnail":"//img10.360buyimg.com/popshop/s190x80_jfs/t16390/270/1887231446/24253/18756a28/5a72d454N18b1efc6.jpg","title":"店铺1","venderId":{"$numberLong":"1"},"banner":["http://img14.360buyimg.com/ling/jfs/t1/460/5/5518/747242/5b9f1eb2Ed89cd28b/7787f2a49186610f.jpg","http://img30.360buyimg.com/ling/jfs/t1/268/31/5534/1729274/5b9f1f14Eee5b2adf/8e74d65c03f3f9fd.jpg!q60","http://img12.360buyimg.com/ling/jfs/t1/1501/21/5274/925976/5b9f2021E25bcf9e1/9850163290842937.jpg!q60","http://img14.360buyimg.com/ling/jfs/t1/1826/38/5279/1690440/5b9f1f90Eecfa2c50/10051d297b94c29b.jpg!q60"],"desc":"店铺1页面","_openid":"oFQSH5MekinNSc_yqH9dNlmKh6vI"}
2 | {"_id":"2","desc":"店铺2页面","floors":[{"desc":"http://img10.360buyimg.com/ling/jfs/t1/1657/27/5346/245880/5b9f2d78E85f0c8c7/1dc51ecf4e25b6d0.jpg","title":"//img12.360buyimg.com/tuangou/s750x170_jfs/t15316/209/1136705664/8030/71099545/5a4626ebN8fea2205.png","commodities":[{"$numberLong":"3"},{"$numberLong":"1"},{"$numberLong":"2"},{"$numberLong":"5"}]},{"commodities":[{"$numberLong":"1"},{"$numberLong":"3"},{"$numberLong":"2"},{"$numberLong":"7"}],"desc":"http://img30.360buyimg.com/ling/jfs/t1/5083/21/5232/267378/5b9f2d78E8bcd381b/ff27135de4d8cf8c.jpg","title":"//img10.360buyimg.com/tuangou/s750x170_jfs/t15328/270/809894122/7669/cc12bee5/5a38bbd7Nd9f338f0.png"}],"thumbnail":"//img10.360buyimg.com/popshop/s190x80_jfs/t17935/53/2369573223/24376/e2dd64/5af1b116N558ae2db.jpg","title":"店铺2","venderId":{"$numberLong":"2"},"banner":["http://img30.360buyimg.com/ling/jfs/t1/268/31/5534/1729274/5b9f1f14Eee5b2adf/8e74d65c03f3f9fd.jpg!q60","http://img12.360buyimg.com/ling/jfs/t1/1501/21/5274/925976/5b9f2021E25bcf9e1/9850163290842937.jpg!q60","http://img14.360buyimg.com/ling/jfs/t1/1826/38/5279/1690440/5b9f1f90Eecfa2c50/10051d297b94c29b.jpg!q60","http://img20.360buyimg.com/ling/jfs/t1/5373/22/5202/707257/5b9f1e8aE219cdf19/bb17192e448bade7.jpg"],"_openid":"oFQSH5MekinNSc_yqH9dNlmKh6vI"}
3 | {"_id":"3","desc":"店铺3页面","floors":[{"commodities":[{"$numberLong":"2"},{"$numberLong":"3"},{"$numberLong":"6"},{"$numberLong":"4"}],"desc":"http://img30.360buyimg.com/ling/jfs/t1/5083/21/5232/267378/5b9f2d78E8bcd381b/ff27135de4d8cf8c.jpg","title":"//img12.360buyimg.com/tuangou/s750x170_jfs/t15316/209/1136705664/8030/71099545/5a4626ebN8fea2205.png"},{"title":"//img10.360buyimg.com/tuangou/s750x170_jfs/t15328/270/809894122/7669/cc12bee5/5a38bbd7Nd9f338f0.png","commodities":[{"$numberLong":"1"},{"$numberLong":"5"},{"$numberLong":"3"},{"$numberLong":"6"}],"desc":"http://img10.360buyimg.com/ling/jfs/t1/1657/27/5346/245880/5b9f2d78E85f0c8c7/1dc51ecf4e25b6d0.jpg"}],"thumbnail":"//img12.360buyimg.com/n1/s190x80_jfs/t22429/300/1109626640/5017/d77c7252/5b50350aNb53dba6c.png","title":"店铺3","venderId":{"$numberLong":"3"},"banner":["http://img20.360buyimg.com/ling/jfs/t1/5373/22/5202/707257/5b9f1e8aE219cdf19/bb17192e448bade7.jpg","http://img14.360buyimg.com/ling/jfs/t1/460/5/5518/747242/5b9f1eb2Ed89cd28b/7787f2a49186610f.jpg","http://img30.360buyimg.com/ling/jfs/t1/268/31/5534/1729274/5b9f1f14Eee5b2adf/8e74d65c03f3f9fd.jpg!q60","http://img12.360buyimg.com/ling/jfs/t1/1501/21/5274/925976/5b9f2021E25bcf9e1/9850163290842937.jpg!q60"],"_openid":"oFQSH5MekinNSc_yqH9dNlmKh6vI"}
4 | {"_id":"4","venderId":{"$numberLong":"4"},"banner":["http://img20.360buyimg.com/ling/jfs/t1/5373/22/5202/707257/5b9f1e8aE219cdf19/bb17192e448bade7.jpg","http://img14.360buyimg.com/ling/jfs/t1/460/5/5518/747242/5b9f1eb2Ed89cd28b/7787f2a49186610f.jpg","http://img30.360buyimg.com/ling/jfs/t1/268/31/5534/1729274/5b9f1f14Eee5b2adf/8e74d65c03f3f9fd.jpg!q60","http://img11.360buyimg.com/ling/jfs/t1/4629/4/5095/1714340/5b9f1f72E997695e5/4f56ca1a12642971.jpg!q60"],"desc":"店铺4页面","floors":[{"commodities":[{"$numberLong":"4"},{"$numberLong":"6"},{"$numberLong":"1"},{"$numberLong":"2"}],"desc":"http://img30.360buyimg.com/ling/jfs/t1/5083/21/5232/267378/5b9f2d78E8bcd381b/ff27135de4d8cf8c.jpg","title":"//img12.360buyimg.com/tuangou/s750x170_jfs/t15316/209/1136705664/8030/71099545/5a4626ebN8fea2205.png"},{"commodities":[{"$numberLong":"1"},{"$numberLong":"2"},{"$numberLong":"5"},{"$numberLong":"3"}],"desc":"http://img13.360buyimg.com/ling/jfs/t1/351/8/5598/360623/5b9f2d78E2ae9ff61/716a483125913fd9.jpg","title":"//img10.360buyimg.com/tuangou/s750x170_jfs/t15328/270/809894122/7669/cc12bee5/5a38bbd7Nd9f338f0.png"}],"thumbnail":"//img14.360buyimg.com/popshop/s190x80_jfs/t11023/223/1027006619/7985/c520a46c/5a379a4aN9d105368.png","title":"店铺4","_openid":"oFQSH5MekinNSc_yqH9dNlmKh6vI"}
5 |
--------------------------------------------------------------------------------
/taro-demo/cloud/doc/user.json:
--------------------------------------------------------------------------------
1 | {"_id":"oFQSH5DTPL_1z8GvsBX3eug7B0YI","country":"China","nickName":"Mr_Prune","province":"Chongqing","city":"","gender":{"$numberLong":"1"},"isAuth":true,"language":"zh_CN","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/2JXQXmeRCKLKicw8SACyqYXicibDVreHhCjJW17tuQcSL0ibaQgJeBsZyhgzZYXTs0ucTpqLiaTRw1SKBcia2lEEJk7g/132"}
2 | {"_id":"oFQSH5Hy28tDuKGyI2qHHjLw5fRY","gender":{"$numberLong":"1"},"isAuth":true,"language":"zh_CN","nickName":"江锡忠","province":"Guangdong","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLHGZgQJjatG9aEe85aSVdicvfePpS5UKFzPD2DS12LiaZc0LPhfXhIITE6DCJJBbnT0UIrTbr3zZIw/132","city":"Zhanjiang","country":"China"}
3 | {"_id":"oFQSH5MekinNSc_yqH9dNlmKh6vI","country":"China","gender":{"$numberLong":"1"},"language":"zh_CN","nickName":"- 爽。。","province":"Guangdong","city":"Shenzhen","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/NzY4FlYl7m50Hib0VZfkjaQsVkZ0YtpK0ceWx7AQnMeQu0DetkS0ecp2oQwFrS41TSNw5xa7yib2mmOKms5Fup1Q/132","isAuth":true}
4 | {"_id":{"$oid":"5b6d6d16524ec2d3211e5933"},"province":"Guangdong","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/NzY4FlYl7m50Hib0VZfkjaQsVkZ0YtpK0ceWx7AQnMeQu0DetkS0ecp2oQwFrS41TSNw5xa7yib2mmOKms5Fup1Q/132","city":"Shenzhen","country":"China","gender":{"$numberLong":"1"},"isAuth":true,"language":"zh_CN","nickName":"- 爽。。"}
5 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/cart/editCart.js:
--------------------------------------------------------------------------------
1 | const { typeMap, getNewCartData } = require('./utils')
2 |
3 | function changCartNum (oldCartInfo, skus) {
4 | // 更新购物车中的商品数据
5 | const newCartInfo = oldCartInfo.map((item) => {
6 | const temp = skus.filter(sku => item.skuId === sku.skuId)[0]
7 | if (temp) {
8 | item.num = temp.num
9 | item.isCheck = true
10 | }
11 | return item
12 | })
13 |
14 | return newCartInfo
15 | }
16 |
17 | function addCart (oldCartInfo, skus) {
18 | skus.forEach((sku) => { sku.isCheck = true })
19 | let spliceIdx
20 | // 更新购物车中的商品数据
21 | let newCartInfo = oldCartInfo.map((item) => {
22 | const temp = skus.filter((sku, idx) => {
23 | if (item.skuId === sku.skuId) {
24 | spliceIdx = idx
25 | return true
26 | }
27 | })[0]
28 | if (temp) {
29 | skus.splice(spliceIdx, 1)
30 | item.num += temp.num
31 | item.isCheck = temp.isCheck
32 | item.size = temp.size
33 | item.color = temp.color
34 | }
35 |
36 | return item
37 | })
38 |
39 | return newCartInfo.concat(skus)
40 | }
41 |
42 | function delCart (oldCartInfo, skus) {
43 | const newCartInfo = oldCartInfo.filter((item) => {
44 | const temp = skus.filter(sku => { return item.skuId === sku.skuId })[0]
45 | return !temp
46 | })
47 |
48 | return newCartInfo
49 | }
50 |
51 | function checkCart (oldCartInfo, skus) {
52 | // 更新购物车中的商品数据
53 | const newCartInfo = oldCartInfo.map((item) => {
54 | const temp = skus.filter(sku => item.skuId === sku.skuId)[0]
55 | if (temp) {
56 | item.isCheck = true
57 | }
58 | return item
59 | })
60 |
61 | return newCartInfo
62 | }
63 |
64 | function inverseCheckCart (oldCartInfo, skus) {
65 | // 更新购物车中的商品数据
66 | const newCartInfo = oldCartInfo.map((item) => {
67 | const temp = skus.filter(sku => item.skuId === sku.skuId)[0]
68 | if (temp) {
69 | item.isCheck = false
70 | }
71 | return item
72 | })
73 |
74 | return newCartInfo
75 | }
76 |
77 | function changeAttr (oldCartInfo, skus) {
78 | // 更新购物车中的商品数据
79 | const newCartInfo = oldCartInfo.map((item) => {
80 | const temp = skus.filter(sku => item.skuId === sku.skuId)[0]
81 | if (temp) {
82 | item.info.colorInfo.value = temp.color
83 | item.info.sizeInfo.value = temp.size
84 | }
85 | return item
86 | })
87 |
88 | return newCartInfo
89 | }
90 |
91 | async function editCart (db, data) {
92 | const { _id, skus, type } = data
93 | const cartColl = db.collection('cart')
94 |
95 | // 补存num字段
96 | skus.forEach((sku) => {
97 | sku.skuId = sku.skuId + ''
98 | if(!sku.num) { sku.num = 1 }
99 | })
100 |
101 | // 获取当前购物车
102 | const res = await cartColl.doc(_id).field({
103 | cartInfo: true,
104 | shopMap: true
105 | }).get()
106 | const shopMap = res.data[0].shopMap
107 | const oldCartInfo = res.data[0].cartInfo
108 | let newCartInfo
109 |
110 | // 根据type进行相应的购物车操作
111 | switch (type) {
112 | case typeMap['CHANGE_NUM']:
113 | newCartInfo = changCartNum(oldCartInfo, skus)
114 | break
115 | case typeMap['ADD']:
116 | newCartInfo = addCart(oldCartInfo, skus)
117 | break
118 | case typeMap['DEL']:
119 | newCartInfo = delCart(oldCartInfo, skus)
120 | break
121 | case typeMap['CHECK']:
122 | newCartInfo = checkCart(oldCartInfo, skus)
123 | break
124 | case typeMap['INVERT_CHECK']:
125 | newCartInfo = inverseCheckCart(oldCartInfo, skus)
126 | break
127 | case typeMap['CHANGE_ATTR']:
128 | newCartInfo = changeAttr(oldCartInfo, skus)
129 | break
130 | default:
131 | break
132 | }
133 |
134 | // 得到新的购物车数据
135 | const cartData = await getNewCartData({cartInfo: newCartInfo, shopMap})
136 |
137 | // 更新数据
138 | await cartColl.doc(_id).update(cartData)
139 |
140 | return cartData
141 | }
142 |
143 | exports.editCart = editCart
144 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/cart/getCart.js:
--------------------------------------------------------------------------------
1 | async function getCart (db, data) {
2 | const { _id } = data
3 | const cartColl = db.collection('cart')
4 | let cartData = {
5 | _id,
6 | cartNum: 0,
7 | totalPrice: 0,
8 | cartInfo: [],
9 | shopMap: {}
10 | }
11 |
12 | const res = await cartColl.doc(_id).get()
13 | if (res.data.length === 0) {
14 | await cartColl.add(cartData)
15 | } else {
16 | cartData = res.data[0]
17 | }
18 | return cartData
19 | }
20 |
21 | exports.getCart = getCart
22 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/cart/index.js:
--------------------------------------------------------------------------------
1 | const app = require('wx-server-sdk')
2 |
3 | const { getCart } = require('./getCart.js')
4 | const { editCart } = require('./editCart.js')
5 |
6 | app.init({
7 | envName: 'taro-ebook-23bbcb',
8 | mpAppId: 'wx9504f077bdc24ea2'
9 | })
10 |
11 | async function main (event, context) {
12 | const db = app.database()
13 | const { func, data } = event
14 | let res
15 | if (func === 'getCart') {
16 | res = await getCart(db, data).catch(err => console.log(err))
17 | } else if (func === 'editCart') {
18 | res = await editCart(db, data).catch(err => console.log(err))
19 | }
20 |
21 | return {
22 | context,
23 | data: res
24 | }
25 | }
26 |
27 | exports.main = main
28 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/cart/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "wx-server-sdk": "^0.2.1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/cart/utils.js:
--------------------------------------------------------------------------------
1 | const app = require('tcb-admin-node')
2 |
3 | app.init({
4 | envName: 'taro-ebook-23bbcb',
5 | mpAppId: 'wx9504f077bdc24ea2',
6 | })
7 |
8 | const typeMap = {
9 | ADD: '2',
10 | CHANGE_NUM: '3',
11 | DEL: '4',
12 | CHECK: '5',
13 | INVERT_CHECK: '6',
14 | CHANGE_ATTR: '8'
15 | }
16 |
17 | async function getNewCartData ({cartInfo, shopMap}) {
18 | const db = app.database()
19 | const comColl = db.collection('commodity')
20 | const shopColl = db.collection('shop')
21 |
22 | const newShopMap = {}
23 | const allCartInfoData = await Promise.all(cartInfo.map(async (item) => {
24 | let newItem = item
25 |
26 | // 如果没有商品的具体信息
27 | if (!item.info) {
28 | // 获得商品的具体信息
29 | let allItemData = await comColl.doc(item.skuId).get()
30 | allItemData = allItemData.data[0]
31 |
32 | // 加上venderId
33 | if (!item.venderId) { item.venderId = allItemData.venderId }
34 | item.venderId += ''
35 |
36 | // 更改尺寸
37 | if (item.size) {
38 | allItemData.sizeInfo.value = item.size
39 | }
40 |
41 | // 更改颜色
42 | if (item.color) {
43 | allItemData.colorInfo.value = item.color
44 | }
45 |
46 | // 判定是否被选中
47 | if (!item.isCheck) { item.isCheck = false }
48 |
49 | newItem = Object.assign({}, item, { info: allItemData })
50 | }
51 |
52 | // 获得商店的具体信息
53 | if (!newShopMap[newItem.venderId]) {
54 | // 先找下有没有缓存,不用再查数据库
55 | if (!shopMap[newItem.venderId]) {
56 | let shopInfo = await shopColl.doc(newItem.venderId).field({
57 | thumbnail: true,
58 | title: true,
59 | venderId: true
60 | }).get()
61 | shopInfo = shopInfo.data[0]
62 | newShopMap[newItem.venderId] = shopInfo
63 | } else {
64 | newShopMap[newItem.venderId] = shopMap[newItem.venderId]
65 | }
66 | }
67 |
68 | return newItem
69 | }))
70 |
71 | const cartData = {
72 | cartNum: 0,
73 | totalPrice: 0,
74 | cartInfo: allCartInfoData,
75 | shopMap: [newShopMap]
76 | }
77 |
78 | allCartInfoData.forEach((item) => {
79 | cartData.cartNum += item.num
80 | if (item.isCheck) {
81 | cartData.totalPrice += item.num * parseInt(item.info.price)
82 | }
83 | })
84 |
85 | return cartData
86 | }
87 |
88 | module.exports = {
89 | typeMap,
90 | getNewCartData
91 | }
92 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/order/addOrder.js:
--------------------------------------------------------------------------------
1 | async function addOrder (db, data) {
2 | const { _id, freightPrice = 14, payType = 4 } = data
3 | const _ = db.command
4 | const orderColl = db.collection('order')
5 | const cartColl = db.collection('cart')
6 |
7 | let cartData = await cartColl.doc(_id).get()
8 | cartData = cartData.data[0]
9 |
10 | // 获取购物车中被选中的数据
11 | const payInfo = cartData.cartInfo.filter((item) => {
12 | return item.isCheck
13 | })
14 |
15 | // 使用新的商品map
16 | const oldShopMap = cartData.shopMap[0]
17 | const newShop = {}
18 | payInfo.forEach(item => {
19 | newShop[item.venderId] = oldShopMap[item.venderId]
20 | })
21 |
22 | if (payInfo.length === 0) {
23 | return {
24 | code: -1,
25 | msg: '购物车中没有勾选物品'
26 | }
27 | }
28 |
29 | const orderId = Math.random().toString(36).substr(2)
30 |
31 | const orderData = {
32 | _id: orderId,
33 | dateSubmit: db.serverDate(),
34 | orderId,
35 | orderState: 1,
36 | ownerId: _id,
37 | payType,
38 | shopInfo: newShop,
39 | shouldPayPrice: cartData.totalPrice + freightPrice,
40 | skuInfoList: payInfo,
41 | cancelReasonText: '提交申请'
42 | }
43 |
44 | // 新插入订单
45 | await orderColl.add(orderData).catch(err => console.log(err))
46 |
47 | // 购物车中除移生成了订单的商品
48 | let newCartNum = 0
49 | let newCartShopMap = {}
50 | const newCartInfo = cartData.cartInfo.filter((item) => {
51 | if (!item.isCheck) {
52 | newCartShopMap[item.venderId] = oldShopMap[item.venderId]
53 | newCartNum += item.num
54 | return true
55 | }
56 | return false
57 | })
58 |
59 | await cartColl.doc(_id).update({
60 | cartInfo: newCartInfo,
61 | cartNum: newCartNum,
62 | shopMap: [newCartShopMap],
63 | totalPrice: 0
64 | })
65 |
66 | return {
67 | code: 0,
68 | msg: '成功生成订单',
69 | data: orderData
70 | }
71 | }
72 |
73 | exports.addOrder = addOrder
74 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/order/cancelOrder.js:
--------------------------------------------------------------------------------
1 | async function cancelOrder ( db, data) {
2 | const { orderId, cancelReasonText } = data
3 | const orderColl = db.collection('order')
4 | const _ = db.command
5 |
6 | await orderColl.doc(orderId).update({
7 | orderState: -1,
8 | cancelReasonText
9 | })
10 |
11 | return {
12 | code: 0,
13 | msg: '成功取消订单'
14 | }
15 | }
16 |
17 | exports.cancelOrder = cancelOrder
18 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/order/getBalance.js:
--------------------------------------------------------------------------------
1 | async function getBalance (app, data) {
2 | const { _id } = data
3 | const res = await app.callFunction({
4 | name: 'cart',
5 | data: {
6 | func: 'getCart',
7 | data: {
8 | _id
9 | }
10 | }
11 | })
12 | const cartData = res.result.data
13 | const payInfo = cartData.cartInfo.filter((item) => {
14 | return item.isCheck
15 | })
16 |
17 | const balanceData = {
18 | isNeedBanlance: payInfo.length !== 0,
19 | payInfo,
20 | shopMap: cartData.shopMap,
21 | totalPrice: cartData.totalPrice
22 | }
23 |
24 | return balanceData
25 | }
26 |
27 | exports.getBalance = getBalance
28 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/order/getOrder.js:
--------------------------------------------------------------------------------
1 | async function getOrder (db, data) {
2 | const { _id } = data
3 | const orderColl = db.collection('order')
4 | const _ = db.command
5 |
6 | const res = await orderColl.where({
7 | ownerId: _.eq(_id)
8 | }).orderBy('dateSubmit', 'desc').get()
9 |
10 | const orderData = res.data
11 |
12 | return orderData
13 | }
14 |
15 | exports.getOrder = getOrder
16 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/order/getOrderDetail.js:
--------------------------------------------------------------------------------
1 | async function getOrderDetail (db, data) {
2 | const { _id, orderId } = data
3 | const orderColl = db.collection('order')
4 | const _ = db.command
5 |
6 | const res = await orderColl.where({
7 | ownerId: _.eq(_id),
8 | orderId: _.eq(orderId)
9 | }).get()
10 |
11 | const orderData = res.data[0]
12 |
13 | return orderData
14 | }
15 |
16 | exports.getOrderDetail = getOrderDetail
17 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/order/index.js:
--------------------------------------------------------------------------------
1 | const app = require('wx-server-sdk')
2 |
3 | const { getBalance } = require('./getBalance.js')
4 | const { addOrder } = require('./addOrder.js')
5 | const { getOrder } = require('./getOrder.js')
6 | const { cancelOrder } = require('./cancelOrder.js')
7 | const { getOrderDetail } = require('./getOrderDetail.js')
8 |
9 | app.init({
10 | envName: 'taro-ebook-23bbcb',
11 | mpAppId: 'wx9504f077bdc24ea2',
12 | // secretId: 'AKIDuA6QxlhN9619IeT2y45S8tmCvRtnubjs',
13 | // secretKey: 'qXW08RurtFSb6YYZs73DvEQ1qmEFSDIJ',
14 | // sessionToken: '4431b3f2da2e54cdce7c85a8714b8abb63ca397340001'
15 | })
16 |
17 | async function main (event, context) {
18 | const db = app.database()
19 | const { func, data } = event
20 | let res
21 | if (func === 'getBalance') {
22 | res = await getBalance(app, data)
23 | } else if (func === 'addOrder') {
24 | res = await addOrder(db, data)
25 | } else if (func === 'getOrder') {
26 | res = await getOrder(db, data)
27 | } else if (func === 'getOrderDetail') {
28 | res = await getOrderDetail(db, data)
29 | } else if (func === 'cancelOrder') {
30 | res = await cancelOrder(db, data)
31 | }
32 |
33 | return {
34 | data: res
35 | }
36 | }
37 |
38 | exports.main = main
39 |
40 | // // 测试的函数
41 | // async function test (params) {
42 | // const res = await main({
43 | // func: 'getOrder',
44 | // data: {
45 | // _id: 'oFQSH5MekinNSc_yqH9dNlmKh6vI'
46 | // }
47 | // })
48 |
49 | // console.log(res)
50 | // }
51 |
52 | // test()
53 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/order/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "wx-server-sdk": "^0.2.1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/search/getList.js:
--------------------------------------------------------------------------------
1 | async function getList (db, data) {
2 | const commColl = db.collection('commodity')
3 | const _ = db.command
4 |
5 | const allGoods = await commColl.get()
6 | let res = {}
7 | let searchGoods = allGoods.data.filter(item => {
8 | return item.skuName.indexOf(data.keyWords) > -1
9 | })
10 | res.wares = searchGoods
11 | res.count = searchGoods.length
12 | res.page = data.page
13 | return res
14 | }
15 |
16 | exports.getList = getList
17 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/search/index.js:
--------------------------------------------------------------------------------
1 | const app = require('wx-server-sdk')
2 |
3 | const { getList } = require('./getList.js')
4 |
5 | app.init({
6 | envName: 'taro-ebook-23bbcb',
7 | mpAppId: 'wx9504f077bdc24ea2',
8 | })
9 |
10 | exports.main = async (event, context) => {
11 | const db = app.database()
12 | const { func, data } = event
13 | let res
14 | if (func === 'getList') {
15 | res = await getList(db, data)
16 | }
17 | return {
18 | context,
19 | data: res
20 | }
21 | }
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/search/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "wx-server-sdk": "^0.2.1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/shop/getInformation.js:
--------------------------------------------------------------------------------
1 | async function getInformation (db) {
2 | const collection = db.collection('information')
3 | const res = await collection.get()
4 | return res.data
5 | }
6 |
7 | exports.getInformation = getInformation
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/shop/getShop.js:
--------------------------------------------------------------------------------
1 | async function getShop (db, venderId) {
2 | const shopColl = db.collection('shop')
3 | const commColl = db.collection('commodity')
4 | const _ = db.command
5 |
6 | const res = await shopColl.where({
7 | venderId: _.eq(Number(venderId))
8 | }).get()
9 |
10 | const shopData = res.data[0]
11 | const floors = await Promise.all(shopData.floors.map(async (floor) => {
12 | let res = await commColl.where({
13 | skuId: _.in(floor.commodities)
14 | }).get()
15 | floor.commodities = res.data
16 | return floor
17 | }))
18 | shopData.floors = floors
19 |
20 | return shopData
21 | }
22 |
23 | exports.getShop = getShop
24 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/shop/getSku.js:
--------------------------------------------------------------------------------
1 | async function getSku (db, skuId) {
2 | const commColl = db.collection('commodity')
3 | const res = await commColl.doc(skuId).get()
4 | console.log(res)
5 | return res.data
6 | }
7 |
8 | exports.getSku = getSku
9 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/shop/index.js:
--------------------------------------------------------------------------------
1 | const app = require('wx-server-sdk')
2 |
3 | const { getInformation } = require('./getInformation.js')
4 | const { getShop } = require('./getShop.js')
5 | const { getSku } = require('./getSku.js')
6 |
7 | app.init({
8 | envName: 'taro-ebook-23bbcb',
9 | mpAppId: 'wx9504f077bdc24ea2'
10 | })
11 |
12 | async function main (event, context) {
13 | const db = app.database()
14 | const { func, data } = event
15 | let res
16 | if (func === 'getInformation') {
17 | res = await getInformation(db)
18 | } else if (func === 'getShop') {
19 | res = await getShop(db, data)
20 | } else if (func === 'getSku'){
21 | res = await getSku(db, data)
22 | }
23 |
24 | return {
25 | context,
26 | data: res
27 | }
28 | }
29 |
30 | exports.main = main
31 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/shop/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "wx-server-sdk": "^0.2.1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/user/addUser.js:
--------------------------------------------------------------------------------
1 | async function addUser (db, userInfo) {
2 | const collection = db.collection('user')
3 | await collection.doc(userInfo._id).set(userInfo)
4 | return userInfo
5 | }
6 |
7 | exports.addUser = addUser
8 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/user/getUser.js:
--------------------------------------------------------------------------------
1 | async function getUser (db, _openid) {
2 | const _ = db.command
3 | const collection = db.collection('user')
4 | const user = await collection.where({
5 | _openid: _.eq(_openid)
6 | })
7 |
8 | return user
9 | }
10 |
11 | exports.getUser = getUser
12 |
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/user/index.js:
--------------------------------------------------------------------------------
1 | const app = require('wx-server-sdk')
2 |
3 | const { addUser } = require('./addUser.js')
4 | const { getUser } = require('./getUser.js')
5 |
6 | app.init({
7 | envName: 'taro-ebook-23bbcb',
8 | mpAppId: 'wx9504f077bdc24ea2'
9 | })
10 |
11 | exports.main = async (event, context) => {
12 | const db = app.database()
13 | const { func, data } = event
14 | let res
15 | if (func === 'addUser') {
16 | res = await addUser(db, data)
17 | } else if (func === 'getUser') {
18 | res = await getUser(db, data)
19 | } else if (func === 'getOpenId') {
20 | res = event.userInfo
21 | }
22 |
23 | return {
24 | data: res
25 | }
26 | }
--------------------------------------------------------------------------------
/taro-demo/cloud/functions/user/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "wx-server-sdk": "^0.2.1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/taro-demo/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "description",
3 | "packOptions": {
4 | "ignore": [
5 | "server",
6 | "cloud"
7 | ]
8 | },
9 | "setting": {
10 | "urlCheck": false,
11 | "es6": false,
12 | "postcss": false,
13 | "minified": false,
14 | "newFeature": true
15 | },
16 | "compileType": "miniprogram",
17 | "libVersion": "2.6.2",
18 | "appid": "wx9504f077bdc24ea2",
19 | "projectname": "%E6%8E%98%E9%87%91%E5%B0%8F%E5%86%8Cdemo",
20 | "isGameTourist": false,
21 | "miniprogramRoot": "client/dist/",
22 | "cloudfunctionRoot": "cloud/functions/",
23 | "condition": {
24 | "search": {
25 | "current": -1,
26 | "list": []
27 | },
28 | "conversation": {
29 | "current": -1,
30 | "list": []
31 | },
32 | "plugin": {
33 | "current": -1,
34 | "list": []
35 | },
36 | "game": {
37 | "currentL": -1,
38 | "list": []
39 | },
40 | "miniprogram": {
41 | "current": 7,
42 | "list": [
43 | {
44 | "id": -1,
45 | "name": "shop",
46 | "pathName": "pages/shop/shop",
47 | "query": "venderId=1"
48 | },
49 | {
50 | "id": 1,
51 | "name": "cart",
52 | "pathName": "pages/cart/cart",
53 | "query": ""
54 | },
55 | {
56 | "id": -1,
57 | "name": "cloud",
58 | "pathName": "pages/cloud/cloud",
59 | "query": ""
60 | },
61 | {
62 | "id": 3,
63 | "name": "detail",
64 | "pathName": "pages/detail/detail",
65 | "query": "skuId=1"
66 | },
67 | {
68 | "id": -1,
69 | "name": "cart_sub",
70 | "pathName": "pages/cart/cart_sub",
71 | "query": "2"
72 | },
73 | {
74 | "id": 5,
75 | "name": "结算页",
76 | "pathName": "pages/balance/balance",
77 | "query": ""
78 | },
79 | {
80 | "id": 6,
81 | "name": "order",
82 | "pathName": "pages/user/order/list/list",
83 | "query": "",
84 | "scene": null
85 | },
86 | {
87 | "id": 7,
88 | "name": "orderDetail",
89 | "pathName": "pages/user/order/detail/detail",
90 | "query": "orderId=o6zt3qslcj&__key_=15535015457221",
91 | "scene": null
92 | }
93 | ]
94 | }
95 | }
96 | }
--------------------------------------------------------------------------------
/taro-demo/tcb.json:
--------------------------------------------------------------------------------
1 | {
2 | "mpappid": "wx9504f077bdc24ea2",
3 | "env": "taro-ebook-23bbcb",
4 | "secretid": "AKIDhIyd705LQxzJBN1lYYVQzhbmLrMy7Btf",
5 | "secretkey": "7wfqvN7OLXRZihYgrUNabufu178hWvLX",
6 | "path": {
7 | "storage": "./cloud/storage",
8 | "database": "./cloud/database",
9 | "functions": "./cloud/functions"
10 | }
11 | }
--------------------------------------------------------------------------------
/todoList-Redux/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/todoList-Redux/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["taro"],
3 | "rules": {
4 | "no-unused-vars": ["error", { "varsIgnorePattern": "Taro" }],
5 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx"] }]
6 | },
7 | "parser": "babel-eslint"
8 | }
9 |
--------------------------------------------------------------------------------
/todoList-Redux/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | .temp/
3 | .rn_temp/
4 | node_modules/
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/todoList-Redux/config/dev.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | NODE_ENV: '"development"'
4 | },
5 | defineConstants: {
6 | },
7 | weapp: {},
8 | h5: {}
9 | }
10 |
--------------------------------------------------------------------------------
/todoList-Redux/config/index.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | projectName: 'todos',
3 | date: '2018-6-12',
4 | designWidth: 750,
5 | sourceRoot: 'src',
6 | outputRoot: 'dist',
7 | plugins: {
8 | babel: {
9 | sourceMap: true,
10 | presets: [
11 | 'env'
12 | ],
13 | plugins: [
14 | 'transform-class-properties',
15 | 'transform-decorators-legacy',
16 | 'transform-object-rest-spread'
17 | ]
18 | },
19 | },
20 | defineConstants: {
21 | },
22 | weapp: {
23 |
24 | },
25 | h5: {
26 | publicPath: '/',
27 | staticDirectory: 'static',
28 | module: {
29 | postcss: {
30 | autoprefixer: {
31 | enable: true
32 | }
33 | }
34 | }
35 | }
36 | }
37 |
38 | module.exports = function (merge) {
39 | if (process.env.NODE_ENV === 'development') {
40 | return merge({}, config, require('./dev'))
41 | }
42 | return merge({}, config, require('./prod'))
43 | }
44 |
--------------------------------------------------------------------------------
/todoList-Redux/config/prod.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | NODE_ENV: '"production"'
4 | },
5 | defineConstants: {
6 | },
7 | weapp: {},
8 | h5: {}
9 | }
10 |
--------------------------------------------------------------------------------
/todoList-Redux/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todos",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "taro 集成 redux 例子",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "author": "",
11 | "license": "MIT",
12 | "dependencies": {
13 | "@tarojs/components": "1.1.4",
14 | "@tarojs/redux": "1.1.4",
15 | "@tarojs/router": "1.1.4",
16 | "@tarojs/taro": "1.1.4",
17 | "@tarojs/taro-h5": "1.1.4",
18 | "@tarojs/taro-weapp": "1.1.4",
19 | "nervjs": "^1.2.18",
20 | "redux": "^4.0.0",
21 | "redux-action": "^1.2.2",
22 | "redux-logger": "^3.0.6",
23 | "redux-thunk": "^2.3.0"
24 | },
25 | "devDependencies": {
26 | "@tarojs/plugin-babel": "1.1.4",
27 | "@tarojs/plugin-csso": "1.1.4",
28 | "@tarojs/plugin-sass": "1.1.4",
29 | "@tarojs/plugin-uglifyjs": "1.1.4",
30 | "@tarojs/webpack-runner": "1.1.4",
31 | "babel-plugin-transform-class-properties": "^6.24.1",
32 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
33 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
34 | "babel-preset-env": "^1.6.1"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/todoList-Redux/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "miniprogramRoot": "./dist",
3 | "projectname": "todoList",
4 | "description": "todo List",
5 | "appid": "touristappid",
6 | "setting": {
7 | "urlCheck": true,
8 | "es6": false,
9 | "postcss": false,
10 | "minified": false
11 | },
12 | "compileType": "miniprogram"
13 | }
14 |
--------------------------------------------------------------------------------
/todoList-Redux/src/actions/index.js:
--------------------------------------------------------------------------------
1 | import { ADD, DELETE } from '../constants/todos'
2 |
3 | export const add = (data) => {
4 | return {
5 | data,
6 | type: ADD
7 | }
8 | }
9 |
10 | export const del = (data) => {
11 | return {
12 | data,
13 | type: DELETE
14 | }
15 | }
--------------------------------------------------------------------------------
/todoList-Redux/src/app.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { Provider } from '@tarojs/redux'
3 |
4 | import configStore from './store'
5 | import Index from './pages/index'
6 |
7 | import './app.scss'
8 |
9 | const store = configStore()
10 |
11 | class App extends Component {
12 | config = {
13 | pages: [
14 | 'pages/index/index'
15 | ],
16 | window: {
17 | backgroundTextStyle: 'light',
18 | navigationBarBackgroundColor: '#fff',
19 | navigationBarTitleText: 'WeChat',
20 | navigationBarTextStyle: 'black'
21 | }
22 | }
23 |
24 | componentDidMount () {}
25 |
26 | componentDidShow () {}
27 |
28 | componentDidHide () {}
29 |
30 | componentCatchError () {}
31 |
32 | render () {
33 | return (
34 |
35 |
36 |
37 | )
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/todoList-Redux/src/app.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/todoList-Redux/src/app.scss
--------------------------------------------------------------------------------
/todoList-Redux/src/constants/todos.js:
--------------------------------------------------------------------------------
1 | export const ADD = 'ADD'
2 | export const DELETE = 'DELETE'
--------------------------------------------------------------------------------
/todoList-Redux/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Taro
8 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/todoList-Redux/src/pages/index/index.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Input, Text } from '@tarojs/components'
3 | import { connect } from '@tarojs/redux'
4 | import './index.scss'
5 |
6 | import { add, del } from '../../actions/index'
7 |
8 | class Index extends Component {
9 | config = {
10 | navigationBarTitleText: '首页'
11 | }
12 |
13 | constructor () {
14 | super ()
15 |
16 | this.state = {
17 | newTodo: ''
18 | }
19 | }
20 |
21 | componentDidMount () {
22 |
23 | }
24 |
25 | saveNewTodo (e) {
26 | let { newTodo } = this.state
27 | if (!e.detail.value || e.detail.value === newTodo) return
28 |
29 | this.setState({
30 | newTodo: e.detail.value
31 | })
32 | }
33 |
34 | addTodo () {
35 | let { newTodo } = this.state
36 | let { add } = this.props
37 |
38 | if (!newTodo) return
39 |
40 | add(newTodo)
41 | this.setState({
42 | newTodo: ''
43 | })
44 | }
45 |
46 | delTodo (id) {
47 | let { del } = this.props
48 | del(id)
49 | }
50 |
51 | render () {
52 | // 获取未经处理的todos并展示
53 | let { newTodo } = this.state
54 | let { todos, add, del } = this.props
55 |
56 | const todosJsx = todos.map(todo => {
57 | return (
58 | {todo.text}-
59 | )
60 | })
61 |
62 | return (
63 |
64 |
65 |
66 | +
67 |
68 | { todosJsx }
69 |
70 | )
71 | }
72 | }
73 |
74 | export default connect (({ todos }) => ({
75 | todos: todos.todos
76 | }), (dispatch) => ({
77 | add (data) {
78 | dispatch(add(data))
79 | },
80 | del (id) {
81 | dispatch(del(id))
82 | }
83 | }))(Index)
84 |
85 |
--------------------------------------------------------------------------------
/todoList-Redux/src/pages/index/index.scss:
--------------------------------------------------------------------------------
1 | .todos {
2 | padding: 20px 40px;
3 | font-size: 30px;
4 | line-height: 36px;
5 |
6 | &_item {
7 | margin-top: 20px;
8 | }
9 |
10 | .add_wrap {
11 | margin-bottom: 40px;
12 | overflow: hidden;
13 | }
14 |
15 | input {
16 | width: 576px;
17 | float: left;
18 | border: 1px solid #999;
19 | border-right: none;
20 | padding-left: 20px;
21 | }
22 |
23 | .del,
24 | .add {
25 | float: right;
26 | border: 1px solid #999;
27 | padding: 0 25px;
28 | background: #999;
29 | color: #fff;
30 | }
31 |
32 | .add {
33 | float: left;
34 | line-height: 52px;
35 | }
36 | }
--------------------------------------------------------------------------------
/todoList-Redux/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux'
2 | import { ADD, DELETE } from '../constants/todos'
3 |
4 | const INITIAL_STATE = {
5 | todos: [
6 | {id: 0, text: '第一条todo'}
7 | ]
8 | }
9 |
10 | function todos (state = INITIAL_STATE, action) {
11 | // 获取当前todos条数,用以id自增
12 | let todoNum = state.todos.length
13 |
14 | switch (action.type) {
15 | case ADD:
16 | return {
17 | ...state,
18 | todos: state.todos.concat({
19 | id: todoNum,
20 | text: action.data
21 | })
22 | }
23 | case DELETE:
24 | let newTodos = state.todos.filter(item => {
25 | return item.id !== action.data
26 | })
27 |
28 | return {
29 | ...state,
30 | todos: newTodos
31 | }
32 | default:
33 | return state
34 | }
35 | }
36 |
37 | export default combineReducers({
38 | todos
39 | })
--------------------------------------------------------------------------------
/todoList-Redux/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux'
2 |
3 | // 引入需要的中间件
4 | import thunkMiddleware from 'redux-thunk'
5 | import { createLogger } from 'redux-logger'
6 |
7 | // 引入根reducers
8 | import rootReducer from '../reducers'
9 |
10 | const middlewares = [
11 | thunkMiddleware,
12 | createLogger()
13 | ]
14 |
15 | // 创建store
16 | export default function configStore () {
17 | const store = createStore(rootReducer, applyMiddleware(...middlewares))
18 | return store
19 | }
20 |
--------------------------------------------------------------------------------
/todoList/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/todoList/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["taro"],
3 | "rules": {
4 | "no-unused-vars": ["error", { "varsIgnorePattern": "Taro" }],
5 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx"] }]
6 | },
7 | "parser": "babel-eslint"
8 | }
9 |
--------------------------------------------------------------------------------
/todoList/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | .temp/
3 | .rn_temp/
4 | node_modules/
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/todoList/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://r.cnpmjs.org
2 | disturl=https://r.cnpmjs.org/node
3 | sass_binary_site=https://r.cnpmjs.org/node-sass/
4 | fse_binary_host_mirror=https://r.cnpmjs.org/fsevents
5 |
--------------------------------------------------------------------------------
/todoList/config/dev.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | NODE_ENV: '"development"'
4 | },
5 | defineConstants: {
6 | },
7 | weapp: {},
8 | h5: {}
9 | }
10 |
--------------------------------------------------------------------------------
/todoList/config/index.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | projectName: 'todoList',
3 | date: '2018-11-12',
4 | designWidth: 750,
5 | deviceRatio: {
6 | '640': 2.34 / 2,
7 | '750': 1,
8 | '828': 1.81 / 2
9 | },
10 | sourceRoot: 'src',
11 | outputRoot: 'dist',
12 | plugins: {
13 | babel: {
14 | sourceMap: true,
15 | presets: [
16 | 'env'
17 | ],
18 | plugins: [
19 | 'transform-class-properties',
20 | 'transform-decorators-legacy',
21 | 'transform-object-rest-spread'
22 | ]
23 | }
24 | },
25 | defineConstants: {
26 | },
27 | copy: {
28 | patterns: [
29 | ],
30 | options: {
31 | }
32 | },
33 | weapp: {
34 | module: {
35 | postcss: {
36 | autoprefixer: {
37 | enable: true
38 | },
39 | url: {
40 | enable: true,
41 | limit: 10240
42 | }
43 | }
44 | }
45 | },
46 | h5: {
47 | publicPath: '/',
48 | staticDirectory: 'static',
49 | module: {
50 | postcss: {
51 | autoprefixer: {
52 | enable: true
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
59 | module.exports = function (merge) {
60 | if (process.env.NODE_ENV === 'development') {
61 | return merge({}, config, require('./dev'))
62 | }
63 | return merge({}, config, require('./prod'))
64 | }
65 |
--------------------------------------------------------------------------------
/todoList/config/prod.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | NODE_ENV: '"production"'
4 | },
5 | defineConstants: {
6 | },
7 | weapp: {},
8 | h5: {}
9 | }
10 |
--------------------------------------------------------------------------------
/todoList/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todoList",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "todo List",
6 | "scripts": {
7 | "build:weapp": "taro build --type weapp",
8 | "build:swan": "taro build --type swan",
9 | "build:alipay": "taro build --type alipay",
10 | "build:h5": "taro build --type h5",
11 | "build:rn": "taro build --type rn",
12 | "dev:weapp": "npm run build:weapp -- --watch",
13 | "dev:swan": "npm run build:swan -- --watch",
14 | "dev:alipay": "npm run build:alipay -- --watch",
15 | "dev:h5": "npm run build:h5 -- --watch",
16 | "dev:rn": "npm run build:rn -- --watch"
17 | },
18 | "author": "",
19 | "license": "MIT",
20 | "dependencies": {
21 | "@tarojs/components": "^1.1.4",
22 | "@tarojs/router": "^1.1.4",
23 | "@tarojs/taro": "^1.1.4",
24 | "@tarojs/taro-alipay": "^1.1.4",
25 | "@tarojs/taro-h5": "^1.1.4",
26 | "@tarojs/taro-swan": "^1.1.4",
27 | "@tarojs/taro-weapp": "^1.1.4",
28 | "nervjs": "^1.3.5"
29 | },
30 | "devDependencies": {
31 | "@types/react": "^16.4.6",
32 | "@types/webpack-env": "^1.13.6",
33 | "@tarojs/plugin-babel": "^1.1.4",
34 | "@tarojs/plugin-csso": "^1.1.4",
35 | "@tarojs/plugin-sass": "^1.1.4",
36 | "@tarojs/plugin-uglifyjs": "^1.1.4",
37 | "@tarojs/webpack-runner": "^1.1.4",
38 | "babel-plugin-transform-class-properties": "^6.24.1",
39 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
40 | "babel-plugin-transform-jsx-stylesheet": "^0.6.5",
41 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
42 | "babel-preset-env": "^1.6.1",
43 | "babel-eslint": "^8.2.3",
44 | "eslint": "^4.19.1",
45 | "eslint-config-taro": "^1.1.4",
46 | "eslint-plugin-react": "^7.8.2",
47 | "eslint-plugin-import": "^2.12.0",
48 | "eslint-plugin-taro": "^1.1.4"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/todoList/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "miniprogramRoot": "dist/",
3 | "projectname": "todoList_simple",
4 | "description": "todo List",
5 | "appid": "touristappid",
6 | "setting": {
7 | "urlCheck": true,
8 | "es6": false,
9 | "postcss": false,
10 | "minified": false,
11 | "newFeature": true
12 | },
13 | "compileType": "miniprogram",
14 | "condition": {}
15 | }
--------------------------------------------------------------------------------
/todoList/src/app.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import Index from './pages/index'
3 |
4 | import './app.scss'
5 |
6 | class App extends Component {
7 |
8 | config = {
9 | pages: [
10 | 'pages/index/index'
11 | ],
12 | window: {
13 | backgroundTextStyle: 'light',
14 | navigationBarBackgroundColor: '#fff',
15 | navigationBarTitleText: 'WeChat',
16 | navigationBarTextStyle: 'black'
17 | }
18 | }
19 |
20 | componentDidMount () {}
21 |
22 | componentDidShow () {}
23 |
24 | componentDidHide () {}
25 |
26 | componentDidCatchError () {}
27 |
28 | // 在 App 类中的 render() 函数没有实际作用
29 | // 请勿修改此函数
30 | render () {
31 | return (
32 |
33 | )
34 | }
35 | }
36 |
37 | Taro.render(, document.getElementById('app'))
38 |
--------------------------------------------------------------------------------
/todoList/src/app.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/o2team/taro-ebook-source/ed7772e1921de9e01865d250761bcd302cede18d/todoList/src/app.scss
--------------------------------------------------------------------------------
/todoList/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Taro
12 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/todoList/src/pages/index/index.js:
--------------------------------------------------------------------------------
1 | import Taro, { Component } from '@tarojs/taro'
2 | import { View, Text, Input } from '@tarojs/components'
3 | import './index.scss'
4 |
5 | export default class Index extends Component {
6 | config = {
7 | navigationBarTitleText: '首页'
8 | }
9 |
10 | constructor (props) {
11 | super (props)
12 | this.state = {
13 | // 创建一个初始的 Todolist
14 | list: [
15 | 'get up',
16 | 'coding',
17 | 'sleep',
18 | ],
19 | inputVal: ''
20 | }
21 | }
22 |
23 | // ... 生命周期函数,暂时不需要关注
24 |
25 | addItem () {
26 | let { list, inputVal } = this.state
27 | if (inputVal == '') return
28 | list.push(inputVal)
29 | this.setState({
30 | list,
31 | inputVal: ''
32 | })
33 | }
34 |
35 | delItem (index) {
36 | let { list } = this.state
37 | list.splice(index, 1)
38 | this.setState({
39 | list
40 | })
41 | }
42 |
43 | inputHandler (e) {
44 | this.setState({ inputVal: e.target.value })
45 | }
46 |
47 | render () {
48 | let { list, inputVal } = this.state
49 |
50 | return (
51 |
52 |
53 | 添加
54 |
55 | Todo list
56 | {
57 | list.map((item, index) => {
58 | return
59 | {index + 1}.{item}
60 | 删除
61 |
62 | })
63 | }
64 |
65 |
66 | )
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/todoList/src/pages/index/index.scss:
--------------------------------------------------------------------------------
1 | .input {
2 | display: inline-block;
3 | margin: 20px;
4 | border: 1px solid #666;
5 | width: 500px;
6 | vertical-align: middle;
7 | }
8 | .list_wrap {
9 | padding: 50px 20px;
10 | }
11 | .list {
12 | margin: 20px 0;
13 | }
14 | .add,
15 | .del {
16 | display: inline-block;
17 | width: 120px;
18 | height: 60px;
19 | margin: 0 10px;
20 | padding: 0 10px;
21 | color: #333;
22 | font-size: 22px;
23 | line-height: 60px;
24 | text-align: center;
25 | border-radius: 10px;
26 | border: 1px solid #C5D9E8;
27 | box-sizing: border-box;
28 | overflow: hidden;
29 | text-overflow: ellipsis;
30 | white-space: nowrap;
31 | justify-content: center;
32 | vertical-align: middle;
33 | }
34 | .add {
35 | background-color: #5c89e4;
36 | color: #fff;
37 | border: 1PX solid #5c89e4;
38 | }
39 | .del {
40 | background-color: #fff;
41 | color: #5c89e4;
42 | border: 1PX solid #5c89e4;
43 | margin-left: 100px;
44 | }
45 |
--------------------------------------------------------------------------------