├── .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 |
269 |
登录/注册
270 |
271 |

{ 272 | this.showProtocol(); 273 | }}>登录或注册即代表您已同意《用户注册协议》

274 | {/*----协议----*/} 275 | { console.log('ok'); this.onClose('visible')(); } }]} 283 | > 284 |
285 |