Commit 454affe1 by wangshuo

Merge branch 'master' of gitlab.julyedu.com:baiguangyao/mr-julyedu

parents b15d5864 a0ece39f
......@@ -57,7 +57,8 @@ class App extends Component {
payload = {
hasError: true,
msg: res.data.msg,
code: res.data.code
code: res.data.code,
data: {}
}
}
return payload
......
......@@ -8,6 +8,7 @@
border: 1px solid $border_ccc;
border-radius: 3px;
-webkit-appearance: none;
font-size: 15px;
&::-webkit-input-placeholder {
color: $color_999;
......
......@@ -3,43 +3,36 @@ import './clearable-input.scss'
import classnames from 'classnames'
class ClearableInput extends Component {
constructor(props) {
super(props);
this.state = {
value: ''
}
}
handleChange = (e) => {
let {onChange} = this.props
let val = e.target.value
this.setState({value: val})
onChange && onChange(val)
}
clearInput = () => {
this.setState({value: ''})
}
render() {
let {wrapperClass, inputClass, placeholder, type = 'text', onChange, icon, ...rest} = this.props
let {
value,
name,
wrapperClass,
inputClass,
type = 'text',
icon,
setValues,
...rest
} = this.props
let clearIconStyle = {
display: this.state.value.length ? 'block' : 'none'
display: value && value.length ? 'block' : 'none'
}
return (
<div className={classnames('clearable-input-wrapper', wrapperClass)}>
<input
type={type}
value={value}
className={inputClass}
value={this.state.value}
onChange={this.handleChange}
placeholder={placeholder}
{...rest}
name={name}
/>
{icon}
<i
className={'iconfont icondanseshixintubiao-3 clear'}
onClick={this.clearInput}
onClick={() => {
setValues({[name]: ''})
}}
style={clearIconStyle}
/>
</div>
......
......@@ -5,18 +5,30 @@ class HeaderBar extends Component {
constructor(props) {
super(props);
}
goBack = () => {
window.history.go(-1);
}
goShop = () => {
location.replace('/shopcart');
}
render() {
return (
<div className="detail-header" style={{...this.props.style}}>
<i className={`iconfont ${this.props.arrow ? 'iconiconfront-68' : ''} return`} onClick={this.goBack}></i>
{
this.props.arrow &&
<i className='iconfont iconiconfront-68' onClick={this.goBack}></i>
}
<span className='herder'>{this.props.title}</span>
<i className={`iconfont ${this.props.cart ? 'icongouwuche-xianxing' : ''} shopping-cart`} onClick={this.goShop}></i>
{
this.props.cart &&
<i className='iconfont icongouwuche-xianxing' onClick={this.goShop}></i>
}
{
this.props.delete &&
<i className='iconfont iconiconfront-56' onClick={this.props.toDelete}></i>
}
</div>
);
}
......
......@@ -3,13 +3,21 @@
line-height: 44px;
padding: 0 15px;
background-color: $bg_f7f9fc;
display: flex;
justify-content: space-between;
text-align: center;
.shopping-cart, .return {
i {
font-size: 18px !important;
}
i:nth-of-type(1) {
float: left;
}
i:nth-of-type(2) {
float: right;
}
.herder {
font-size: 16px;
color: $color_202426;
......
......@@ -21,7 +21,7 @@ class HeaderBar extends Component {
onFocus={this.toSearch.bind(this)}
showCancelButton={false}
/>
<i className={'iconfont icongouwuche shopping-cart'}></i>
<i className={'iconfont icongouwuche-xianxing shopping-cart'}></i>
</div>
</div>
)
......
......@@ -4,3 +4,7 @@ export { default as Tag } from './CategoryTag'
export { default as OrderItem } from './OrderList'
export { default as HeaderBar } from './HeaderBar'
export { default as ToApp } from './ToApp'
export { default as Captcha } from './Captcha'
export { default as ClearableInput } from "./ClearableInput";
......@@ -4,6 +4,8 @@ import './index.scss';
import {http, api} from "@/utils";
import {Link} from 'react-router-dom'
import {Toast} from 'antd-mobile'
import { HeaderBar } from "@/common"
class Classify extends Component {
constructor(props) {
......@@ -45,7 +47,7 @@ class Classify extends Component {
render() {
return (
<div className='class-box'>
<div className="class-title">分类</div>
<HeaderBar title='分类' arrow={false} cart={false}></HeaderBar>
<ClassCourseBox data={this.state.camp.list} title={this.state.camp.name} type={1}/>
<ClassCourseBox data={this.state.employment.list} title={this.state.employment.name} type={1}/>
<ClassCourseBox data={this.state.basics.list} title={this.state.basics.name} type={2}/>
......
......@@ -70,7 +70,7 @@ class BtnStatus extends Component {
<i className='iconfont iconerji'></i>
<span>课程咨询</span>
</a>
<button className='btn btn-m bg-09f'>开始学习</button>
<Link to={`/play?id=${getParam('id')}`} className='btn btn-m bg-09f'>开始学习</Link>
</div>
}
{/*拼团 未开团*/}
......
......@@ -7,7 +7,7 @@
background-color: $bg_fff;
display: flex;
justify-content: space-between;
border-top: 1px solid $sp_e7eaf1;
.consult {
display: inline-block;
......
......@@ -74,7 +74,7 @@ class Detail extends Component {
return (
<div className='detail-box'>
<ToApp className='toapp' toApp={this.toApp}></ToApp>
<HeaderBar title={'课程详情'}></HeaderBar>
<HeaderBar title='课程详情' arrow={true} cart={true}></HeaderBar>
{/*弹幕*/}
<Carouselw></Carouselw>
{/*课程*/}
......
import React, {Component} from 'react'
import {Tabs, WhiteSpace} from 'antd-mobile'
import './index.scss'
import {api, getParam, http} from "@/utils";
import {api, getParam, http} from "@/utils"
import {Toast} from 'antd-mobile'
class OutLine extends Component {
......@@ -25,6 +26,8 @@ class OutLine extends Component {
this.setState({
stageInfo: res.data.data
})
} else {
Toast.info(res.data.msg, 2)
}
})
}
......
import React, {Component} from 'react'
import './index.scss'
import {api, getParam, http} from "@/utils";
import {withRouter} from "react-router-dom";
import {api, getParam, http} from "@/utils"
import {withRouter} from "react-router-dom"
import {Toast} from 'antd-mobile'
class ShareRank extends Component {
......@@ -23,6 +24,8 @@ class ShareRank extends Component {
rankingslice: res.data.data.slice(0, 2),
courseInfo: this.props.data.course_info
})
} else {
Toast.info(res.data.msg, 2)
}
})
// 获取分销码
......@@ -34,6 +37,8 @@ class ShareRank extends Component {
this.setState({
code: res.data.data.code
})
} else {
Toast.info(res.data.msg, 2)
}
})
}
......
import React, {Component} from 'react'
import './index.scss'
import {api, getParam, http, is_weixin} from "@/utils";
import {Toast, WhiteSpace, WingBlank, Button} from 'antd-mobile';
import {Toast} from 'antd-mobile';
class Single extends Component {
......@@ -41,7 +41,7 @@ class Single extends Component {
})
this.state.payType === '1' ? this.alipayPay(this.state.orderId) : this.weixinPay(this.state.orderId)
} else {
alert(res.data.msg)
Toast.info(res.data.msg, 2)
}
})
}
......@@ -56,7 +56,7 @@ class Single extends Component {
if (res.data.errno === 0) {
window.location.href = res.data.data.url + "&redirect_url=" + encodeURIComponent(window.location.href + "&weixinpay=1").toLowerCase();
} else {
alert(res.data.msg);
Toast.info(res.data.msg, 2)
}
})
}
......@@ -67,7 +67,7 @@ class Single extends Component {
if (res.data.errno === 0) {
window.location = res.data.data.url;
} else {
alert(res.data.msg);
Toast.info(res.data.msg, 2)
}
})
}
......@@ -112,7 +112,7 @@ class Single extends Component {
this.onBridgeReady()
}
} else {
alert(res.data.msg)
Toast.info(res.data.msg, 2)
}
})
}
......@@ -145,7 +145,7 @@ class Single extends Component {
status: 2
})
} else {
alert(res.data.data.msg)
Toast.info(res.data.data.msg, 2)
}
})
}
......
import React, {PureComponent} from 'react'
import './index.scss'
import {connect} from "react-redux"
import {Toast} from 'antd-mobile'
import {api, http} from "@/utils"
import {HeaderBar} from "@/common"
class MyEdut extends PureComponent {
constructor(props) {
super(props)
this.state = {
isShow: false,
value: ''
}
}
// 点击编辑
toEditName = () => {
this.setState({
isShow: true,
value: ''
})
}
// 取消
cancle = () => {
this.setState({
isShow: false
})
}
// 获取input的值
handleChange = (e) => {
this.setState({
value: e.target.value
})
}
// 退出登录
outLogin = () => {
}
// 确定修改
submit = () => {
console.log(this.state.value)
if (this.state.value.length > 12) {
Toast.info('不超过12个字符', 2)
} else if (this.state.value.length === 0) {
Toast.info('请输入昵称', 2)
} else {
let data = {
user_name: this.state.value
}
http.post(`${api.home}/m/user_info/update`, data).then((res) => {
if (res.data.code === 200) {
this.setState({
isShow: false
})
Toast.info('修改成功', 2)
} else {
Toast.info(res.data.msg, 2)
}
})
}
}
render() {
const {user} = this.props
const username = user && user.data && user.data.username
const avatar = user && user.data && user.data.avatar
return (
<div className="edit-name">
<HeaderBar title='账号' arrow={true} cart={false}></HeaderBar>
<div className='my-mess'>
<img src={avatar} alt=""/>
<span className="name">{username}</span>
<span onClick={this.toEditName} className="edit">编辑</span>
</div>
<div className="out-login" onClick={this.outLogin}>
退出登录
</div>
{
this.state.isShow &&
<div className="edit-mbc">
<div className="edit-content">
<div className="edit-title">修改昵称</div>
<input type="text" placeholder='请输入昵称(不超过12个字符)'
value={this.state.value}
onChange={this.handleChange.bind(this)}
/>
<div className="edit-btn">
<button className='cancle' onClick={this.cancle}>取消</button>
<button className='submit' onClick={this.submit}>确认</button>
</div>
</div>
</div>
}
</div>
)
}
}
export default connect(
state => ({user: state.user}),
null
)(MyEdut)
import React, {PureComponent} from 'react';
import {Flex, WhiteSpace, NavBar, List} from 'antd-mobile';
import './index.scss';
import Avatar from './image/avatar.png';
import Vip from './image/vip.png';
import React, {PureComponent} from 'react'
import {Flex, WhiteSpace, List} from 'antd-mobile'
import './index.scss'
import Avatar from './image/avatar.png'
import Vip from './image/vip.png'
import {WithTab} from '@/HOCs'
import {Link} from "react-router-dom";
// import UnVip from './image/unVIP.png';
import {Link} from "react-router-dom"
import {connect} from "react-redux"
import {HeaderBar} from "@/common"
const Item = List.Item;
const Brief = Item.Brief;
......@@ -18,70 +18,81 @@ class My extends PureComponent {
data: []
}
}
// 去登录
toLogin = () => {
this.props.history.push('/passport')
}
render() {
let { history } = this.props;
const {user} = this.props
const uid = user && user.data && user.data.uid
const username = user && user.data && user.data.username
const avatar = user && user.data && user.data.avatar
const isVIP = user && user.data && user.data.isVIP
let list
if (!uid) {
list = <List className="my-list">
<Item
className="avatar-wrap"
arrow="horizontal"
multipleLine
thumb={Avatar}
onClick={this.toLogin}>
<Brief>点击登录</Brief>
</Item>
</List>
} else {
list = <List className="my-list">
<Link to='/myedit'>
<Item
className="avatar-wrap"
arrow="horizontal"
multipleLine
thumb={avatar}
>
<Brief>
{username}
{
isVIP === 1 &&
<img src={Vip} className='vip' alt=""/>
}
</Brief>
<Brief style={{fontSize: "12px"}}>学号: {uid}</Brief>
</Item>
</Link>
{
(isVIP === 0 || !isVIP) &&
<div className="my-isvip"></div>
}
</List>
}
return (
<div className="flex-container">
<Flex>
<Flex.Item>
<NavBar
className="my-tab"
mode="light"
>
我的
</NavBar>
{/* <List className="my-list">
<Item
className="avatar-wrap"
arrow="horizontal"
multipleLine
thumb={Avatar}
onClick={() => { }}>
<Brief>点击登录</Brief>
</Item>
</List> */}
<List className="my-list">
<Item
className="avatar-wrap"
arrow="horizontal"
multipleLine
thumb={Avatar}
onClick={() => {
}}>
<Brief style={{fontSize: "18px"}}>
xuan先生
<img src={Vip} alt=""/>
</Brief>
<Brief style={{fontSize: "12px"}}>学号: 410026</Brief>
</Item>
<div className="my-isvip"></div>
{/* <div className="my-shadow"></div> */}
</List>
<List>
<Item
arrow="horizontal"
onClick={() => {
}}
>
<i className="iconfont iconiconfront-27"></i>
已购课程
</Item>
<HeaderBar title='我的' arrow={false} cart={false}></HeaderBar>
{list}
<div className="am-list-header"></div>
<List className="my-list-content">
<Link to='/purchased'>
<Item arrow="horizontal">
<i className="iconfont iconiconfront-27"></i>
已购课程
</Item>
</Link>
<Link to='/shopcart'>
<Item
arrow="horizontal"
onClick={() => {
}}
>
<i className="iconfont icongouwuche"></i>
<Item arrow="horizontal">
<i className="iconfont icongouwuche-xianxing"></i>
购物车
</Item>
</Link>
<Link to='/myorders'>
<Item
arrow="horizontal"
onClick={() => {
}}
>
<Item arrow="horizontal">
<i className="iconfont iconiconfront-24"></i>
课程订单
</Item>
......@@ -92,27 +103,20 @@ class My extends PureComponent {
from: this.props.location.pathname
}
}}>
<Item
arrow="horizontal"
>
<Item arrow="horizontal" className="no-border">
<i className="iconfont iconiconfront-52"></i>
优惠券
</Item>
</Link>
<div className="am-list-header"></div>
</List>
<Link to='/scholarship'>
<List renderHeader={() => ''}>
<Item
arrow="horizontal"
onClick={() => {
}}
>
<Link to='/scholarship'>
<Item arrow="horizontal" className='btm-scholarship'>
<i className="iconfont iconiconfront-51"></i>
赚奖学金
</Item>
</List>
</Link>
</Link>
</List>
</Flex.Item>
</Flex>
......@@ -123,4 +127,7 @@ class My extends PureComponent {
}
export default WithTab(My);
\ No newline at end of file
export default connect(
state => ({user: state.user}),
null
)(WithTab(My))
.flex-container {
.my-tab {
width: 100%;
height: 44px;
font-size: $font_16;
background: $bg_f7f9fc;
}
.my-tab {
width: 100%;
height: 44px;
font-size: $font_16;
background: $bg_f7f9fc;
}
.my-list {
.avatar-wrap {
padding: 15px 20px;
}
.my-list-content {
.am-list-item-middle {
height: 50px;
.am-list-line {
border-bottom: 1px solid $border_e7eaf1;
padding: 0;
}
}
.my-isvip {
width: 100%;
height: 43px;
background-image: url("./image/vip_bg.png");
background-size: cover;
background-repeat: no-repeat;
border-radius: 3px;
.no-border {
.am-list-line {
border-bottom: none;
}
}
}
.my-stu {
font-size: 12px;
.my-list {
.avatar-wrap {
padding: 15px 20px;
height: 95px;
}
}
.my-isvip {
width: 100%;
height: 43px;
background-image: url("./image/vip_bg.png");
background-size: cover;
background-repeat: no-repeat;
border-radius: 3px;
}
// 修改List组件默认样式
.am-list-item {
padding-left: 22px;
padding-right: 8px;
.my-stu {
font-size: 12px;
}
// 修改List组件默认样式
.am-list-item {
padding: 0 20px;
.vip {
width: 18px;
height: 17px;
margin-left: 6px;
}
}
.am-list-item .am-list-line-multiple {
padding-right: 0px !important;
}
.am-list-item .am-list-line-multiple {
padding-right: 0px !important;
.am-list-thumb {
img {
width: 64px;
height: 64px;
border-radius: 50%;
}
}
.am-list-thumb {
img {
width: 64px;
height: 64px;
}
.am-list-brief {
color: $color_333 !important;
}
.am-list-header {
padding: 2.5px 0;
background: $bg_f5f5f5;
}
.am-list-content {
font-size: 14px !important;
color: $color_333 !important;
i {
vertical-align: middle;
display: inline-block;
margin: 10px 12px 10px 0;
font-size: 18px !important;
}
}
.am-list-brief {
color: $color_333 !important;
.my-list {
.am-list-arrow {
width: 8px !important;
height: 15px !important;
}
}
.am-list-header {
padding: 2.5px 0;
background: $bg_f5f5f5;
.am-list-body {
.am-list-arrow {
width: 7px;
height: 12px;
}
}
.am-list-content {
i {
vertical-align: middle;
margin-top: -1px;
display: inline-block;
margin-right: 12px;
margin: 10px 12px 10px 0;
font-size: 30px !important;
}
.am-list-line-multiple::after {
background-color: transparent !important;
}
.my-list {
.am-list-body::after {
background-color: transparent !important;
}
}
.am-list-body::after {
background-color: $bg_fff !important;
}
.am-list-content i {
margin: 0;
margin-top: -4px;
margin-right: 10px;
}
.am-list-body::before {
background-color: transparent !important;
height: 0 !important;
}
}
.am-list-line-multiple::after {
background-color: transparent !important;
.edit-name {
width: 100%;
height: 100%;
background-color: $bg_f5f5f5;
position: relative;
.my-mess {
width: 100%;
height: 94px;
padding: 0 20px;
line-height: 94px;
font-size: 16px;
background-color: $bg_fff;
img {
width: 64px;
height: 64px;
border-radius: 50%;
margin-right: 15px;
vertical-align: middle;
}
.my-list {
.am-list-body::after {
background-color: transparent !important;
}
.name {
display: inline-block;
margin-left: 15px;
color: $color_666;
}
.am-list-content i {
margin: 0;
margin-top: -4px;
margin-right: 10px;
.edit {
color: $active;
float: right;
}
}
.out-login {
width: 100%;
height: 44px;
background-color: $bg_fff;
line-height: 44px;
text-align: center;
font-size: 16px;
color: $color_333;
position: absolute;
bottom: 50px;
}
.am-list-body::before {
background-color: transparent !important;
height: 0 !important;
.edit-mbc {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, .5);
.edit-content {
background-color: $bg_fff;
width: 300px;
height: 135px;
border-radius: 5px;
margin: 224px auto 0 auto;
text-align: center;
padding-top: 20px;
.edit-title {
font-size: 16px;
color: $color_333;
height: 16px;
line-height: 16px;
}
input {
width: 240px;
height: 30px;
border: 1px solid $border_ddd;
border-radius: 3px;
padding-left: 15px;
margin-top: 15px;
}
.edit-btn {
height: 40px;
margin-top: 15px;
font-size: 16px;
border-top: 1px solid $border_ddd;
button {
background-color: $bg_fff;
width: 50%;
height: 100%;
border: none;
}
.cancle {
border-right: 1px solid $border_ddd;
border-radius: 0 0 0 3px;
}
.submit {
color: $active;
border-radius: 0 0 3px 0;
}
}
}
}
}
\ No newline at end of file
import React, {Component} from 'react';
import './index.scss';
import React, {Component} from 'react'
import './index.scss'
import {HeaderBar} from '../../common'
import OrderList from '@/common/OrderList';
import {http, api} from "@/utils";
import OrderList from '@/common/OrderList'
import {http, api} from "@/utils"
import {Link} from 'react-router-dom'
import {Checkbox, NavBar, Modal, Toast} from 'antd-mobile'
import {Modal, Toast} from 'antd-mobile'
const alert = Modal.alert;
......@@ -61,38 +61,44 @@ class MyOrders extends Component {
return (
<div className='myorders-box'>
<HeaderBar title={'我的订单'}></HeaderBar>
<HeaderBar title='我的订单' arrow={true} cart={false}></HeaderBar>
{
this.state.data && this.state.data.length > 0 && this.state.data.map((item, index) => {
return (
<div className="order-body" key={index}>
<OrderInfo item={item}/>
{
item.course && item.course.length > 0 && item.course.map((item, index) => {
const Info = (
<div className="order-info">
<p className='order-title text-overflow-one'>
<Link to={`/detail?id=${item.course_id}`}>{item.course_title}</Link>
</p>
<p className='order-content text-overflow-2'>{item.description}</p>
<p className='order-des'>
<span className='order-newprice'>¥{item.pay_amount}</span>
<span className='order-price'>¥{item.price0}</span>
</p>
</div>
)
return (
<div className="order-wrap" key={index}>
<OrderList info={Info} src={item.image_name} id={item.course_id}></OrderList>
</div>
)
})
}
<PayInfo item={item} cancel={this.cancel}/>
</div>
)
})
this.state.data && this.state.data.length > 0 ?
this.state.data.map((item, index) => {
return (
<div className="order-body" key={index}>
<OrderInfo item={item}/>
{
item.course && item.course.length > 0 && item.course.map((item, index) => {
const Info = (
<div className="order-info">
<p className='order-title text-overflow-one'>
<Link
to={`/detail?id=${item.course_id}`}>{item.course_title}</Link>
</p>
<p className='order-content text-overflow-2'>{item.description}</p>
<p className='order-des'>
<span className='order-newprice'>¥{item.pay_amount}</span>
<span className='order-price'>¥{item.price0}</span>
</p>
</div>
)
return (
<div className="order-wrap" key={index}>
<OrderList info={Info} src={item.image_name}
id={item.course_id}></OrderList>
</div>
)
})
}
<PayInfo item={item} cancel={this.cancel}/>
</div>
)
}) : <div className="cart-tip">
<p className='cart-mess'>您还没有订单哦,快去逛逛吧~</p>
<Link to='/classify'>去逛逛</Link>
</div>
}
</div>
......@@ -136,7 +142,7 @@ function PayInfo(props) {
props.item.pay_time === '0' && props.item.member_num === 0 &&
<div className='btm-right'>
<button className='cancel' onClick={event => props.cancel(props.item.oid)}>取消订单</button>
<Link to='/'>去支付</Link>
<Link to='/order'>去支付</Link>
</div>
}
......
.myorders-box {
width: 100%;
height: 100%;
background-color: $bg_f5f5f5;
.order-body {
......@@ -100,4 +101,31 @@
}
}
.cart-tip {
color: #555;
margin-top: 140px;
text-align: center;
.iconfridge {
font-size: 21px;
}
.cart-mess {
font-size: 12px;
color: $color_666;
}
a {
display: inline-block;
width: 130px;
height: 30px;
border: 1px solid $bg_active;
border-radius: 15px;
font-size: 16px;
margin-top: 30px;
color: $active;
text-align: center;
line-height: 28px;
}
}
}
\ No newline at end of file
.custom-button {
width:300px;
height:44px;
border-radius:3px;
width: 300px;
height: 44px;
border-radius: 3px;
-webkit-appearance: none;
border: none;
font-size: $font_18;
color: $white;
&.active {
background: $active;
color: $white;
}
}
\ No newline at end of file
......@@ -3,9 +3,9 @@ import './button.scss'
import classnames from 'classnames'
const Button = ({className, children}) => {
const Button = ({children, active}) => {
return (
<button className={classnames('custom-button', className)}>
<button className={classnames('custom-button', {active})}>
{children}
</button>
);
......
import React, { Component } from 'react';
import './veri-code-input.scss'
import { http, api } from '@/utils';
import { http, api, validateEmail, validateTel } from '@/utils';
import { Toast } from "antd-mobile";
import { has } from 'lodash'
import classnames from 'classnames'
......@@ -17,11 +18,12 @@ class VeriCodeInput extends Component {
}
timer = null
countDown = () => {
let {count} = this.state
if (!this.state.isFirst) {
Toast.info('请重新进行滑块验证',2,null,false)
Toast.info('请重新进行滑块验证', 2, null, false)
this.props.instance.refresh()
this.setState({
isFirst: true
......@@ -45,8 +47,40 @@ class VeriCodeInput extends Component {
}
}
getType = () => {
const {account} = this.props
if (validateEmail(account)) {
return 'email'
}
}
sendCode = () => {
if (!this.validate()) return
console.log(this.getType())
this.getType() === 'email' ? this.sendEmail() : this.sendSMS();
return true;
}
sendEmail = () => {
const {account, challenge} = this.props
http.post(`${api['passport-api']}/send_email_code`, {
email: account,
challenge
}).then(res => {
if (res.data.errno === 0) {
Toast.info('验证码发送成功', 2, null, false)
} else {
Toast.info(res.data.msg, 2, null, false)
}
this.setState({
isFirst: false
})
})
}
sendSMS = () => {
const {action, tel, challenge} = this.props
http.post(`${api['passport-api']}/quick_sms`, {
phone_num: tel,
......@@ -62,15 +96,23 @@ class VeriCodeInput extends Component {
isFirst: false
})
})
return true
}
validate = () => {
const {tel, challenge} = this.props
if (!tel) {
Toast.info('手机号码不能为空', 2, null, false)
const {tel, challenge, account} = this.props
let hasTel = has(this.props, 'tel')
let content
if (hasTel) {
content = '手机号码不能为空'
} else {
content = '手机号或电子邮件不能为空'
}
if ((hasTel && !tel) || (!hasTel && !account)) {
Toast.info(content, 2, null, false)
return false
}
if (!challenge) {
Toast.info('请进行滑块验证', 2, null, false)
return false
......
.forgot-password {
height: 100%;
padding: 38px 36px;
.content {
padding: 38px 36px;
}
.place {
width: 100%;
......@@ -13,12 +18,8 @@
margin-bottom: 21px;
}
.verify-code{
.verify-code {
margin-bottom: 21px;
}
.next {
background: $active;
color: $white;
}
}
\ No newline at end of file
import React, { Component } from 'react'
import './forgot-password.scss'
import ClearableInput from '@common/ClearableInput'
import VeriCodeButton from '../common/veriCodeInput'
import VeriCodeInput from '../common/veriCodeInput'
import Button from '../common/Button'
import { withFormik, Form, Field } from 'formik';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { Toast } from "antd-mobile";
import { HeaderBar, Captcha, ClearableInput } from "@/common";
import { validateTel, validateEmail } from "@/utils";
import { quickLogin } from '@/store/userAction';
import { isEmpty } from "lodash";
class ForgotPassword extends Component {
constructor(props) {
super(props);
this.state = {
verificationCode: '',
password: ''
}
state = {
validate: null,
captchaInstance: null
}
setTel = (val) => {
this.setState({tel: val})
}
setVerificationCode = (val) => {
this.setState({verificationCode: val});
getCaptchaInstance = instance => {
this.setState({
captchaInstance: instance
})
}
onVerify = (err, data) => {
if (err) {
console.log(err)
} else {
this.setState({
validate: data.validate
})
}
}
render() {
const {
values,
errors
} = this.props
console.log(this.props)
return (
<div className={'forgot-password'}>
<ClearableInput
type={'tel'}
placeholder={'请输入注册时的邮箱账号或手机号'}
onChange={this.setTel}
wrapperClass={'tel-input'}
icon={<i className={'iconfont iconshouji'}
style={{fontSize: '22px', left: '11px'}}
/>}
/>
<VeriCodeButton
className={'verify-code'}
onChange={this.setVerificationCode}
icon={<i className={'iconfont iconduanxin'}
style={{fontSize: '20px', left: '12px'}}
/>}
/>
<div className="place"/>
<Button className={'next'}>下一步</Button>
<HeaderBar title='忘记密码'/>
<div className="content">
<Form className='forgot-password-form'>
<Field
name={'account'}
render={({field, form}) => {
return (
<ClearableInput
{...field}
setValues={form.setValues}
type={'tel'}
placeholder={'请输入注册时的邮箱账号或手机号'}
wrapperClass={'tel-input'}
icon={<i className={'iconfont iconshouji'}
style={{fontSize: '22px', left: '11px'}}
/>}
/>)
}}
/>
{
this.state.validate &&
<Field
name='veriCode'
render={({field}) => {
return (
<VeriCodeInput
{...field}
className={'verify-code'}
icon={<i className={'iconfont iconduanxin'}
style={{fontSize: '20px', left: '12px'}}
/>}
account={values.account}
challenge={this.state.validate}
instance={this.state.captchaInstance}
/>
)
}}
/>
}
<Captcha getInstance={this.getCaptchaInstance} onVerify={this.onVerify}/>
<Button active={values.account && values.veriCode && isEmpty(errors)}>下一步</Button>
</Form>
</div>
</div>
);
}
}
export default ForgotPassword
\ No newline at end of file
const formikConfig = {
mapPropsToValues: () => ({
account: '',
veriCode: ''
}),
validateOnchange: true,
validate: values => {
let errors = {}
if (!validateTel(values.account) && !validateEmail(values.account)) {
errors.account = '请输入正确的手机号或邮箱地址'
}
return errors
},
handleSubmit(values, {props}) {
console.log(props)
props.quickLogin({
phone_num: values.account,
phone_code: values.veriCode
}).then(res => {
if (res.hasError) {
Toast.info(res.msg);
} else {
let state = props.location.state || {from: {pathname: '/'}}
props.history.replace(state.from)
}
})
},
}
export default compose(
connect(
null,
{quickLogin}
),
withFormik(formikConfig)
)(ForgotPassword)
\ No newline at end of file
......@@ -44,7 +44,6 @@ class Passport extends Component {
render() {
let {match, location} = this.props
console.log(location)
return (
<div className="passport">
<Switch>
......
......@@ -7,12 +7,12 @@ import Header from '../common/Header'
import VeriCodeInput from '../common/veriCodeInput'
import { Form, Field, withFormik } from "formik"
import Captcha from '@/common/Captcha'
import { http, api } from '@/utils';
import { quickLogin } from '@/store/userAction';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { isEmpty } from 'lodash'
import { Toast } from 'antd-mobile';
import {validateTel} from "@/utils";
class WechatLogin extends Component {
......@@ -124,7 +124,7 @@ const FormikConfig = {
validateOnChange: true,
validate: (values) => {
let errors = {}
if (!/^1[3-9](\d{9})$/.test(values.tel)) {
if (!validateTel(values.tel)) {
errors.tel = '请填写正确格式的手机号'
}
if (!/[0-9]{6}/.test(values.veriCode)) {
......
import React, { Component } from 'react';
import './set-password.scss'
import { withFormik, Form, Field } from "formik";
import PasswordInput from '../common/passwordInput'
import Button from '../common/Button'
import classnames from 'classnames'
import { compose } from 'redux'
class SetPassword extends Component {
......@@ -26,14 +26,25 @@ class SetPassword extends Component {
}
render() {
return (
<div className={'set-password'}>
<p className='title'>密码需要包含6-16位字母及数字</p>
<PasswordInput
placeholder={'设置密码'}
onChange={this.handleChange}
/>
<Button className={'btn-active'}>完成</Button>
<Form>
<Field
name='password'
render={({field}) => {
return (
<PasswordInput
placeholder={'设置密码'}
onChange={this.handleChange}
{...field}
/>
)
}}
/>
<Button className={'btn-active'}>完成</Button>
</Form>
<p className='user-agreement'>
<i className={classnames({
'iconfont iconiconfront-3': this.state.agree,
......@@ -47,4 +58,15 @@ class SetPassword extends Component {
}
}
export default SetPassword;
\ No newline at end of file
const formikConfig = {
mapValuesToProps: () => ({
password: ''
}),
handleSubmit: (values) => {
}
}
export default compose(
withFormik(formikConfig)
)(SetPassword);
\ No newline at end of file
......@@ -5,7 +5,7 @@ import {VList} from '../../common'
import {http, api} from "@/utils";
import {Link} from 'react-router-dom'
import {Toast} from 'antd-mobile'
import {connect} from "react-redux";
import {connect} from "react-redux"
class Purchased extends Component {
constructor(props) {
......@@ -19,12 +19,6 @@ class Purchased extends Component {
this.getList()
}
componentDidUpdate(prevProps, prevState) {
const {user} = this.props
console.log(user && user.data && user.data.uid);
}
// 获取订单
getList = () => {
http.get(`${api.home}/m/my/courses`,).then((res) => {
......@@ -44,7 +38,7 @@ class Purchased extends Component {
const uid = user && user.data && user.data.uid
return (
<div className='purchased-box'>
<HeaderBar title={'已购课程'}></HeaderBar>
<HeaderBar title='已购课程' arrow={true} cart={false}></HeaderBar>
{
this.state.data && this.state.data.length > 0 ?
<div className="purchased-body">
......@@ -73,7 +67,6 @@ class Purchased extends Component {
}
</div>
: <div className="cart-tip">
<p><i className='iconfont iconfridge'></i></p>
<p className='cart-mess'>您还没有课程哦,快去逛逛吧~</p>
<Link to='/classify'>去逛逛</Link>
</div>
......
......@@ -2,7 +2,9 @@ import React, {Component} from 'react'
import './index.scss'
import {HeaderBar} from '../../common'
import {http, api, getParam} from '@/utils'
import QRCode from 'qrcode';
import QRCode from 'qrcode'
import { Toast} from 'antd-mobile'
class SharePoster extends Component {
......@@ -32,6 +34,8 @@ class SharePoster extends Component {
name: res.data.data.username
})
this.initCanvas(this.state.bgImage, 0)
} else {
Toast.info(res.data.msg, 2)
}
})
}
......@@ -225,7 +229,7 @@ class SharePoster extends Component {
render() {
return (
<div className='share-poster'>
<HeaderBar title={'生成专属海报'}></HeaderBar>
<HeaderBar title='生成专属海报' arrow={true} cart={false}></HeaderBar>
<div className="total-container">
<div className='placard-img-container' id='imgWrapper'>
<img src={this.state.billSrc.src} alt=""/>
......
......@@ -25,7 +25,6 @@ class cartList extends Component {
)
})
: <div className="cart-tip">
<p><i className='iconfont iconfridge'></i></p>
<p className='cart-mess'>这里是空的,快去逛逛吧~</p>
<Link to='/classify'>去逛逛</Link>
</div>
......
import React, {Component} from 'react'
import {connect} from 'react-redux'
import {Checkbox, NavBar, Modal, Toast} from 'antd-mobile'
import {Checkbox, Modal, Toast} from 'antd-mobile'
import {HeaderBar} from '../../common'
//组件
import ShopCart from './cartList.js'
......@@ -126,7 +127,7 @@ class Cart extends Component {
}
// 删除
detail = () => {
todelete = () => {
if (this.state.courseIdarr.length > 0) {
alert('', '确定从购物车中删除?', [
{text: '取消', onPress: () => console.log('cancel')},
......@@ -155,18 +156,7 @@ class Cart extends Component {
render() {
return (
<div className="cart-page" style={{overflow: 'hidden'}}>
<NavBar
style={{"height": "44px"}}
className="order-tab"
mode="light"
icon={<i style={{"fontSize": '24px'}} className="iconfont iconiconfront-68"></i>}
rightContent={[
<i key="0" style={{"fontSize": '24px'}} className="iconfont iconiconfront-56"
onClick={this.detail}></i>
]}
>
购物车
</NavBar>
<HeaderBar title='购物车' arrow={true} cart={false} delete={true} toDelete={this.todelete}></HeaderBar>
<div className="cart-body">
<ShopCart checkChange={this.checkChange.bind(this)} data={this.state.data}/>
......
......@@ -4,6 +4,7 @@ import loadable from '@loadable/component'
import Index from '@/components/Index';
import Classify from '@/components/classify';
import My from '@/components/my';
import MyEdit from '@/components/my/edit';
import CourseList from '@/components/classify/courselist';
import Order from '@/components/order/index';
import Orderinfo from '@/components/order/orderinfo';
......@@ -44,6 +45,10 @@ export default [
component: My
},
{
path: '/myedit',
component: MyEdit
},
{
path: '/courselist',
component: CourseList
},
......
export { default as http } from './http'
export { default as api } from './api'
export { html, initCaptcha }
export { html, initCaptcha, validateTel, validateEmail }
export const getParam = (key, str) => {
......@@ -69,3 +69,12 @@ export const is_weixin = () => {
}
return false;
}
function validateTel(tel) {
return /^1[3-9](\d{9})$/.test(tel)
}
function validateEmail(email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(String(email).toLowerCase());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment