├── .editorconfig
├── .env
├── .eslintrc
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .umirc.js
├── Readme.md
├── mock
├── .gitkeep
└── home.js
├── package.json
└── src
├── DINPro-Bold.eot
├── DINPro-Bold.svg
├── DINPro-Bold.ttf
├── DINPro-Bold.woff
├── DINPro-Bold.woff2
├── assets
├── 2c3968e33e2342feaa9fa3695b2e169e.png
├── 5a28b40bc60057c40a000005.png
├── 5a28ef0d575a970000000039.png
├── default-pic.png
├── icon-classify.png
├── recycleH5_01.png
├── recycleH5_02.png
├── recycleH5_03.png
├── recycleH5_04.png
├── recycleH5_05.png
├── recycleH5_06.png
├── recycleH5_07.png
├── recycleH5_10.png
├── recycleH5_11.png
├── recycleH5_13.png
├── recycleH5_14.png
├── recycleH5_16.png
├── recycleH5_17.png
├── recycleH5_18.png
├── recycleH5_19.png
├── recycleH5_apple.png
├── recycleH5_huawei.png
├── recycleH5_oppo.png
├── recycleH5_vivo.png
├── verify-code.jpg
└── yay.jpg
├── components
├── home-tabbar
│ └── home-tabber-carousel
│ │ ├── index.js
│ │ └── index.less
├── name-card
│ ├── index.js
│ └── index.less
├── order-status-item
│ ├── index.js
│ └── index.less
└── order-status
│ ├── index.js
│ └── index.less
├── dva.js
├── global.css
├── layouts
├── baseLayout
│ ├── baselayout.less
│ └── index.js
├── index.css
└── index.js
├── models
└── .gitkeep
├── pages
├── class
│ ├── index.js
│ └── index.less
├── document.ejs
├── home
│ ├── index.js
│ ├── index.less
│ └── models
│ │ └── home.js
├── index.js
├── login
│ ├── index.js
│ └── index.less
└── my
│ ├── index.js
│ ├── index.less
│ └── models
│ └── my.js
├── services
├── home.js
└── my.js
└── utils
├── authorized.js
├── baseServer.js
├── formValid.js
├── index.js
├── request.js
└── token.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
15 | [Makefile]
16 | indent_style = tab
17 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | BROWSER=none
2 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "eslint-config-umi"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /npm-debug.log*
6 | /yarn-error.log
7 | /yarn.lock
8 | /package-lock.json
9 |
10 | # production
11 |
12 | # misc
13 | .DS_Store
14 |
15 | # umi
16 | .umi
17 | .umi-production
18 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | **/*.md
2 | **/*.svg
3 | **/*.ejs
4 | **/*.html
5 | package.json
6 | .umi
7 | .umi-production
8 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "es5",
4 | "printWidth": 100,
5 | "overrides": [
6 | {
7 | "files": ".prettierrc",
8 | "options": { "parser": "json" }
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/.umirc.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const server = 'http://localhost:3000';
4 |
5 | // ref: https://umijs.org/config/
6 | export default {
7 | plugins: [
8 | // ref: https://umijs.org/plugin/umi-plugin-react.html
9 | ['umi-plugin-react', {
10 | antd: true,
11 | dva: true,
12 | dynamicImport: false,
13 | dll: true,
14 | routes: {
15 | exclude: [
16 | /model\.(j|t)sx?$/,
17 | /service\.(j|t)sx?$/,
18 | /models\//,
19 | /components\//,
20 | /services\//,
21 | ]
22 | },
23 | hardSource: false,
24 | }],
25 | ],
26 | alias:{
27 | components:path.resolve(__dirname,'src/components'),
28 | utils:path.resolve(__dirname,'src/utils'),
29 | services:path.resolve(__dirname,'src/services'),
30 | models:path.resolve(__dirname,'src/models'),
31 | // themes:path.resolve(__dirname,'src/themes'),
32 | images:path.resolve(__dirname,'src/assets')
33 | },
34 | // proxy: {
35 | // "/api": {
36 | // "target": 'http://192.168.2.120:8081',
37 | // "changeOrigin": true,
38 | // "pathRewrite": { "^/api" : "/api" }
39 | // }
40 | // }
41 | }
42 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | ### 推荐安装yarn
2 | 1. 确保 node 版本是 8.10 或以上
3 | 2. npm i yarn -g
4 |
5 | ### 快速开始
6 |
7 | 进入目录安装依赖:
8 |
9 | ```bash
10 | yarn install
11 | ```
12 |
13 | 启动服务.
14 |
15 | ```bash
16 | $ yarn start
17 | ```
18 |
19 | 编译.
20 |
21 | ```bash
22 | $ umi build
23 | ```
24 | ### FAQ
25 | > 如有问题可以参考一下我这篇文章 [umi + dva + ant-design-mobile快速搭建H5项目](https://www.jianshu.com/p/59099cb3e28d),可以在文章中评论区写提问或者直接在简书发信息给我
26 |
--------------------------------------------------------------------------------
/mock/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/mock/.gitkeep
--------------------------------------------------------------------------------
/mock/home.js:
--------------------------------------------------------------------------------
1 | export default {
2 | '/api/home': {
3 | "code":1,
4 | "data":{
5 | "bannerList":[
6 | {
7 | "isShow":1,
8 | "url":null,
9 | "imageUrl":"../../../assets/2c3968e33e2342feaa9fa3695b2e169e.png",
10 | "comment":"仅做展示"}
11 | ],
12 | "productList":[
13 | {
14 | "id":1,
15 | "productName":"苹果 iPhone",
16 | "topPrice":7500,
17 | "imgUrl":"",
18 | },{
19 | "id":2,
20 | "productName":"苹果 iPhone",
21 | "topPrice":2265,
22 | "imgUrl":"",
23 | }
24 | ]
25 | },
26 | "msg":"ok"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "start": "umi dev",
5 | "build": "umi build",
6 | "test": "umi test",
7 | "lint": "",
8 | "precommit": "lint-staged"
9 | },
10 | "devDependencies": {
11 | "antd-pro-server": "^1.0.1",
12 | "babel-eslint": "^9.0.0",
13 | "eslint": "^5.4.0",
14 | "eslint-config-umi": "^0.1.5",
15 | "eslint-plugin-flowtype": "^2.50.0",
16 | "eslint-plugin-import": "^2.14.0",
17 | "eslint-plugin-jsx-a11y": "^5.1.1",
18 | "eslint-plugin-react": "^7.11.1",
19 | "husky": "^0.14.3",
20 | "lint-staged": "^7.2.2",
21 | "mockjs": "^1.0.1-beta3",
22 | "umi": "^2.2.7",
23 | "umi-plugin-react": "^1.1.1"
24 | },
25 | "lint-staged": {
26 | "*.{js,jsx}": [
27 | "eslint --fix",
28 | "git add"
29 | ]
30 | },
31 | "engines": {
32 | "node": ">=8.0.0"
33 | },
34 | "dependencies": {
35 | "classnames": "^2.2.6",
36 | "react-copy-to-clipboard": "^5.0.1",
37 | "react-motion": "^0.5.2",
38 | "react-transition-group": "^2.5.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/DINPro-Bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/DINPro-Bold.eot
--------------------------------------------------------------------------------
/src/DINPro-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/DINPro-Bold.ttf
--------------------------------------------------------------------------------
/src/DINPro-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/DINPro-Bold.woff
--------------------------------------------------------------------------------
/src/DINPro-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/DINPro-Bold.woff2
--------------------------------------------------------------------------------
/src/assets/2c3968e33e2342feaa9fa3695b2e169e.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/2c3968e33e2342feaa9fa3695b2e169e.png
--------------------------------------------------------------------------------
/src/assets/5a28b40bc60057c40a000005.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/5a28b40bc60057c40a000005.png
--------------------------------------------------------------------------------
/src/assets/5a28ef0d575a970000000039.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/5a28ef0d575a970000000039.png
--------------------------------------------------------------------------------
/src/assets/default-pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/default-pic.png
--------------------------------------------------------------------------------
/src/assets/icon-classify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/icon-classify.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_01.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_02.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_03.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_04.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_05.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_06.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_07.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_10.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_11.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_13.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_14.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_16.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_17.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_18.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_19.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_apple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_apple.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_huawei.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_huawei.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_oppo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_oppo.png
--------------------------------------------------------------------------------
/src/assets/recycleH5_vivo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/recycleH5_vivo.png
--------------------------------------------------------------------------------
/src/assets/verify-code.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/verify-code.jpg
--------------------------------------------------------------------------------
/src/assets/yay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/assets/yay.jpg
--------------------------------------------------------------------------------
/src/components/home-tabbar/home-tabber-carousel/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Carousel } from 'antd-mobile';
3 | import styles from './index.less'
4 | import { connect } from 'dva';
5 | import router from 'umi/router';
6 |
7 | class HomeTabbarCarousel extends Component{
8 | constructor(props){
9 | super(props)
10 | this.state = {
11 | data: ['1', '2', '3'],
12 | imgHeight: 176,
13 | slideIndex: 0
14 | }
15 | }
16 | bannerLink(link){
17 | router.push('/class')
18 | }
19 | render() {
20 | const { bannerItem } = this.props;
21 | console.log(bannerItem)
22 | return (
23 |
29 | {(this.props.bannerItem ? this.props.bannerItem : []).map((val,index) => (
30 | this.bannerLink(val.url)}
33 | style={{ display: 'inline-block', width: '100%', height: this.state.imgHeight }}
34 | >
35 |
{
40 | window.dispatchEvent(new Event('resize'));
41 | this.setState({ imgHeight: 'auto' });
42 | }}
43 | />
44 |
45 | ))}
46 |
47 | )
48 | }
49 | }
50 |
51 | export default HomeTabbarCarousel
52 |
--------------------------------------------------------------------------------
/src/components/home-tabbar/home-tabber-carousel/index.less:
--------------------------------------------------------------------------------
1 | .space_carousel {
2 | overflow: hidden;
3 | }
4 | .am-carousel-wrap-dot > span {
5 | display: none;
6 | width: 1rem;
7 | height: 2px;
8 | margin: 0 3px;
9 | border-radius: 1px;
10 | background: #fff;
11 | }
12 | .am-carousel-wrap-dot-active > span {
13 | width: 10px;
14 | height: 2px;
15 | margin: 0 6px;
16 | background: rgb(249, 233, 50);
17 | }
18 | .slider-decorator-0 {
19 | left: 0;
20 | margin-bottom: 5px;
21 | }
22 | .slider-list, .slider-slide{
23 | width: 100% !important;
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/name-card/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Carousel } from 'antd-mobile';
3 | import styles from './index.less'
4 | import { connect } from 'dva';
5 | import router from 'umi/router';
6 | import imgURL from '../../assets/default-pic.png';
7 |
8 | class NameCard extends React.Component {
9 | constructor(props) {
10 | super(props);
11 | }
12 | link() {
13 | router.push('/login');
14 | }
15 | render() {
16 | const avatar = this.props.avatar || imgURL;
17 | if (this.props.notLogin === 1) {
18 | return (
19 |
20 |
21 |

22 |
{this.props.name}
23 |
24 |
25 | )
26 | } else {
27 | return (
28 | this.link()}>
30 |
31 |

32 |
{this.props.name}
33 |
34 |
35 | )
36 | }
37 | }
38 | }
39 |
40 | export default NameCard;
41 |
--------------------------------------------------------------------------------
/src/components/name-card/index.less:
--------------------------------------------------------------------------------
1 | .name_content {
2 | padding: 0 0.3rem;
3 | position: relative;
4 | display: flex;
5 | justify-content: space-between;
6 | height: 2.2rem;
7 | width: 100%;
8 | background: url(../../assets/recycleH5_10.png) no-repeat center center;
9 | background-size: 6.9rem 2.2rem;
10 | align-items: center;
11 | margin: 0 0 0.2rem 0;
12 | .content_card {
13 | display: flex;
14 | align-items: center;
15 | .avatar{
16 | width: 1rem;
17 | height: 1rem;
18 | border: 1px solid #E92B27;
19 | border-radius: 2rem;
20 | margin-left: 0.3rem;
21 | background: #fff;
22 | padding: 10px;
23 | }
24 | .content_name {
25 | font-family: PingFangSC-Medium;
26 | font-size: 0.28rem;
27 | color: #FFFFFF;
28 | letter-spacing: 0;
29 | line-height: 0.28rem;
30 | margin-left: 0.21rem;
31 | }
32 | }
33 | .content_namecard_setting {
34 | background: url(/images/me/setting.png) no-repeat center center;
35 | background-size: cover;
36 | width: 0.32rem;
37 | height: 0.32rem;
38 | background-size: 0.32rem 0.32rem;
39 | padding: 0.5rem 0.3rem 0.5rem 0.5rem;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/components/order-status-item/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'dva';
3 | import styles from './index.less'
4 |
5 | class OrderStatusItem extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | }
9 |
10 | render() {
11 | return (
12 |
13 |
this.props.onStatusClick(e)}>
14 | {this.props.count ? (
15 |
{this.props.count}
16 | ) : (
17 |
18 | )}
19 |

20 |
21 |
{this.props.text}
22 |
23 | );
24 | }
25 | }
26 |
27 | export default OrderStatusItem;
28 |
--------------------------------------------------------------------------------
/src/components/order-status-item/index.less:
--------------------------------------------------------------------------------
1 | .order_status_item {
2 | flex: 1;
3 | width: 25%;
4 | min-width: 25%;
5 | max-width: 25%;
6 | position: relative;
7 | margin: .4rem 0;
8 | .order_status_item_image {
9 | display: flex;
10 | justify-content: space-around;
11 | width: 100%;
12 | align-items: center;
13 | height: 0.5rem;
14 | position: relative;
15 | }
16 | .order_status_item_image_text {
17 | margin-top: 9px;
18 | text-align: center;
19 | font-size: .24rem;
20 | }
21 | .order_status_item_image_icon {
22 | float: right;
23 | background-color: #fff;
24 | border: 1px solid #ff5b05;
25 | width: 16px;
26 | height: 16px;
27 | border-radius: 8px;
28 | color: #ff5b05;
29 | font-size: 10px;
30 | text-align: center;
31 | line-height: 14px;
32 | right: 16px;
33 | top: -8px;
34 | position: absolute;
35 | }
36 | .order_status_item_image_icon_disable {
37 | visibility: hidden;
38 | float: right;
39 | width: 16px;
40 | height: 16px;
41 | border-radius: 8px;
42 | color: #ff5b05;
43 | font-size: 10px;
44 | text-align: center;
45 | line-height: 16px;
46 | right: 16px;
47 | top: -8px;
48 | position: absolute;
49 | }
50 | &.order_status_item:nth-child(1){
51 | .order_status_item_image_content {
52 | width: 0.47rem;
53 | height: 0.47rem;
54 | }
55 | }
56 | &.order_status_item:nth-child(2){
57 | .order_status_item_image_content {
58 | width: 0.47rem;
59 | height: 0.47rem;
60 | }
61 | }
62 | &.order_status_item:nth-child(3){
63 | .order_status_item_image_content {
64 | width: 0.47rem;
65 | height: 0.47rem;
66 | }
67 | }
68 | &.order_status_item:nth-child(4){
69 | .order_status_item_image_content {
70 | width: 0.47rem;
71 | height: 0.47rem;
72 | }
73 | }
74 | &.order_status_item:nth-child(5){
75 | .order_status_item_image_content {
76 | width: 0.38rem;
77 | height: 0.41rem
78 | }
79 | }
80 | &.order_status_item:nth-child(6){
81 | .order_status_item_image_content {
82 | width: 0.42rem;
83 | height: 0.38rem
84 | }
85 | }
86 | &.order_status_item:nth-child(7){
87 | .order_status_item_image_content {
88 | width: 0.38rem;
89 | height: 0.42rem;
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/components/order-status/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Carousel } from 'antd-mobile';
3 | import styles from './index.less'
4 | import { connect } from 'dva';
5 | import router from 'umi/router';
6 | import OrderStatusItem from '../order-status-item';
7 | import recycleH5_14 from '../../assets/recycleH5_14.png';
8 | import recycleH5_13 from '../../assets/recycleH5_13.png';
9 | import recycleH5_16 from '../../assets/recycleH5_16.png';
10 | import recycleH5_11 from '../../assets/recycleH5_11.png';
11 |
12 | export default class OrderStatus extends React.Component {
13 | constructor(props) {
14 | super(props);
15 | this.state = {
16 | // 订单状态
17 | statusItem: [
18 | {
19 | text: `待发货`,
20 | url: recycleH5_14,
21 | name:'waitingDeliveryCount',
22 | value: 1
23 | },
24 | {
25 | text: `待收货`,
26 | url: recycleH5_13,
27 | name: 'waitingReceiveCount',
28 | value: 2
29 | },
30 | {
31 | text: `待验机`,
32 | url: recycleH5_16,
33 | name:'waitingReviewCount',
34 | value: 3
35 | },
36 | {
37 | text: `待确认`,
38 | url: recycleH5_11,
39 | name:'waitingConfirmCount',
40 | value: 4
41 | },
42 | ],
43 |
44 | // 订单状态
45 | orderStatus: {}
46 | };
47 | }
48 |
49 | componentWillMount() {}
50 | orderMore(){
51 | console.log('跳转去更多哦')
52 | }
53 | render() {
54 | this.props.countList
55 | return (
56 |
57 |
{
60 | this.orderMore();
61 | }
62 | }
63 | >
64 |
我的订单
65 |
66 | 查看更多
67 |
68 |
69 |
70 | {(this.state.statusItem ? this.state.statusItem : []).map((item, index) => {
71 | return (
72 | {
78 | console.log(`跳转到${item.text}`)
79 | }}
80 | />
81 | );
82 | })}
83 |
84 |
85 | );
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/components/order-status/index.less:
--------------------------------------------------------------------------------
1 | .orders {
2 | display: flex;
3 | flex-direction: row;
4 | margin-top: 10px;
5 | padding: 0.31rem 0.31rem 0.3rem 0.31rem;
6 | border-bottom: 0.01rem solid #E4E4E4;
7 | .order_text_large {
8 | font-family: PingFangSC-Medium;
9 | font-size: 0.3rem;
10 | color: #333;
11 | letter-spacing: 0;
12 | line-height: 0.28rem;
13 | }
14 |
15 | .order_text_right {
16 | display: flex;
17 | justify-content: flex-end;
18 | align-items: center;
19 | flex: 1;
20 | color: #a4a4a4;
21 | font-size: 12px;
22 | .right_content {
23 | background: url(https://res.zudeapp.com/recycle/recycleH5_44.png) no-repeat right center;
24 | background-size: cover;
25 | display: block;
26 | background-size: 0.15rem 0.25rem;
27 | padding-right: 14px;
28 | font-size: 0.28rem;
29 | color: #999;
30 | text-align: left;
31 | line-height: 0.28rem;
32 | }
33 | }
34 | }
35 | .list {
36 | display: flex;
37 | // justify-content: space-around;
38 | flex-flow: row;
39 | flex-wrap: wrap;
40 | align-items: center;
41 | padding: .2rem 0;
42 | width: 100%;
43 | .order_status_item{
44 | .order_status_item_image_icon, .order_status_item_image_icon_disable{
45 | position: absolute;
46 | top: -8px;
47 | right: 16px;
48 | }
49 | }
50 |
51 | }
52 | .order_deatil_info{
53 | width: 6.9rem;
54 | margin-left: 0.3rem;
55 | border-radius: 8px;
56 | background: #fff;
57 | }
58 |
--------------------------------------------------------------------------------
/src/dva.js:
--------------------------------------------------------------------------------
1 | import { message } from 'antd';
2 |
3 | export function config() {
4 | return {
5 | onError(err) {
6 | err.preventDefault();
7 | message.error(err.message);
8 | }
9 | };
10 | }
11 |
--------------------------------------------------------------------------------
/src/layouts/baseLayout/baselayout.less:
--------------------------------------------------------------------------------
1 | .base{
2 | &Layout{
3 | height: 100%;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/src/layouts/baseLayout/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { TabBar } from 'antd-mobile';
3 | import router from 'umi/router';
4 | import 'antd-mobile/dist/antd-mobile.css';
5 | import styles from './baseLayout.less';
6 |
7 | const TabBarData = [
8 | {
9 | id: 'home',
10 | name: '首页',
11 | icon: require('../../assets/recycleH5_07.png'),
12 | selectedicon: require('../../assets/recycleH5_02.png'),
13 | url: '/home',
14 | },
15 | {
16 | id: 'class',
17 | name: '分类',
18 | icon: require('../../assets/recycleH5_03.png'),
19 | selectedicon: require('../../assets/recycleH5_06.png'),
20 | url: '/class',
21 | },
22 | {
23 | id: 'my',
24 | name: '我的',
25 | icon: require('../../assets/recycleH5_04.png'),
26 | selectedicon: require('../../assets/recycleH5_05.png'),
27 | url: '/my',
28 | }
29 | ];
30 |
31 | class BaseLayout extends React.Component {
32 |
33 | isTabBarSelect = (url) => {
34 | const {location: {pathname}} = this.props;
35 | if (pathname == '/' && url == '/home') {
36 | return true;
37 | } else {
38 | return pathname === url;
39 | }
40 | }
41 | render() {
42 | return (
43 |
44 |
50 | {
51 | TabBarData.map(t => {
52 | const isSelect = this.isTabBarSelect(t.url);
53 | return (
61 | }
62 | selectedIcon={
67 | }
68 | // badge={1}
69 | onPress={() => {
70 | router.push(t.url);
71 | }}
72 | selected={isSelect}
73 | data-seed="logId"
74 | >
75 | {isSelect && this.props.children}
76 |
77 | )
78 | })
79 | }
80 |
81 |
82 | );
83 | }
84 | }
85 |
86 | export default BaseLayout;
87 |
--------------------------------------------------------------------------------
/src/layouts/index.css:
--------------------------------------------------------------------------------
1 |
2 | .normal {
3 | font-family: Georgia, sans-serif;
4 | text-align: center;
5 | }
6 |
7 | .title {
8 | font-size: 2.5rem;
9 | font-weight: normal;
10 | letter-spacing: -1px;
11 | background: darkslateblue;
12 | padding: .6em 0;
13 | color: white;
14 | margin: 0;
15 | }
16 |
--------------------------------------------------------------------------------
/src/layouts/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import BaseLayout from './baseLayout';
3 |
4 | const ULR_NO_LAYOUT = ['/', '/home', '/class', '/my'];
5 |
6 | class Index extends Component {
7 | componentDidMount() {
8 | }
9 | renderBody = () => {
10 | const {location: {pathname}, children } = this.props;
11 | if (ULR_NO_LAYOUT.includes(pathname)) {
12 | return ();
13 | }
14 | return (
15 |
16 | {children}
17 |
18 | );
19 | }
20 |
21 | render() {
22 | return (
23 |
24 | {this.renderBody()}
25 |
26 | )
27 | }
28 | }
29 |
30 | export default Index;
31 |
--------------------------------------------------------------------------------
/src/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jadeite2/umi-antd-mobile/f7a35ca9ac04b43e90036814b90f99db28c23956/src/models/.gitkeep
--------------------------------------------------------------------------------
/src/pages/class/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'dva';
3 | import { SearchBar, Modal, Menu, Toast} from 'antd-mobile';
4 | import router from 'umi/router';
5 | import styles from './index.less';
6 |
7 | class ClassPage extends Component {
8 | constructor(props) {
9 | super(props)
10 | this.state = {
11 |
12 | }
13 | }
14 | componentDidMount() {
15 |
16 | }
17 | render() {
18 | return (
19 |
20 | 我是一个分类页面
21 |
22 | )
23 | }
24 | }
25 |
26 |
27 | export default ClassPage;
28 |
--------------------------------------------------------------------------------
/src/pages/class/index.less:
--------------------------------------------------------------------------------
1 | :global{
2 | .search_cart{
3 | overflow: auto;
4 | top: 0;
5 | width: 100%;
6 | position: absolute;
7 | bottom: 0;
8 | .search_cart_Search {
9 | background-image: linear-gradient(90deg, #FA9850 3%, #FF6262 100%);
10 | height: 1.74rem;
11 | position: relative;
12 | .am-search {
13 | height: .94rem;
14 | padding: .19rem .31rem;
15 | .am-search-input {
16 | background: rgb(235, 236, 241);
17 | height: .56rem;
18 | input{
19 | height: .56rem;
20 | }
21 | }
22 | }
23 | .am-search-input .am-search-synthetic-ph {
24 | text-align: left;
25 | background: #fff;
26 | text-indent: 1em;
27 | height: .56rem;
28 | line-height: .56rem;
29 | font-size: 12px;
30 | }
31 | .crosswiseMeun{
32 | /*
33 | position: absolute;
34 | left: 0;
35 | right: 0;
36 | bottom: 0;
37 | top:.94rem;
38 | */
39 | white-space: nowrap;
40 | overflow-x: auto;
41 | overflow-y: hidden;
42 | -webkit-overflow-scrolling:auto;
43 | a{
44 | height: .8rem;
45 | line-height: .8rem;
46 | margin: 0 .4rem;
47 | font-size: .3rem;
48 | color: #fff;
49 | cursor: pointer;
50 | }
51 | .active{
52 | position: relative;
53 | &:after{
54 | content: "";
55 | height: 0.1rem;
56 | border-radius: 2px;
57 | background: #FEDA58;
58 | position: absolute;
59 | bottom: -0.22rem;
60 | width: 130%;
61 | left: -15%;
62 | }
63 | }
64 | }
65 | }
66 | .search-cart__content{
67 | .null{
68 | margin: 0 auto;
69 | img{
70 | width: 2rem;
71 | padding-top: 1rem;
72 | }
73 | text-align: center;
74 | .title{
75 | padding-top: .1rem;
76 | color: #999;
77 | font-size: .32rem;
78 | }
79 | }
80 | flex: 1;
81 | display: flex;
82 | height: calc(100% - 1.7rem);
83 | .am-list-body::before {
84 | height: 0;
85 | }
86 | .search-cart__content-menu {
87 | width: 2rem;
88 | height: 100%;
89 | background: rgb(235, 236, 241);
90 | overflow: auto;
91 | .am-list-item {
92 | border-left: 0.08rem solid rgb(235, 236, 241);
93 | padding-left: 0.15rem;
94 | }
95 | .am-list-content {
96 | font-size: 14px !important;
97 | }
98 | .am-sub-menu-item-selected {
99 | border-left: 0.08rem solid #FF6262;
100 | background: #fff;
101 | .am-list-content {
102 | color: rgb(32, 5, 5) !important;
103 | color: #FF6262 !important;
104 | }
105 | .am-radio-inner {
106 | display: none;
107 | }
108 | }
109 | .am-flexbox .am-flexbox-item:last-child {
110 | background: #EDEDED;
111 | }
112 | .am-flexbox .am-flexbox-item:first-child .am-list .am-list-body {
113 | background: rgb(235, 236, 241);
114 | }
115 | .am-flexbox .am-flexbox-item:last-child .am-list .am-list-item {
116 | background: rgb(235, 236, 241);
117 | }
118 | .am-flexbox .am-flexbox-item:last-child .am-list .am-sub-menu-item-selected {
119 | background: #fff;
120 | }
121 |
122 | }
123 | .search-cart__content-tab {
124 | flex: 1;
125 | display: flex;
126 | flex-flow: wrap;
127 | align-content: flex-start;
128 | background: #fff;
129 | overflow: auto;
130 | .serch-cart__content-tab__sub {
131 | width: 100%;
132 | height: 44px;
133 | padding-left: .8rem;
134 | position: relative;
135 | .sub-number {
136 | height: .3rem;
137 | width: .3rem;
138 | background: #333;
139 | position: absolute;
140 | left: .3rem;
141 | top:50%;
142 | transform: translateY(-50%);
143 | color: #999;
144 | text-align: center;
145 | background: url(https://res.zudeapp.com/recycle/recycleH5_24.png) no-repeat center;
146 | background-size: .3rem .3rem;
147 | line-height: .31rem;
148 | font-family:"DINPro-Bold";
149 | }
150 | .sub-numberBg01{
151 | background: url(https://res.zudeapp.com/recycle/recycleH5_21.png) no-repeat center;
152 | background-size: .3rem .3rem;
153 | color: #fff;
154 | }
155 | .sub-numberBg02{
156 | background: url(https://res.zudeapp.com/recycle/recycleH5_22.png) no-repeat center;
157 | background-size: .3rem .3rem;
158 | color: #fff;
159 | }
160 | .sub-numberBg03{
161 | background: url(https://res.zudeapp.com/recycle/recycleH5_23.png) no-repeat center;
162 | background-size: .3rem .3rem;
163 | color: #fff;
164 | }
165 | .sub-name {
166 | text-align: left;
167 | height: 100%;
168 | line-height: 44px;
169 | }
170 | }
171 | }
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/pages/document.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | umi项目
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/pages/home/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { connect } from 'dva';
3 | import { SearchBar, Modal, Flex } from 'antd-mobile';
4 | import HomeCarousel from '../../components/home-tabbar/home-tabber-carousel'
5 | import Link from 'umi/link';
6 | import router from 'umi/router';
7 | import styles from './index.less';
8 |
9 | @connect(({ home }) => ({ home }))
10 | class Home extends Component {
11 | constructor(props) {
12 | super(props)
13 | this.state = {
14 | banner: [],
15 | icon: [],
16 | tab: [],
17 | bottomBanner: [],
18 | loinBannerList: [],
19 | cardLists: [],
20 | tofobanner: [],
21 | visible: false,
22 | }
23 | }
24 | render() {
25 | const { home } = this.props;
26 | return (
27 |
28 |
29 |
30 | this.manualFocusInst = ref}
33 | onFocus={() => router.push('/search')}
34 | />
35 |
36 |
router.push('/class')}>
37 |
}/)
38 |
39 | {
40 | home.list.bannerList && home.list.bannerList.length !== 0 ?
41 |
42 | : ""
43 | }
44 |
45 |
46 |
四步变现
47 |
![]()
router.push('/class')} src={require('../../assets/recycleH5_01.png')} alt="" />
48 |
49 |
50 |
热门机型
51 |
52 | router.push('/class?brand=52')}>
苹果
53 | router.push('/class?brand=4')}>
OPPO
54 | router.push('/class?brand=16')}>
VIVO
55 | router.push('/class?brand=9')}>
华为
56 |
57 |
58 |
59 |
热门回收
router.push('/class')}>更多

60 |
61 | {
62 | home.list.productList && home.list.productList.length !== 0 ? home.list.productList.map((val)=>(
63 |
{console.log('去商品')}}>
64 |
65 |
})
66 |
67 |
{val.productName}
68 |
最高回收价 ¥{val.topPrice}
69 |
立即回收
70 |
71 | ))
72 | : ""
73 | }
74 |
75 |
76 |
this.onClose()}
83 | >
84 |
router.push("/indexActivity")} />
85 |
86 |
87 | )
88 | }
89 | }
90 |
91 |
92 | export default Home;
93 |
--------------------------------------------------------------------------------
/src/pages/home/index.less:
--------------------------------------------------------------------------------
1 | :global{
2 | .homePage{
3 | background: #f7f7f7;
4 | .homePage_search{
5 | height: 3.75rem;
6 | width: 100%;
7 | position: relative;
8 | background: #ccc;
9 | .homePage_input{
10 | position: absolute;
11 | left: .24rem;
12 | right: 1rem;
13 | top:.2rem;
14 | .am-search{
15 | z-index: 11;
16 | padding: 0;
17 | }
18 | }
19 | .homePage_search_ico{
20 | position: absolute;
21 | right: 0;
22 | top: 0.2rem;
23 | width: 1rem;
24 | height: 1rem;
25 | z-index: 11;
26 | text-align: center;
27 | line-height: .8rem;
28 | img {
29 | width: .42rem;
30 | height: .42rem;
31 | }
32 | }
33 | }
34 | .stepBlock{
35 | background-color: #fff;
36 | height: 2.68rem;
37 | margin-bottom: .2rem;
38 | &title{
39 | font-size: .36rem;
40 | font-weight: bold;
41 | color: #333;
42 | height: .98rem;
43 | padding: .26rem .32rem;
44 | }
45 | &img{
46 | width: 100%;
47 | height: 1.7rem;
48 | }
49 | &.hotMobileBlock{
50 | height: 2.36rem;
51 | }
52 | .hotMobile_block{
53 | padding: 0 .3rem;
54 | }
55 | .hotMobile{
56 | text-align: center;
57 | .hotMobile_icon{
58 | height: .8rem;
59 | width: 100%;
60 | background: url(../../assets/recycleH5_apple.png) 0 center no-repeat;
61 | background-size: contain;
62 | &.oppo{
63 | background: url(../../assets/recycleH5_oppo.png) 0 center no-repeat;
64 | background-size: contain;
65 | }
66 | &.vivo{
67 | background: url(../../assets/recycleH5_vivo.png) 0 center no-repeat;
68 | background-size: contain;
69 | }
70 | &.huawei{
71 | background: url(../../assets/recycleH5_huawei.png) 0 center no-repeat;
72 | background-size: contain;
73 | }
74 | }
75 | }
76 | }
77 | .itemList{
78 | margin-top: .2rem;
79 | background: #fff;
80 | &title{
81 | font-size: .36rem;
82 | font-weight: bold;
83 | background-color: #fff;
84 | color: #333;
85 | height: .98rem;
86 | padding: .26rem .32rem;
87 | }
88 | .hotlist{
89 | padding: .32rem;
90 | .itemBlock{
91 | width: 47%;
92 | display: inline-block;
93 | box-shadow: #ccc 3px 2px 16px -4px;
94 | padding: 0.3rem;
95 | // height: 5.6rem;
96 | &:nth-child(2n+1){
97 | margin-right: 4%;
98 | }
99 | .product_img{
100 | width: 2.7rem;
101 | height: 2.7rem;
102 | margin: 0 auto;
103 | box-sizing: border-box;
104 | text-align: center;
105 | .img{
106 | width: 100%;
107 | height: 100%;
108 | }
109 | }
110 | .text_ellipsis{
111 | text-align: center;
112 | font-size: .28rem;
113 | color: #333;
114 | text-overflow: ellipsis;
115 | word-break: break-all;
116 | display: -webkit-box;
117 | -webkit-line-clamp: 2;
118 | /*! autoprefixer: off */
119 | -moz-box-orient: vertical;
120 | -webkit-box-orient: vertical;
121 | /*! autoprefixer: on */
122 | overflow: hidden;
123 | height: 0.86rem;
124 | }
125 | .priceBox{
126 | text-align: center;
127 | color:#999;
128 | font-size: .26rem;
129 | .price{
130 | font-size: .3rem;
131 | line-height: .26rem;
132 | font-weight: bold;
133 | color:#ea4b3b;
134 | font-family:"DINPro-Bold";
135 | }
136 | }
137 | .btn {
138 | width: 100%;
139 | height: .58rem;
140 | line-height: .58rem;
141 | text-align: center;
142 | margin-top: .17rem;
143 | background-image: linear-gradient(90deg, #FE8264 3%, #FF6262 100%);
144 | border-radius: .12rem;
145 | font-family: PingFangHK-Regular;
146 | font-size: .28rem;
147 | color: #FFFFFF;
148 | }
149 | }
150 | }
151 | .hotlist{
152 | padding: .32rem;
153 | .itemBlock{
154 | width: 47%;
155 | display: inline-block;
156 | border-radius: .12rem;
157 | box-shadow: #ccc 3px 2px 16px -4px;
158 | padding: 0.3rem;
159 | margin-bottom: .2rem;
160 | // height: 5.6rem;
161 | &:nth-child(2n+1){
162 | margin-right: 5.2%;
163 | }
164 | .product_img{
165 | width: 2.7rem;
166 | height: 2.7rem;
167 | margin: 0 auto;
168 | box-sizing: border-box;
169 | text-align: center;
170 | .img{
171 | width: 100%;
172 | height: 100%;
173 | }
174 | }
175 | .text_ellipsis{
176 | text-align: center;
177 | font-size: .28rem;
178 | color: #333;
179 | text-overflow: ellipsis;
180 | word-break: break-all;
181 | display: -webkit-box;
182 | -webkit-line-clamp: 2;
183 | /*! autoprefixer: off */
184 | -moz-box-orient: vertical;
185 | -webkit-box-orient: vertical;
186 | /*! autoprefixer: on */
187 | overflow: hidden;
188 | height: 0.86rem;
189 | }
190 | .priceBox{
191 | text-align: center;
192 | color:#999;
193 | font-size: .26rem;
194 | .price{
195 | font-size: .3rem;
196 | line-height: .26rem;
197 | font-weight: bold;
198 | color:#ea4b3b;
199 | font-family:"DINPro-Bold";
200 | }
201 | }
202 | .btn {
203 | width: 100%;
204 | height: .58rem;
205 | line-height: .58rem;
206 | text-align: center;
207 | margin-top: .17rem;
208 | background-image: linear-gradient(90deg, #FE8264 3%, #FF6262 100%);
209 | border-radius: .12rem;
210 | font-family: PingFangHK-Regular;
211 | font-size: .28rem;
212 | color: #FFFFFF;
213 | }
214 | }
215 | }
216 | }
217 | .itemListtitle{
218 | position: relative;
219 | padding-right: 2rem;
220 | .gotoMore{
221 | position: absolute;
222 | right: .3rem;
223 | top:0;
224 | font-weight:400;
225 | font-size: .28rem;
226 | bottom: 0;
227 | line-height: .98rem;
228 | color: #999;
229 | padding-right: .3rem;
230 | img{
231 | height: .28rem;
232 | position: absolute;
233 | right: 0;
234 | top: 50%;
235 | transform: translateY(-50%);
236 | }
237 | }
238 | }
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/src/pages/home/models/home.js:
--------------------------------------------------------------------------------
1 | import { reg } from 'services/home';
2 | import router from 'umi/router';
3 | export default {
4 | namespace: 'home',
5 | state: {
6 | 'list':{
7 | 'productList': '',
8 | 'bannerList': ''
9 | }
10 | },
11 | effects: {
12 | *reg({ payload, callback }, { call, put }) {
13 | const response = yield call(reg, payload);
14 | yield put({
15 | type: 'setData',
16 | payload: response.data
17 | });
18 | }
19 | },
20 | reducers: {
21 | setData(state, { payload }) {
22 | return {
23 | ...state,
24 | list: payload,
25 | }
26 | }
27 | },
28 | subscriptions: {
29 | setup({ dispatch, history }) {
30 | return history.listen(({ pathname, search }) => {
31 | if (pathname == '/home'||pathname == '/') {
32 | dispatch({
33 | type: 'reg',
34 | });
35 | }
36 | });
37 | },
38 | },
39 | };
40 |
--------------------------------------------------------------------------------
/src/pages/index.js:
--------------------------------------------------------------------------------
1 | import Home from './home';
2 |
3 | export default function() {
4 | return (
5 |
6 | );
7 | }
8 |
--------------------------------------------------------------------------------
/src/pages/login/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { connect } from 'dva';
3 | import './index.less';
4 | import classNames from 'classnames';
5 | import { Toast, Modal, Button, List } from 'antd-mobile';
6 | import { CSSTransition } from 'react-transition-group';
7 | import router from 'umi/router';
8 | import { baseUrl } from '@/utils/baseServer';
9 |
10 | // @connect(({ login }) => ({ login }))
11 | class LoginNew extends React.Component {
12 | constructor(props) {
13 | super(props);
14 | this.state = {
15 | phone: '', // 电话
16 | phoneIsFocus: false, // 是否获取焦点
17 | phoneError: false, // 电话是否格式错误
18 | imgCode: '', // 图形验证码
19 | imgCodeIsFocus: false, // 是否获取焦点
20 | imgCodeError: false, // 图形验证码是否图形错误
21 | phoneCode: '', // 短信验证码
22 | phoneCodeIsFocus: false, // 是否获取焦点
23 | codeText: '获取验证码',
24 | isWait: false, // 是否在倒计时
25 | codeImageUrl: '', // 验证码图片
26 | visible: false
27 | };
28 | this.getCode = this.getCode.bind(this)
29 | this.submit = this.submit.bind(this)
30 | }
31 |
32 | componentWillMount() {
33 | // 获取图形验证码
34 | this.refreshCodeImage();
35 |
36 | }
37 |
38 | // 协议弹窗
39 | showProtocol() {
40 | this.setState({
41 | visible: true
42 | });
43 | }
44 | close(v) {
45 | this.setState({
46 | visible: false
47 | });
48 | }
49 | onClose = key => () => {
50 | this.setState({
51 | [key]: false,
52 | });
53 | }
54 |
55 | /**
56 | * 刷新图形验证码
57 | */
58 | refreshCodeImage() {
59 | console.log('刷新图形验证码!!')
60 | }
61 |
62 | /**
63 | * 倒计时
64 | */
65 | setTime() {
66 | this.setState({ isWait: true });
67 | let countdown = 60
68 | this.setState({ codeText: countdown + 's' });
69 | this.timer = setInterval(() => {
70 | if (countdown === 0) {
71 | this.setState({
72 | codeText: '重新获取',
73 | isWait: false
74 | });
75 | this.refreshCodeImage();
76 | clearInterval(this.timer);
77 | } else {
78 | countdown--
79 | this.setState({ codeText: countdown + 's' });
80 | }
81 | }, 1000)
82 | }
83 |
84 | /**
85 | * 获取短信验证码
86 | * @return {Boolean} 当信息不完整时退出
87 | */
88 | getCode() {
89 | const { phone, phoneCode, imgCode } = this.state;
90 | const { dispatch } = this.props;
91 | if (this.state.isWait) {
92 | return false
93 | }
94 | if (!this.checkData()) return
95 |
96 | Toast.success('验证码发送成功', 2);
97 | // 接口成功发送验证码并倒计时
98 | this.setTime()
99 | }
100 |
101 | /**
102 | * 登录
103 | * @return {Boolean} 当信息不完整时退出
104 | */
105 | submit() {
106 | router.push('/home')
107 | }
108 |
109 | /**
110 | * 校验表单
111 | * @return {Boolean} 当信息不完整时退出
112 | */
113 | checkData() {
114 | if (!this.state.phone) {
115 | Toast.fail('请输入手机号码', 2);
116 | return false
117 | }
118 | if (!/^1[3456789]\d{9}$/.test(this.state.phone)) {
119 | Toast.fail('请输入正确的手机号', 2);
120 | this.setState({ phoneError: true });
121 | return false
122 | }
123 | if (!this.state.imgCode) {
124 | Toast.fail('请输入图形验证码', 2);
125 | return false
126 | }
127 | if (!/^[a-zA-Z0-9]{4,5}$/.test(this.state.imgCode)) {
128 | Toast.fail('图形验证码不正确', 2);
129 | this.setState({ imgCodeError: true });
130 | return false
131 | }
132 | return true
133 | }
134 |
135 | componentDidUpdate(prevProps, prevState) {
136 | // watch监听实时校验表单
137 | if (prevState.phone !== this.state.phone) {
138 | if (/^1[3456789]\d{9}$/.test(this.state.phone)) {
139 | this.setState({ phoneError: false });
140 | }
141 | }
142 | if (prevState.imgCode !== this.state.imgCode) {
143 | if (/^[0-9]{4}$/.test(this.state.imgCode)) {
144 | this.setState({ imgCodeError: false });
145 | }
146 | }
147 | }
148 |
149 | render() {
150 | const {phone, phoneIsFocus, phoneError, imgCode, codeImageUrl, imgCodeIsFocus, imgCodeError, phoneCode, phoneCodeIsFocus, codeText, isWait} = this.state;
151 | return (
152 |
153 |
154 |
155 |
156 |
您好!
157 |
欢迎来到UMI项目
158 |
159 |
160 |
161 |
162 | 0}
164 | timeout={400}
165 | classNames="fade"
166 | unmountOnExit
167 | >
168 | 手机号
169 |
170 | 0}
172 | timeout={400}
173 | classNames="input"
174 | >
175 | {
179 | if(e.target.value.length <= 11) {
180 | this.setState({ phone: e.target.value })
181 | }
182 | }}
183 | onFocus={() => {
184 | this.setState({ phoneIsFocus: true });
185 | }}
186 | onBlur={() => {
187 | this.setState({ phoneIsFocus: false });
188 | }}
189 | type="text"
190 | placeholder="请输入手机号"/>
191 |
192 |
193 |
194 |
195 |
196 | 0}
198 | timeout={400}
199 | classNames="fade"
200 | unmountOnExit
201 | >
202 | 图形验证码
203 |
204 | 0}
206 | timeout={400}
207 | classNames="input"
208 | >
209 | {
213 | this.setState({ imgCode: e.target.value });
214 | }}
215 | onFocus={() => {
216 | this.setState({ imgCodeIsFocus: true });
217 | }}
218 | onBlur={() => {
219 | this.setState({ imgCodeIsFocus: false });
220 | }}
221 | type="text"
222 | placeholder="请输入图像验证码"/>
223 |
224 |
225 |
226 |
})
227 |
{this.refreshCodeImage()}}>
228 |
229 |
230 |
231 |
232 |
233 | 0}
235 | timeout={400}
236 | classNames="fade"
237 | unmountOnExit
238 | >
239 | 短信验证码
240 |
241 | 0}
243 | timeout={400}
244 | classNames="input"
245 | >
246 | {
249 | this.setState({ phoneCode: e.target.value });
250 | }}
251 | onFocus={() => {
252 | this.setState({ phoneCodeIsFocus: true });
253 | }}
254 | onBlur={() => {
255 | this.setState({ phoneCodeIsFocus: false });
256 | }}
257 | type="text"
258 | placeholder="请输入短信验证码"/>
259 |
260 |
261 |
262 | {codeText}
264 |
265 |
266 |
267 |
268 |
271 |
{
272 | this.showProtocol();
273 | }}>登录或注册即代表您已同意《用户注册协议》
274 | {/*----协议----*/}
275 |
{ console.log('ok'); this.onClose('visible')(); } }]}
283 | >
284 |
285 |
295 |
296 |
297 | );
298 | }
299 | }
300 |
301 | // 分割线动画组件
302 | class Line extends React.Component {
303 | constructor(props) {
304 | super(props);
305 | this.state = {}
306 | }
307 | render() {
308 | return (
309 |
318 | )
319 | }
320 | }
321 | export default LoginNew
322 |
--------------------------------------------------------------------------------
/src/pages/login/index.less:
--------------------------------------------------------------------------------
1 | :global{
2 | .login-bg {
3 | min-height: 100%;
4 | background: white;
5 | padding-top: .98rem;
6 | }
7 | .logo-wrap {
8 | display: flex;
9 | .logo {
10 | margin-left: 1.68rem;
11 | height: 1.44rem;
12 | width: 1.44rem;
13 | background: url(../../assets/yay.jpg) no-repeat center;
14 | background-size: 1.44rem 1.44rem;
15 | }
16 | .welcome-wrap {
17 | margin-left: .3rem;
18 | display: flex;
19 | justify-content: center;
20 | flex-direction: column;
21 | .hello {
22 | font-family: PingFangSC-Regular;
23 | font-size: .6rem;
24 | color: #333333;
25 | letter-spacing: 0;
26 | line-height: .6rem;
27 | }
28 | .welcome {
29 | margin-top: .24rem;
30 | font-family: PingFangSC-Regular;
31 | font-size: .4rem;
32 | color: #999;
33 | letter-spacing: 0;
34 | line-height: .4rem;
35 | span {
36 | color: #FF6262;
37 | }
38 | }
39 | }
40 | }
41 | .form-wraper {
42 | margin-top: .4rem;
43 | padding: 0 .5rem;
44 | box-sizing: border-box;
45 | .input-wrap {
46 | display: flex;
47 | justify-content: center;
48 | flex-direction: column;
49 | height: 1.1rem;
50 | width: 100%;
51 | .error {
52 | color: red;
53 | }
54 | input {
55 | position: relative;
56 | left: 0;
57 | top: 0;
58 | z-index: 1;
59 | }
60 | span {
61 | margin-bottom: 7px;
62 | font-family: PingFangSC-Regular;
63 | font-size: 11px;
64 | color: #666666;
65 | letter-spacing: 0;
66 | line-height: 11px;
67 | }
68 | }
69 | .input-wrap-flex {
70 | display: flex;
71 | .left {
72 | flex: 0 0 4.39rem;
73 | display: flex;
74 | justify-content: center;
75 | flex-direction: column;
76 | height: 1.1rem;
77 | .error {
78 | color: red;
79 | }
80 | span {
81 | margin-bottom: 7px;
82 | font-family: PingFangSC-Regular;
83 | font-size: 11px;
84 | color: #666666;
85 | letter-spacing: 0;
86 | line-height: 11px;
87 | }
88 | }
89 | .right {
90 | flex: 1;
91 | display: flex;
92 | align-items: center;
93 | .img-code {
94 | width: 1.59rem;
95 | height: .64rem;
96 | }
97 | .refresh {
98 | margin-left: 12px;
99 | width: .4rem;
100 | height: .38rem;
101 | background: url(https://m.zudeapp.com/images/login/new_login/refresh.png) no-repeat center;
102 | background-size: .4rem .38rem;
103 | }
104 | .close {
105 | margin-right: 11px;
106 | flex: 0 0 20px;
107 | height: 20px;
108 | background: url(https://m.zudeapp.com/images/login/new_login/close.png) no-repeat center;
109 | background-size: 12px 12px;
110 | }
111 | .code-info {
112 | flex: 1;
113 | text-align: right;
114 | font-family: PingFangHK-Regular;
115 | font-size: 14px;
116 | color: #333333;
117 | letter-spacing: 0;
118 | }
119 | .gray-info {
120 | color: #CCCCCC;
121 | }
122 | .active-info {
123 | color: #FF6262;
124 | }
125 | }
126 | }
127 | }
128 |
129 | .login-wrap {
130 | margin-top: .6rem;
131 | display: flex;
132 | justify-content: center;
133 | padding: 0 25px;
134 | .login {
135 | width: 100%;
136 | height: .88rem;
137 | line-height: .88rem;
138 | text-align: center;
139 | background-image: linear-gradient(90deg, #FA9850 3%, #FF6262 100%);
140 | border-radius: 100px;
141 | font-family: PingFangHK-Regular;
142 | font-size: .36rem;
143 | color: #FFFFFF;
144 | box-shadow: #FA9850 0 5px 16px -4px;
145 | }
146 | .login:not(.disabled):not(:disabled):active {
147 | background: rgba(250, 152, 80, .5);
148 | }
149 | }
150 | .agree-wrap {
151 | margin-top: .4rem;
152 | text-align: center;
153 | font-family: PingFangSC-Regular;
154 | font-size: 14px;
155 | color: #999999;
156 | line-height: 14px;
157 | .agree {
158 | color: #FA9850;
159 | }
160 | }
161 |
162 | .margin-top-20 {
163 | margin-top: .2rem;
164 | }
165 | // label动画
166 | .fade-enter {
167 | opacity: 0;
168 | transform: translateY(100%);
169 | }
170 | .fade-enter-active {
171 | opacity: 1;
172 | transform: translateY(0%);
173 | transition: all 1s;
174 | }
175 | .fade-enter-done {
176 | opacity: 1;
177 | }
178 | .fade-exit {
179 | opacity: 1;
180 | transform: translateY(0%);
181 | }
182 | .fade-exit-active {
183 | opacity: 0;
184 | transform: translateY(100%);
185 | transition: all .4s;
186 | }
187 | .fade-exit-done {
188 | opacity: 0;
189 | }
190 | // input动画
191 | .input-enter {
192 | transform: translateY(0%);
193 | }
194 | .input-enter-active {
195 | transform: translateY(0%);
196 | transition: all 1s;
197 | }
198 | .input-enter-done {
199 | }
200 | .input-exit {
201 | transform: translateY(0%);
202 | }
203 | .input-exit-active {
204 | transform: translateY(-14px);
205 | transition: all 1s;
206 | }
207 | .input-exit-done {
208 | }
209 |
210 | .line-wrap {
211 | position: relative;
212 | width: 100%;
213 | height: 1px;
214 | background: #E5E5E5;
215 | .line {
216 | //position: absolute;
217 | //top: 0;
218 | //left: 0;
219 | //height: 1px;
220 | //width: 100%;
221 | //background: #E5E5E5;
222 | z-index: 1;
223 | position: absolute;
224 | left:0;
225 | bottom: -1px;
226 | background:#E5E5E5;
227 | width: 100%;
228 | height: 2px;
229 | -webkit-transform: scaleY(0.5);
230 | transform: scaleY(0.5);
231 | -webkit-transform-origin: 0 0;
232 | transform-origin: 0 0;
233 | }
234 | .line-enter {
235 | width: 0;
236 | background: #E5E5E5;
237 | }
238 | .line-enter-active {
239 | width: 100%;
240 | background: red;
241 | transition: all 1s linear;
242 | }
243 | .line-enter-done {
244 | background: red;
245 | width: 100%;
246 | }
247 | .line-exit {
248 | background: red;
249 | width: 100%;
250 | }
251 | .line-exit-active {
252 | background: #E5E5E5;
253 | width: 0;
254 | transition: all 1s linear;
255 | }
256 | .line-exit-done {
257 | background: #E5E5E5;
258 | width: 100%;
259 | }
260 | }
261 |
262 | .x-scale-1px{
263 | position: relative;
264 | border:none;
265 | }
266 | .x-scale-1px::after{
267 | content: '';
268 | position: absolute;
269 | left:0;
270 | bottom: -1px;
271 | background:#E5E5E5;
272 | width: 100%;
273 | height: 2px;
274 | -webkit-transform: scaleY(0.5);
275 | transform: scaleY(0.5);
276 | -webkit-transform-origin: 0 0;
277 | transform-origin: 0 0;
278 | }
279 |
280 | .x-scale-red-1px{
281 | }
282 | .x-scale-red-1px::after{
283 | background: #FF6262;
284 | }
285 |
286 | .x-scale-top-1px{
287 | position: fixed;
288 | bottom: 0;
289 | left: 0;
290 | right: 0;
291 | border:none;
292 | background: #fff;
293 | }
294 | .x-scale-top-1px::after{
295 | content: '';
296 | position: absolute;
297 | left:0;
298 | top: 0;
299 | background-color: #E4E4E4;
300 | width: 100%;
301 | height: 1px;
302 | -webkit-transform: scaleY(0.5);
303 | transform: scaleY(0.5);
304 | -webkit-transform-origin: 0 0;
305 | transform-origin: 0 0;
306 | }
307 |
308 | }
309 |
--------------------------------------------------------------------------------
/src/pages/my/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'dva';
3 | import { Modal } from 'antd-mobile';
4 | import NameCard from '../../components/name-card';
5 | import OrderStatus from '../../components/order-status';
6 | import router from 'umi/router';
7 | import styles from './index.less';
8 |
9 | @connect(({ my }) => ({ my }))
10 | class MyIndex extends Component {
11 | constructor(props) {
12 | super(props);
13 | this.state = {
14 | nowdata: 0,
15 | name: '登录/注册',
16 | avatar:'',
17 | not_login: false
18 | }
19 | }
20 | componentDidMount() {
21 | const { dispatch } = this.props;
22 |
23 | }
24 | linkurl(v){
25 | if (v === 'address') {
26 | console.log('去地址管理咯')
27 | } else {
28 | console.log('去支付账户管理咯')
29 | }
30 | }
31 | render() {
32 | const { my } = this.props;
33 | const { not_login } = this.state;
34 | return (
35 |
36 |
41 | { !my.list.data &&
}
42 | { my.list.data &&
}
43 |
44 |
我的服务
45 |
46 |
this.linkurl('account')}>
47 |
})
52 |
收款方式
53 |
54 |
this.linkurl('address')}>
55 |
})
60 |
收货地址
61 |
62 |
{console.log('帮助中心')}}>
63 |
})
68 |
帮助中心
69 |
70 |
71 |
72 |
73 | )
74 | }
75 | }
76 | export default MyIndex;
77 |
--------------------------------------------------------------------------------
/src/pages/my/index.less:
--------------------------------------------------------------------------------
1 |
2 | .center () {
3 | position: absolute;
4 | top: 50%;
5 | left: 50%;
6 | transform: translate(-50%, -50%);
7 | }
8 | .my {
9 | width: 100%;
10 | height: 100%;
11 | background: #fff;
12 | &Header{
13 | height: 153px;
14 | position: relative;
15 | &Login{
16 | .center;
17 | width: 92px;
18 | height: 92px;
19 | background: #e60f0d;
20 | border-radius: 50%;
21 | text-align: center;
22 | line-height: 92px;
23 | a {
24 | color: #fff;
25 | font-size: 16px;
26 | }
27 | }
28 | }
29 | }
30 | .content_me{
31 | padding-top: .3rem;
32 | .service_info{
33 | background: #fff;
34 | width: 6.9rem;
35 | margin-left: 0.3rem;
36 | padding: 0.3rem 0 0.35rem 0;
37 | border-radius: 8px;
38 | margin-top: .2rem;
39 | .service_title{
40 | text-align: left;
41 | font-family: PingFangSC-Medium;
42 | font-size: 0.3rem;
43 | color: #333;
44 | letter-spacing: 0;
45 | line-height: .28rem;
46 | position: relative;
47 | padding: 0 .3rem .3rem;
48 | }
49 | .service_content{
50 | display: flex;
51 | margin-top: 0.3rem;
52 | padding-top:0.35rem;
53 | border-top: 0.01rem solid #E4E4E4;
54 | .service_item{
55 | flex: 1;
56 | text-align: center;
57 | .service_img{
58 | width: 0.6rem;
59 | height: 0.6rem;
60 | }
61 | .service_text{
62 | font-size: 0.24rem;
63 | color: #333333;
64 | text-align: center;
65 | line-height: 0.28rem;
66 | margin-top: 0.10rem;
67 | }
68 | }
69 | &:last-child{
70 | border: none;
71 | padding-top: 0;
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/pages/my/models/my.js:
--------------------------------------------------------------------------------
1 | import { reg } from 'services/my';
2 | import router from 'umi/router';
3 | export default {
4 | namespace: 'my',
5 | state: {
6 | list: ''
7 | },
8 | effects: {
9 | *reg({ payload, callback }, { call, put }) {
10 | const response = yield call(reg, payload);
11 | if(!response){
12 | return;
13 | }
14 | yield put({
15 | type: 'setData',
16 | payload: response
17 | });
18 | if (response) {
19 | callback(response);
20 | }
21 | },
22 | },
23 | reducers: {
24 | setData(state, { payload }) {
25 | return {
26 | ...state,
27 | list: payload,
28 | }
29 | },
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/src/services/home.js:
--------------------------------------------------------------------------------
1 | import proxyRequest from 'utils/request';
2 | import { baseUrl } from '@/utils/baseServer';
3 |
4 | export async function reg(params) {
5 | return proxyRequest.get('/api/home', params);
6 | }
7 |
--------------------------------------------------------------------------------
/src/services/my.js:
--------------------------------------------------------------------------------
1 | import proxyRequest from 'utils/request';
2 | import { baseUrl } from '@/utils/baseServer';
3 |
4 | export async function reg(params) {
5 | return proxyRequest.get(`${baseUrl}recycleapi/order/user/orderCount`, params);
6 | }
7 | export async function orderCount(params) {
8 | return proxyRequest.get(`${baseUrl}recycleapi/order/user/orderCount`, params);
9 | }
10 |
--------------------------------------------------------------------------------
/src/utils/authorized.js:
--------------------------------------------------------------------------------
1 | import {connect} from 'dva';
2 | import router from 'umi/router';
3 |
4 | export default connect(props => {
5 | const logging_status = localStorage.getItem('authority') || false;
6 | return logging_status;
7 | })(function Authority (props) {
8 | const {logging_status, route} = props;
9 | console.log(router.path,'path')
10 | if (logging_status) {
11 | console.log(11111)
12 | } else {
13 | console.log(22222)
14 | }
15 | return props.children;
16 | })
17 |
--------------------------------------------------------------------------------
/src/utils/baseServer.js:
--------------------------------------------------------------------------------
1 | export const baseUrl = window.location.origin + '/';
2 |
3 |
4 | export const setFormData = (obj) => {
5 | const formData = new FormData();
6 | if (obj && obj instanceof Object) {
7 | const keys = Object.keys(obj);
8 | if (keys && keys.length) {
9 | keys.forEach(key => {
10 | formData.append(key, obj[key]);
11 | });
12 | }
13 | }
14 | return formData;
15 | }
16 |
17 | export const setUrlEncoded = (obj) => {
18 | let urlEncoded = '';
19 | if(obj && obj instanceof Object) {
20 | const keys = Object.keys(obj);
21 | if(keys && keys.length) {
22 | keys.forEach((key, index) => {
23 | urlEncoded += `${key}=${obj[key]}`;
24 | if(index + 1 < keys.length){
25 | urlEncoded += '&';
26 | }
27 | });
28 | }
29 | }
30 | return urlEncoded;
31 | }
32 |
--------------------------------------------------------------------------------
/src/utils/formValid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 验证必填
3 | */
4 | const require = (message) => {
5 | const msg = message || '必填';
6 | return { required: true, message: msg };
7 | };
8 |
9 | /**
10 | * 数字,中英文,中横线,下划线,utf-8中文
11 | */
12 | const phone = (message) => {
13 | const msg = message || '请输入正确的手机号码';
14 | return { pattern: /^\d{3} \d{4} \d{4}$/, message: msg };
15 | };
16 |
17 | /**
18 | * 验证参数组件必填
19 | */
20 | const verifyCode = (message, fn) => {
21 | const msg = message || '请输入六位数字';
22 | return { pattern: /^\d{6}$/, message: msg };
23 | };
24 |
25 |
26 | export default {
27 | require,
28 | phone,
29 | verifyCode,
30 | }
31 |
--------------------------------------------------------------------------------
/src/utils/index.js:
--------------------------------------------------------------------------------
1 | /* global window */
2 | import request from './request'
3 |
4 | export {
5 | request
6 | }
7 |
--------------------------------------------------------------------------------
/src/utils/request.js:
--------------------------------------------------------------------------------
1 | import fetch from 'dva/fetch';
2 | import { Toast } from 'antd-mobile';
3 | import { setUrlEncoded } from './baseServer';
4 | import { getToken, setToken } from './token';
5 | import router from 'umi/router';
6 |
7 | const codeMessage = {
8 | 200: '服务器成功返回请求的数据。',
9 | 201: '新建或修改数据成功。',
10 | 202: '一个请求已经进入后台排队(异步任务)。',
11 | 204: '删除数据成功。',
12 | 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
13 | 401: '用户没有权限(令牌、用户名、密码错误)。',
14 | 403: '用户得到授权,但是访问是被禁止的。',
15 | 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
16 | 406: '请求的格式不可得。',
17 | 410: '请求的资源被永久删除,且不会再得到的。',
18 | 422: '当创建一个对象时,发生一个验证错误。',
19 | 500: '服务器发生错误,请检查服务器。',
20 | 502: '网关错误。',
21 | 503: '服务不可用,服务器暂时过载或维护。',
22 | 504: '网关超时。',
23 | };
24 |
25 | function checkStatus(response) {
26 | if (response.status >= 200 && response.status < 300) {
27 | return response;
28 | }
29 | const errorText = codeMessage[response.status] || response.statusText;
30 | Toast.fail(errorText, 1);
31 | const error = new Error(errorText);
32 | error.name = response.status;
33 | error.response = response;
34 | throw error;
35 | }
36 |
37 | /**
38 | * Requests a URL, returning a promise.
39 | *
40 | * @param {string} url The URL we want to request
41 | * @param {object} [options] The options we want to pass to "fetch"
42 | * @return {object} An object containing either "data" or "err"
43 | */
44 | function request(url, options) {
45 | const defaultOptions = {
46 | credentials: 'include',
47 | };
48 | const newOptions = { ...defaultOptions, ...options };
49 | // body 添加token
50 | if (newOptions.body) {
51 | newOptions.body.__token__ = getToken();
52 | } else {
53 | newOptions.body = {
54 | __token__: getToken(),
55 | };
56 | }
57 | let new_url;
58 | if (
59 | newOptions.method === 'POST' ||
60 | newOptions.method === 'PUT' ||
61 | newOptions.method === 'DELETE'
62 | ) {
63 | if (newOptions.contentType === 'application/json') {
64 | newOptions.headers = {
65 | Accept: 'application/json',
66 | 'Content-Type': 'application/json',
67 | ...newOptions.headers,
68 | };
69 | newOptions.body = JSON.stringify(newOptions.body);
70 | } else if (newOptions.contentType === 'formData') {
71 | newOptions.headers = {
72 | Accept: 'application/json',
73 | ...newOptions.headers,
74 | };
75 | } else {
76 | newOptions.headers = {
77 | Accept: 'application/json',
78 | 'Content-Type': 'application/x-www-form-urlencoded',
79 | ...newOptions.headers,
80 | };
81 | if (newOptions.body) {
82 | newOptions.body = setUrlEncoded(newOptions.body);
83 | }
84 | }
85 | new_url = url
86 | } else if (newOptions.method === 'GET') {
87 | new_url = url + '?' + setUrlEncoded(newOptions.body)
88 | delete newOptions.body
89 | }
90 |
91 | return fetch(new_url, newOptions)
92 | .then(checkStatus)
93 | .then((response) => {
94 | return response.json();
95 | });
96 | }
97 |
98 | /**
99 | * the proxy of request
100 | * @param url
101 | * @param options
102 | * @returns {*}
103 | */
104 | function proxyRequest(url, options, showError = true) {
105 | options = options || {};
106 | return request(url, options).then((response) => {
107 | if (response && response.token) {
108 | setToken(response.token);
109 | }
110 | if (response.err_code === -1 || response.code === 1) {
111 | // return response.data || {};
112 | return response || {};
113 | }
114 | if (showError) {
115 | if (response.code !== 403){
116 | Toast.fail(response.msg, 1)
117 | }
118 | }
119 | const e = new Error();
120 | e.code = response.code;
121 | e.message = response.message || `Failed to get data code : ${e.code}`;
122 | throw e;
123 | }).catch((e,url) => {
124 | console.log(e,'errrr')
125 | const status = e.code;
126 | if (status === 401) {
127 | // @HACK
128 | /* eslint-disable no-underscore-dangle */
129 | window.g_app._store.dispatch({
130 | type: 'login/logout',
131 | });
132 | return;
133 | }
134 | if (status === 403) {
135 | router.push('/login');
136 | return;
137 | }
138 | if (status <= 504 && status >= 500) {
139 | // router.push('/login');
140 | return;
141 | }
142 | if (status >= 404 && status < 422) {
143 | // router.push('/404');
144 | return;
145 | }
146 | });
147 | }
148 |
149 | proxyRequest.get = (url, data, options, showError) => {
150 | options = options || {};
151 | options.body = data || {};
152 | options.method = 'GET';
153 | return proxyRequest(url, options, showError);
154 | };
155 |
156 | proxyRequest.post = (url, data, options, showError) => {
157 | options = options || {};
158 | options.body = data || {};
159 | options.method = 'POST';
160 | return proxyRequest(url, options, showError);
161 | };
162 |
163 | proxyRequest.put = (url, data, options) => {
164 | options = options || {};
165 | options.body = data || {};
166 | options.method = 'PUT';
167 | return proxyRequest(url, options);
168 | };
169 |
170 | proxyRequest.delete = (url, data, options) => {
171 | options = options || {};
172 | options.body = data || {};
173 | options.method = 'DELETE';
174 | return proxyRequest(url, options);
175 | };
176 |
177 | export default proxyRequest;
178 |
--------------------------------------------------------------------------------
/src/utils/token.js:
--------------------------------------------------------------------------------
1 | export function getToken(str) {
2 | const tokenString =
3 | typeof str === 'undefined' ? localStorage.getItem('recovery-buss-web-token'): str;
4 | return tokenString;
5 | }
6 |
7 | export function setToken(token) {
8 | if(token){
9 | return localStorage.setItem('recovery-buss-web-token', token);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------