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