Commit 4fa39372 by 姜雷

完成首页和注册以及部分主页

parent aa361867
import createFetch from './index';
import { BASE_SERVER_URL } from '../constants/index';
const fetch = createFetch(BASE_SERVER_URL + '/dcxy/api');
export const fetchAllCampus = () =>
fetch({
url: '/campus/all',
});
import Taro, { request } from '@tarojs/taro'; import Taro, { request } from '@tarojs/taro';
import { BASE_SERVER_URL } from '../constants/index'; import store from '../store/index';
type ResponseDataEntity = { export type ResponseDataEntity = {
code: number; code: number;
msg: string; msg: string;
data: any; data: any;
...@@ -13,19 +13,28 @@ type ResponseEntity = { ...@@ -13,19 +13,28 @@ type ResponseEntity = {
[propName: string]: any; [propName: string]: any;
}; };
const fetch = (entity: request.Param) => { const createFetch = (basePath: string) => {
return Taro.request({ return (entity: request.Param): Promise<ResponseDataEntity> => {
...entity, const token = store.getState().userinfo.token;
header: { return Taro.request({
token: '', ...entity,
}, header: token
url: BASE_SERVER_URL + entity.url, ? {
}).then(({ data }: ResponseEntity) => { token: token,
if (data.code === 1000) { }
return data; : {},
} url: basePath + entity.url,
throw data; }).then(({ data }: ResponseEntity) => {
}); if (data.code === 1000) {
return data;
}
Taro.showToast({
title: data.msg,
icon: 'none',
});
throw data;
});
};
}; };
export default fetch; export default createFetch;
import fetch from './index';
export const login = data =>
fetch({
url: '/wx/api/user/login2',
data: data,
});
export const fetchAllCampus = () =>
fetch({
url: '/dcxy/api/campus/all',
});
import createFetch, { ResponseDataEntity } from './index';
import { BASE_SERVER_URL } from '../constants/index';
const fetch = createFetch(BASE_SERVER_URL + '/wx/api');
type LoginPramas = {
code: string;
};
type LoginReponseData = {
registed: boolean;
token: string;
};
export interface LoginReponse extends ResponseDataEntity {
data: LoginReponseData;
}
export const login = (data: LoginPramas): Promise<LoginReponse> =>
fetch({
url: '/user/login2',
data: data,
});
export const fetchValidateCode = () =>
fetch({
url: '/getValidateCode',
});
export const getImageVcode = () =>
fetch({
url: '/getImageValidateCode',
});
export const getVcode = entity =>
fetch({
url: '/getValidateCode',
method: 'POST',
data: entity,
});
type RegisiterPramas = {};
// type RegisiterReponseData = {};
export const fetchWxUserRegister = (entity: RegisiterPramas) =>
fetch({
url: '/user/regisiter2',
method: 'POST',
data: entity,
});
...@@ -30,3 +30,42 @@ button[disabled]:not([type]) { ...@@ -30,3 +30,42 @@ button[disabled]:not([type]) {
width: 100%; width: 100%;
border-top: 1px solid #eee; border-top: 1px solid #eee;
} }
.registerBox-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 80px;
line-height: 80px;
border-bottom: 1px solid #eee;
color: #333;
.loginBox-placeholder,
.noVlaue {
color: #999;
}
.loginBox-input {
width: 100%;
height: 100%;
font-size: 28px;
}
.registerBox-getVcode {
position: relative;
width: 268px;
text-align: center;
font-size: 28px;
color: #456beb;
}
.registerBox-getVcode::before {
content: '';
position: absolute;
left: 0px;
top: 26px;
height: 28px;
border-left: 1px solid #eee;
}
.registerBox-pwdIcon {
width: 44px;
height: 44px;
}
}
...@@ -4,7 +4,7 @@ import { Provider } from '@tarojs/redux'; ...@@ -4,7 +4,7 @@ import { Provider } from '@tarojs/redux';
import Index from './pages/index'; import Index from './pages/index';
import configStore from './store'; import store from './store';
import './app.scss'; import './app.scss';
...@@ -14,8 +14,6 @@ if (process.env.NODE_ENV !== 'production' && process.env.TARO_ENV === 'h5') { ...@@ -14,8 +14,6 @@ if (process.env.NODE_ENV !== 'production' && process.env.TARO_ENV === 'h5') {
require('nerv-devtools'); require('nerv-devtools');
} }
const store = configStore();
class App extends Component { class App extends Component {
/** /**
* 指定config的类型声明为: Taro.Config * 指定config的类型声明为: Taro.Config
...@@ -26,9 +24,11 @@ class App extends Component { ...@@ -26,9 +24,11 @@ class App extends Component {
*/ */
config: Config = { config: Config = {
pages: [ pages: [
'pages/Home/Home',
'pages/index/index', 'pages/index/index',
'pages/ResetPwd/ResetPwd',
'pages/Register/Register', 'pages/Register/Register',
// 'pages/Login/Login', 'pages/Login/Login',
// 'pages/CheckTelephone/CheckTelephone', // 'pages/CheckTelephone/CheckTelephone',
// 'pages/Feedback/Feedback', // 'pages/Feedback/Feedback',
// 'pages/Order/OrderDetail/OrderDetail', // 'pages/Order/OrderDetail/OrderDetail',
......
.ToastBox {
position: absolute;
top: -100px;
left: 50%;
padding: 0 20px;
min-width: 200px;
height: 64px;
line-height: 64px;
text-align: center;
background-color: #ffd506;
border-radius: 48px;
transform: translate(-50%);
transition: all 400ms;
color: #fff;
opacity: 0;
}
.ToastBox.show {
top: 30px;
opacity: 1;
}
import { ComponentClass } from 'react';
import Taro, { Component } from '@tarojs/taro';
import { View } from '@tarojs/components';
import './ToastBox.scss';
type PageOwnProps = {};
type PageState = {
text: string;
visiable: boolean;
timer: number | undefined;
};
interface ToastBox {
props: PageOwnProps;
state: PageState;
}
class ToastBox extends Component {
constructor(props: PageOwnProps) {
super(props);
this.state = {
text: '提示',
visiable: false,
timer: undefined,
};
}
showToast(newText: string) {
const { timer } = this.state;
if (timer) {
clearTimeout(timer);
}
setTimeout(() => {
this.setState({
visiable: false,
});
}, 3000);
this.setState({
text: newText,
visiable: true,
});
}
render() {
const { text, visiable } = this.state;
return <View className={`ToastBox ${visiable ? 'show' : ''}`}>{text}</View>;
}
}
export default ToastBox as ComponentClass<PageOwnProps, PageState>;
...@@ -3,9 +3,11 @@ import Taro, { Component } from '@tarojs/taro'; ...@@ -3,9 +3,11 @@ import Taro, { Component } from '@tarojs/taro';
import { View } from '@tarojs/components'; import { View } from '@tarojs/components';
import './Vcode.scss'; import './Vcode.scss';
import { getVcode } from '../../api/wx';
type PageOwnProps = { type PageOwnProps = {
text?: string; text?: string;
cellphone: string;
}; };
type PageState = { type PageState = {
defaultText: string; defaultText: string;
...@@ -24,6 +26,7 @@ class Vcode extends Component { ...@@ -24,6 +26,7 @@ class Vcode extends Component {
constructor(props: PageOwnProps) { constructor(props: PageOwnProps) {
super(props); super(props);
this.state = { this.state = {
defaultText: props.text ? props.text : '获取验证码', defaultText: props.text ? props.text : '获取验证码',
counting: false, counting: false,
...@@ -39,6 +42,29 @@ class Vcode extends Component { ...@@ -39,6 +42,29 @@ class Vcode extends Component {
} }
} }
clickHandle() {
const { cellphone } = this.props;
if (cellphone && cellphone.length == 11) {
getVcode({
tel: cellphone,
})
.then(res => {
this.countStart();
Taro.showToast({
title: res.msg,
mask: true,
});
})
.catch(console.error);
} else {
Taro.showToast({
title: '输入正确的手机号',
icon: 'none',
mask: true,
});
}
}
countStart() { countStart() {
this.setState({ this.setState({
counting: true, counting: true,
...@@ -66,9 +92,9 @@ class Vcode extends Component { ...@@ -66,9 +92,9 @@ class Vcode extends Component {
render() { render() {
const { defaultText, counting, count } = this.state; const { defaultText, counting, count } = this.state;
return counting ? ( return counting ? (
<View className='vcode-classname Vcode Counting'>{`${count}S`}</View> <View className='vcode-classname Vcode Counting'>{`${count}S后重发`}</View>
) : ( ) : (
<View className='vcode-classname Vcode' onClick={this.countStart}> <View className='vcode-classname Vcode' onClick={this.clickHandle}>
{defaultText} {defaultText}
</View> </View>
); );
......
.Home {
padding: 0 32px;
.Home-UserBox {
position: relative;
width: 100%;
height: 390px;
}
.Home-UserBox-bg {
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
}
.Home-UserBox-info {
padding: 80px 88px 20px 76px;
display: flex;
justify-content: space-between;
color: #333;
}
.Home-UserBox-name {
font-size: 44px;
margin-bottom: 8px;
}
.Home-UserBox-tel {
font-size: 32px;
margin-bottom: 8px;
}
.Home-UserBox-addr {
font-size: 24px;
}
.Home-UserBox-headimg {
width: 100px;
height: 100px;
border-radius: 50%;
border: 10px solid #c8ccfc;
}
.Home-UserBox-line {
width: 620px;
border-top: 1px solid #d7daff;
margin: 0 auto;
}
.Home-UserBox-Bean {
padding: 32px 40px 0;
display: flex;
justify-content: space-around;
}
.Home-UserBox-Order {
position: absolute;
left: 50%;
bottom: -40px;
transform: translate(-50%);
width: 572px;
height: 80px;
line-height: 80px;
background-color: #6180f4;
border-radius: 50px;
display: flex;
overflow: hidden;
}
.Home-UserBox-Order-text {
flex: 1;
text-align: center;
color: #fff;
font-size: 24px;
}
.Home-UserBox-Order-right {
background-color: #375ef1;
width: 212px;
display: flex;
justify-content: center;
align-items: center;
}
.Home-UserBox-Order-icon {
width: 40px;
height: 20px;
}
}
import { ComponentClass } from 'react';
import Taro, { Component } from '@tarojs/taro';
import { View, Image, Text } from '@tarojs/components';
import UserBoxBg from '../../images/home/img_bg@2x.png';
import UserImg from '../../images/home/pc_minel_icon@2x.png';
import ArrowIcon from '../../images/home/icon_dingdan@2x.png';
class Home extends Component {
render() {
return (
<View className='Home'>
<View className='Home-UserBox'>
<Image className='Home-UserBox-bg' src={UserBoxBg} />
<View className='Home-UserBox-info'>
<View className='Home-UserBox-other'>
<View className='Home-UserBox-name'>中小</View>
<View className='Home-UserBox-tel'>16878964216</View>
<View className='Home-UserBox-addr'>成都师范学校-温江小区</View>
</View>
<Image className='Home-UserBox-headimg' src={UserImg} />
</View>
<View className='Home-UserBox-line' />
<View className='Home-UserBox-Bean'>
<View className='Home-UserBox-BeanItem'>吹风豆:2.35</View>
<View className='Home-UserBox-BeanItem'>通用豆:12.35</View>
</View>
<View className='Home-UserBox-Order'>
<Text className='Home-UserBox-Order-text'>我的订单</Text>
<View className='Home-UserBox-Order-right'>
<Image className='Home-UserBox-Order-icon' src={ArrowIcon} />
</View>
</View>
</View>
<View>吹风</View>
<View>公告</View>
</View>
);
}
}
export default Home as ComponentClass;
...@@ -7,20 +7,8 @@ ...@@ -7,20 +7,8 @@
margin-top: 168px; margin-top: 168px;
color: #fff; color: #fff;
font-size: 48px; font-size: 48px;
}
.Login-loginWay-tab {
margin-top: 60px;
margin-bottom: 44px; margin-bottom: 44px;
} }
.Login-loginWay-item {
color: #c2cef9;
font-size: 32px;
margin-right: 28px;
}
.Login-loginWay-item.active {
color: #fff;
font-size: 40px;
}
.Login-vcodeBox, .Login-vcodeBox,
.Login-input { .Login-input {
height: 96px; height: 96px;
...@@ -57,7 +45,8 @@ ...@@ -57,7 +45,8 @@
} }
} }
.Login-regist { .Login-regist {
text-align: right; display: flex;
justify-content: space-between;
color: #c2cef9; color: #c2cef9;
margin-bottom: 52px; margin-bottom: 52px;
} }
......
...@@ -2,16 +2,11 @@ import { ComponentClass } from 'react'; ...@@ -2,16 +2,11 @@ import { ComponentClass } from 'react';
import Taro, { Component, Config } from '@tarojs/taro'; import Taro, { Component, Config } from '@tarojs/taro';
import { View, Button, Text, Input, Navigator } from '@tarojs/components'; import { View, Button, Text, Input, Navigator } from '@tarojs/components';
import Vcode from '../../components/Vcode/Vcode';
import './Login.scss'; import './Login.scss';
type PageState = { type PageState = {
loginWay: string;
vcode: string;
account: string; account: string;
pwd: string; pwd: string;
tel: string;
code: string;
}; };
interface Login { interface Login {
...@@ -26,86 +21,49 @@ class Login extends Component { ...@@ -26,86 +21,49 @@ class Login extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
loginWay: 'tel',
vcode: '',
account: '', account: '',
pwd: '', pwd: '',
tel: '',
code: '',
}; };
} }
toggleLoginWay(state: string) {
this.setState({ loginHandle() {}
loginWay: state,
});
}
render() { render() {
const { loginWay } = this.state;
return ( return (
<View className='Login'> <View className='Login'>
<View className='Login-title'>欢迎来到多彩校园</View> <View className='Login-title'>欢迎来到多彩校园</View>
<View className='Login-loginWay-tab'> <View>
<Text <Input
className={`Login-loginWay-item ${ className='Login-input'
loginWay === 'account' ? 'active' : '' placeholder-class='Login-input-placeholder'
}`} placeholder='请输入账号手机号'
onClick={() => this.toggleLoginWay('account')}> />
账号登录 <Input
</Text> className='Login-input'
<Text placeholder-class='Login-input-placeholder'
className={`Login-loginWay-item ${ password
loginWay === 'tel' ? 'active' : '' placeholder='请输入密码'
}`} />
onClick={() => this.toggleLoginWay('tel')}>
手机号登录
</Text>
</View> </View>
{loginWay === 'account' ? (
<View>
<Input
className='Login-input'
placeholder-class='Login-input-placeholder'
placeholder='请输入账号手机号'
/>
<Input
className='Login-input'
placeholder-class='Login-input-placeholder'
password
placeholder='请输入密码'
/>
</View>
) : (
<View>
<Input
className='Login-input'
type='number'
placeholder-class='Login-input-placeholder'
placeholder='请输入手机号'
maxLength={11}
/>
<View className='Login-vcodeBox'>
<Input
className='Login-input'
type='number'
placeholder-class='Login-input-placeholder'
placeholder='请输入验证码'
maxLength={6}
/>
<Vcode vcode-classname='Login-Vcode' text='获取验证码' />
</View>
</View>
)}
<View className='Login-regist'> <View className='Login-regist'>
还没有账号? <View>
还没有账号?
<Navigator
className='Login-regist-btn'
url='/pages/Register/Register'>
注册
</Navigator>
</View>
<Navigator <Navigator
className='Login-regist-btn' className='Login-regist-btn'
url='/pages/Register/Register'> url='/pages/ResetPwd/ResetPwd'>
注册 忘记密码
</Navigator> </Navigator>
</View> </View>
<Button className='Login-btn'>登录</Button> <Button className='Login-btn' onClick={this.loginHandle}>
登录
</Button>
</View> </View>
); );
} }
......
...@@ -15,24 +15,6 @@ ...@@ -15,24 +15,6 @@
margin-right: 10px; margin-right: 10px;
} }
} }
.registerBox-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 80px;
line-height: 80px;
border-bottom: 1px solid #eee;
color: #333;
.loginBox-placeholder,
.noVlaue {
color: #999;
}
.loginBox-input {
width: 100%;
height: 100%;
font-size: 28px;
}
}
.sexBox { .sexBox {
display: flex; display: flex;
.sexBox-item { .sexBox-item {
...@@ -46,25 +28,7 @@ ...@@ -46,25 +28,7 @@
margin-right: 20px; margin-right: 20px;
} }
} }
.registerBox-getVcode {
position: relative;
width: 268px;
text-align: center;
font-size: 28px;
color: #456beb;
}
.registerBox-getVcode::before {
content: '';
position: absolute;
left: 0px;
top: 26px;
height: 28px;
border-left: 1px solid #eee;
}
.registerBox-pwdIcon {
width: 44px;
height: 44px;
}
} }
.registerBox-agreeBox { .registerBox-agreeBox {
height: 60px; height: 60px;
......
...@@ -15,10 +15,11 @@ import './Register.scss'; ...@@ -15,10 +15,11 @@ import './Register.scss';
import agreeIcon from '../../images/login/icon_zhuce_sel@2x.png'; import agreeIcon from '../../images/login/icon_zhuce_sel@2x.png';
import agreeNotIcon from '../../images/login/icon_zhuce_nor@2x.png'; import agreeNotIcon from '../../images/login/icon_zhuce_nor@2x.png';
import { connect } from '@tarojs/redux'; import { connect } from '@tarojs/redux';
import { StoreState } from 'src/store/rootReducers/userinfo'; import { UserState } from '../../store/rootReducers/userinfo';
import { getVcode, fetchWxUserRegister } from '../../api/wx';
type PageStateProps = { type PageStateProps = {
userinfo: StoreState; userinfo: UserState;
}; };
type PageDispatchProps = { type PageDispatchProps = {
// updateUserInfo: (e: User) => void; // updateUserInfo: (e: User) => void;
...@@ -27,6 +28,7 @@ type PageDispatchProps = { ...@@ -27,6 +28,7 @@ type PageDispatchProps = {
type PageState = { type PageState = {
name: string; name: string;
cellphone: string; cellphone: string;
vcode: string;
pwd: string; pwd: string;
checkPwd: string; checkPwd: string;
sex: string; sex: string;
...@@ -52,10 +54,11 @@ class Register extends Component { ...@@ -52,10 +54,11 @@ class Register extends Component {
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.state = { this.state = {
name: '', name: '姜雷',
cellphone: '', cellphone: '18108096033',
pwd: '', vcode: '',
checkPwd: '', pwd: '123456',
checkPwd: '123456',
sex: 'Male', sex: 'Male',
agree: false, agree: false,
showPwd: false, showPwd: false,
...@@ -68,38 +71,75 @@ class Register extends Component { ...@@ -68,38 +71,75 @@ class Register extends Component {
sex: value, sex: value,
}); });
} }
getVcode() {
updateName({ detail: { value } }) { const { cellphone } = this.state;
this.setState({ if (cellphone.length == 11) {
name: value, // getVcode({
}); // tel: cellphone,
// })
// .then(res => {
// console.log(res);
// Taro.showToast({
// title: res.msg,
// mask: true,
// });
// })
// .catch(console.error);
this.refs.Vcode.countStart();
} else {
Taro.showToast({
title: '输入正确的手机号',
icon: 'none',
mask: true,
});
}
} }
validateRegisterEntity(): boolean { validateRegisterEntity(): boolean {
const { name, cellphone, pwd, checkPwd, agree } = this.state; const { name, cellphone, pwd, checkPwd } = this.state;
const {
userinfo: { campusId },
} = this.props;
if (!name) { if (!name) {
console.log('请输入姓名'); Taro.showToast({
title: '请输入姓名',
icon: 'none',
});
return false; return false;
} }
if (!cellphone || cellphone.length !== 11) { if (!cellphone || cellphone.length !== 11) {
console.log('请输入手机号码'); Taro.showToast({
title: '请输入手机号码',
icon: 'none',
});
return false; return false;
} }
if (!pwd) { if (!pwd) {
console.log('请输入密码'); Taro.showToast({
title: '请输入密码',
icon: 'none',
});
return false; return false;
} }
if (!checkPwd) { if (!checkPwd) {
console.log('请输入确认密码'); Taro.showToast({
title: '请输入确认密码',
icon: 'none',
});
return false; return false;
} }
if (pwd != checkPwd) { if (pwd != checkPwd) {
console.log('请输入确认密码'); Taro.showToast({
title: '请输入确认密码',
icon: 'none',
});
return false; return false;
} }
if (!agree) { if (!campusId) {
console.log('请勾选同意条款'); Taro.showToast({
title: '请选择所属校区',
icon: 'none',
});
return false; return false;
} }
return true; return true;
...@@ -107,9 +147,18 @@ class Register extends Component { ...@@ -107,9 +147,18 @@ class Register extends Component {
getRegister() { getRegister() {
if (this.validateRegisterEntity()) { if (this.validateRegisterEntity()) {
const { name, cellphone, pwd, checkPwd, sex } = this.state; const { name, cellphone, pwd, sex } = this.state;
console.log(name, cellphone, pwd, checkPwd, sex); const {
console.log('跳转首页'); userinfo: { campusId, schoolId },
} = this.props;
fetchWxUserRegister({
cellphone,
campusId,
name,
pwd,
schoolId,
sex,
});
} }
} }
...@@ -138,7 +187,17 @@ class Register extends Component { ...@@ -138,7 +187,17 @@ class Register extends Component {
} }
render() { render() {
const { sex, showPwd, showCheckPwd, agree } = this.state; const {
name,
sex,
showPwd,
showCheckPwd,
agree,
cellphone,
vcode,
pwd,
checkPwd,
} = this.state;
const { userinfo } = this.props; const { userinfo } = this.props;
return ( return (
<View className='Register topBr'> <View className='Register topBr'>
...@@ -152,6 +211,7 @@ class Register extends Component { ...@@ -152,6 +211,7 @@ class Register extends Component {
className='loginBox-input' className='loginBox-input'
placeholderClass='loginBox-placeholder' placeholderClass='loginBox-placeholder'
placeholder='输入您的姓名' placeholder='输入您的姓名'
value={name}
onInput={({ detail: { value } }) => { onInput={({ detail: { value } }) => {
this.setState({ this.setState({
name: value.trim(), name: value.trim(),
...@@ -187,6 +247,7 @@ class Register extends Component { ...@@ -187,6 +247,7 @@ class Register extends Component {
placeholderClass='loginBox-placeholder' placeholderClass='loginBox-placeholder'
placeholder='请输入注册的手机号码' placeholder='请输入注册的手机号码'
type='number' type='number'
value={cellphone}
onInput={({ detail: { value } }) => { onInput={({ detail: { value } }) => {
this.setState({ this.setState({
cellphone: value, cellphone: value,
...@@ -202,8 +263,13 @@ class Register extends Component { ...@@ -202,8 +263,13 @@ class Register extends Component {
placeholderClass='loginBox-placeholder' placeholderClass='loginBox-placeholder'
placeholder='请输入验证码' placeholder='请输入验证码'
maxLength={6} maxLength={6}
value={vcode}
/>
<Vcode
vcode-classname='registerBox-getVcode'
ref='Vcode'
onClickHandle={this.getVcode}
/> />
<Vcode vcode-classname='registerBox-getVcode' />
</View> </View>
<View className='registerBox-title'> <View className='registerBox-title'>
<Image className='registerBox-icon' src={pwdIcon} /> <Image className='registerBox-icon' src={pwdIcon} />
...@@ -216,6 +282,13 @@ class Register extends Component { ...@@ -216,6 +282,13 @@ class Register extends Component {
password={!showPwd} password={!showPwd}
placeholder='密码由6-20位组成' placeholder='密码由6-20位组成'
maxLength={20} maxLength={20}
value={pwd}
onInput={({ detail: { value } }) => {
this.setState({
pwd: value,
});
return value;
}}
/> />
<Image <Image
className='registerBox-pwdIcon' className='registerBox-pwdIcon'
...@@ -230,6 +303,13 @@ class Register extends Component { ...@@ -230,6 +303,13 @@ class Register extends Component {
password={!showCheckPwd} password={!showCheckPwd}
placeholder='确认密码' placeholder='确认密码'
maxLength={20} maxLength={20}
value={checkPwd}
onInput={({ detail: { value } }) => {
this.setState({
checkPwd: value,
});
return value;
}}
/> />
<Image <Image
className='registerBox-pwdIcon' className='registerBox-pwdIcon'
......
.ResetPwd {
.ResetPwd-form {
padding: 0 32px;
}
.ResetPwd-title {
margin-top: 52px;
margin-bottom: 32px;
font-size: 32px;
}
.ResetPwd-btn {
margin: 40px 16px 0;
border-radius: 24px;
}
}
import Taro, { Component, Config } from '@tarojs/taro';
import { ComponentClass } from 'react';
import { View, Input, Image, Button } from '@tarojs/components';
import Vcode from '../../components/Vcode/Vcode';
import pwdHideIcon from '../../images/login/setting_invisible_icon@2x.png';
import pwdShowIcon from '../../images/login/setting_see_icon@2x.png';
import './ResetPwd.scss';
type PageOwnProps = {};
type PageState = {
cellphone: string;
vcode: string;
pwd: string;
checkPwd: string;
showPwd: boolean;
showCheckPwd: boolean;
};
interface ResetPwd {
props: PageOwnProps;
state: PageState;
}
class ResetPwd extends Component {
config: Config = {
navigationBarTitleText: '找回APP登陆密码',
};
constructor(props: PageOwnProps) {
super(props);
this.state = {
cellphone: '',
vcode: '',
pwd: '',
checkPwd: '',
showPwd: false,
showCheckPwd: false,
};
}
togglePwdBox() {
this.setState(({ showPwd }: PageState) => ({
showPwd: !showPwd,
}));
}
togglePwdCheckBox() {
this.setState(({ showCheckPwd }: PageState) => ({
showCheckPwd: !showCheckPwd,
}));
}
validatePwdForm(): boolean {
const { pwd, checkPwd, cellphone, vcode } = this.state;
if (!cellphone || cellphone.length !== 11) {
Taro.showToast({
title: '请输入手机号码',
icon: 'none',
});
return false;
}
if (!vcode || vcode.length !== 6) {
Taro.showToast({
title: '请输入验证码',
icon: 'none',
});
return false;
}
if (!pwd || pwd.length < 6) {
Taro.showToast({
title: '请输入大于6位密码',
icon: 'none',
});
return false;
}
if (!checkPwd || checkPwd.length < 6) {
Taro.showToast({
title: '请输入大于6位密码',
icon: 'none',
});
return false;
}
if (pwd !== checkPwd) {
Taro.showToast({
title: '两次密码不一致',
icon: 'none',
});
return false;
}
return true;
}
resetPwd() {
if (this.validatePwdForm()) {
console.log('回到登陆');
Taro.redirectTo({
url: '/pages/Login/Login',
});
}
}
render() {
const { cellphone, vcode, showPwd, pwd, checkPwd } = this.state;
return (
<View className='ResetPwd'>
<View className='ResetPwd-form'>
<View className='ResetPwd-title'>请输入您的登陆手机号</View>
<View className='registerBox-item'>
<Input
className='loginBox-input'
placeholderClass='loginBox-placeholder'
placeholder='请输入注册的手机号码'
type='number'
value={cellphone}
onInput={({ detail: { value } }) => {
this.setState({
cellphone: value,
});
return value;
}}
maxLength={11}
/>
</View>
<View className='registerBox-item'>
<Input
className='loginBox-input'
placeholderClass='loginBox-placeholder'
placeholder='请输入验证码'
maxLength={6}
value={vcode}
/>
<Vcode
vcode-classname='registerBox-getVcode'
ref='Vcode'
cellphone={cellphone}
/>
</View>
<View className='ResetPwd-title'>设置新密码</View>
<View className='registerBox-item'>
<Input
className='loginBox-input'
placeholderClass='loginBox-placeholder'
password={!showPwd}
placeholder='输入6-20位新密码'
maxLength={20}
value={pwd}
onInput={({ detail: { value } }) => {
this.setState({
pwd: value,
});
return value;
}}
/>
<Image
className='registerBox-pwdIcon'
src={showPwd ? pwdShowIcon : pwdHideIcon}
onClick={this.togglePwdBox}
/>
</View>
<View className='registerBox-item'>
<Input
className='loginBox-input'
placeholderClass='loginBox-placeholder'
password={!showPwd}
placeholder='确认6-20位新密码'
maxLength={20}
value={checkPwd}
onInput={({ detail: { value } }) => {
this.setState({
checkPwd: value,
});
return value;
}}
/>
<Image
className='registerBox-pwdIcon'
src={showPwd ? pwdShowIcon : pwdHideIcon}
onClick={this.togglePwdCheckBox}
/>
</View>
</View>
<Button className='ResetPwd-btn' onClick={this.resetPwd}>
确定
</Button>
</View>
);
}
}
export default ResetPwd as ComponentClass<PageOwnProps, PageState>;
.Location { .Location {
background-color: #fff; background-color: #fff;
overflow-y: scroll; height: 100%;
-webkit-overflow-scrolling: touch;
.searchBox { .searchBox {
display: flex; display: flex;
height: 90px; height: 90px;
...@@ -36,6 +35,7 @@ ...@@ -36,6 +35,7 @@
} }
.infoBar { .infoBar {
position: fixed; position: fixed;
z-index: 2;
top: 262px; top: 262px;
right: 30px; right: 30px;
width: 40px; width: 40px;
...@@ -49,10 +49,12 @@ ...@@ -49,10 +49,12 @@
} }
.infoToast { .infoToast {
position: fixed; position: fixed;
z-index: 2;
width: 180px; width: 180px;
height: 180px; height: 180px;
line-height: 180px; line-height: 180px;
background-color: rgba(254, 148, 10, 0.4); background-color: #a2b5f5;
border-radius: 8px;
left: 9999px; left: 9999px;
top: 480px; top: 480px;
margin-left: -90px; margin-left: -90px;
...@@ -67,9 +69,7 @@ ...@@ -67,9 +69,7 @@
left: 50%; left: 50%;
} }
.locationList { .locationList {
height: 100%; height: calc(100vh - 90rpx);
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
} }
.locationTitle { .locationTitle {
padding: 0 40px; padding: 0 40px;
......
...@@ -2,67 +2,18 @@ import { ComponentClass } from 'react'; ...@@ -2,67 +2,18 @@ import { ComponentClass } from 'react';
import Taro, { Component, Config } from '@tarojs/taro'; import Taro, { Component, Config } from '@tarojs/taro';
import { connect } from '@tarojs/redux'; import { connect } from '@tarojs/redux';
import { View, Text, Input, Image } from '@tarojs/components'; import { View, Text, Input, Image, ScrollView } from '@tarojs/components';
import SearchIcon from '../../images/login/icon_search@2x.png'; import SearchIcon from '../../images/login/icon_search@2x.png';
import { Campus, CampusList } from '../../types/Campus/Campus'; import { Campus, CampusList } from '../../types/Campus/Campus';
import { fetchAllCampus } from '../../api/login'; import { fetchAllCampus } from '../../api/campus';
import { StoreState, updateUserInfo } from '../../store/rootReducers/userinfo'; import { UserState, updateUserInfo } from '../../store/rootReducers/userinfo';
import User from 'src/types/User/User'; import User from 'src/types/User/User';
const resData = [ import './SelectCampus.scss';
{
id: 47,
schoolId: 36,
name: '保定职业技术学院1',
mobile: '15212121222',
address: '河北省保定市新市区朝阳南大街613号',
introduce: '',
fd_version: '1',
isDel: 0,
openLattice: 'N',
firstPin: 'B',
},
{
id: 126,
schoolId: 36,
name: '保定职业技术学院测试学院1',
mobile: '15232569878',
address: '敖德萨所大所多',
introduce: '奥术大师多',
fd_version: '2',
isDel: 0,
openLattice: 'N',
firstPin: 'B',
},
{
id: 12,
schoolId: 6,
name: '成师温江校区',
mobile: '13608207722',
address: '海科路东段99号',
introduce: '',
fd_version: '1',
isDel: 0,
openLattice: 'N',
firstPin: 'C',
},
{
id: 116,
schoolId: 200004,
name: '成都正阳1.0校区 ',
mobile: '15881097999',
address: '四川省成都市温江区',
introduce: '用于虚拟客户体验使用',
fd_version: '1',
isDel: 0,
openLattice: 'N',
firstPin: 'C',
},
];
type PageStateProps = { type PageStateProps = {
userinfo: StoreState; userinfo: UserState;
}; };
type PageDispatchProps = { type PageDispatchProps = {
updateUserInfo: (e: User) => void; updateUserInfo: (e: User) => void;
...@@ -72,6 +23,9 @@ type PageState = { ...@@ -72,6 +23,9 @@ type PageState = {
campusList: CampusList; campusList: CampusList;
filterList: CampusList; filterList: CampusList;
filterName: string; filterName: string;
showToast: boolean;
localText: string;
timer: number | undefined;
}; };
type IProps = PageStateProps & PageDispatchProps; type IProps = PageStateProps & PageDispatchProps;
...@@ -101,10 +55,17 @@ class SelectCampus extends Component { ...@@ -101,10 +55,17 @@ class SelectCampus extends Component {
filterName: '', filterName: '',
campusList: [], campusList: [],
filterList: [], filterList: [],
showToast: false,
localText: '',
timer: undefined,
}; };
} }
componentWillMount() { componentWillMount() {
this.getList();
}
getList() {
fetchAllCampus() fetchAllCampus()
.then(res => { .then(res => {
console.log(res); console.log(res);
...@@ -132,32 +93,9 @@ class SelectCampus extends Component { ...@@ -132,32 +93,9 @@ class SelectCampus extends Component {
}) })
.catch(err => { .catch(err => {
console.log(err); console.log(err);
let campusIndexArr: Array<string> = [];
let campusList: CampusList = [];
resData.map((campus: Campus) => {
let firstPin = campus.firstPin;
if (firstPin) {
let index = campusIndexArr.indexOf(firstPin);
if (index > -1) {
campusList[index].children.push(campus);
} else {
campusIndexArr.push(firstPin);
campusList.push({
firstPin: firstPin,
children: [campus],
});
}
}
});
this.setState({
campusList: campusList,
filterList: campusList,
});
}); });
this.setState(({ campusList }: PageState) => ({
filterList: campusList,
}));
} }
searchList() { searchList() {
let { filterName, campusList } = this.state; let { filterName, campusList } = this.state;
if (filterName) { if (filterName) {
...@@ -185,7 +123,31 @@ class SelectCampus extends Component { ...@@ -185,7 +123,31 @@ class SelectCampus extends Component {
}); });
} }
} }
bindCampus({ id, name, schoolId }: Campus) {
showToastHandle(text: string) {
console.log(text);
const { timer } = this.state;
if (timer) {
clearTimeout(timer);
}
const newTimer = setTimeout(() => {
this.setState({
showToast: false,
localText: '',
});
}, 1000);
this.setState({
showToast: true,
localText: text,
timer: newTimer,
});
}
bindCampus({ target: { dataset } }) {
const {
campus: { id, name, schoolId },
} = dataset;
this.props.updateUserInfo({ this.props.updateUserInfo({
campusId: id, campusId: id,
campusName: name, campusName: name,
...@@ -195,7 +157,13 @@ class SelectCampus extends Component { ...@@ -195,7 +157,13 @@ class SelectCampus extends Component {
} }
render() { render() {
const { filterList, filterName } = this.state; const {
campusList,
filterList,
filterName,
showToast,
localText,
} = this.state;
return ( return (
<View className='Location topBr'> <View className='Location topBr'>
<View className='searchBox'> <View className='searchBox'>
...@@ -215,23 +183,41 @@ class SelectCampus extends Component { ...@@ -215,23 +183,41 @@ class SelectCampus extends Component {
<Text>搜索</Text> <Text>搜索</Text>
</View> </View>
</View> </View>
<View className='locationList'> <View className='infoBar'>
{campusList.map(item => (
<View
key={item.firstPin}
className='infoItem'
onClick={() => this.showToastHandle(item.firstPin)}>
{item.firstPin}
</View>
))}
</View>
<View className={showToast ? 'show br8 infoToast' : 'br8 infoToast'}>
{localText}
</View>
<ScrollView
scroll-y
className='locationList'
scrollIntoView={localText}
scrollWithAnimation>
{filterList.map(campusItem => ( {filterList.map(campusItem => (
<View key={campusItem.firstPin} className='locationArea'> <View key={campusItem.firstPin} className='locationArea'>
<View id={campusItem.firstPin} className='locationTitle'> <View id={campusItem.firstPin} className='locationTitle'>
{campusItem.firstPin} {campusItem.firstPin}
</View> </View>
{campusItem.children.map((campus, index) => ( {campusItem.children.map(campus => (
<View <View
key={index} key={campus.id}
className='locationItem' className='locationItem'
onClick={() => this.bindCampus(campus)}> data-campus={campus}
onClick={this.bindCampus}>
{campus.name} {campus.name}
</View> </View>
))} ))}
</View> </View>
))} ))}
</View> </ScrollView>
</View> </View>
); );
} }
......
import { ComponentClass } from 'react'; import { ComponentClass } from 'react';
import Taro, { Component, Config } from '@tarojs/taro'; import Taro, { Component, Config } from '@tarojs/taro';
import { View, Button } from '@tarojs/components'; import { View } from '@tarojs/components';
import './index.scss'; import './index.scss';
import { login } from '../../api/login'; import { login, LoginReponse } from '../../api/wx';
import { connect } from '@tarojs/redux';
type PageStateProps = { import { updateUserInfo, UserState } from '../../store/rootReducers/userinfo';
counter: {
num: number;
};
};
type PageDispatchProps = {}; type PageDispatchProps = {
updateUserInfo: (e: UserState) => void;
};
type PageOwnProps = {}; type PageOwnProps = {};
type PageState = { type PageState = {};
loadingText: string;
};
type IProps = PageStateProps & PageDispatchProps & PageOwnProps; type IProps = PageDispatchProps & PageOwnProps;
interface Index { interface Index {
props: IProps; props: IProps;
state: PageState; state: PageState;
} }
@connect(
() => ({}),
dispatch => ({
updateUserInfo(entity: UserState) {
dispatch(updateUserInfo(entity));
},
}),
)
class Index extends Component { class Index extends Component {
config: Config = {}; config: Config = {};
constructor(props) { constructor(props: IProps) {
super(props); super(props);
this.state = {
loadingText: 'Loading...',
};
} }
componentWillMount() { componentWillMount() {
Taro.showLoading();
this.checkUser();
}
checkUser() {
Taro.getStorage({ Taro.getStorage({
key: 'token', key: 'token',
}) })
.then(res => { .then(res => {
console.log(res); const data = res.data;
const userInfo = Taro.getStorageSync('userInfo');
console.log('token ' + data);
}) })
.catch(() => { .catch(() => {
this.loginHandle(); this.loginHandle();
...@@ -49,41 +58,43 @@ class Index extends Component { ...@@ -49,41 +58,43 @@ class Index extends Component {
} }
loginHandle() { loginHandle() {
Taro.login().then(res => { const { updateUserInfo } = this.props;
console.log(res); Taro.login()
login({ .then(res => {
code: res.code, console.log(res);
}) login({
.then(res => { code: res.code,
const data = res.data;
}) })
.catch(err => { .then((res: LoginReponse) => {
console.log(err); const { registed, token } = res.data;
this.setState({ if (registed) {
loadingText: '', Taro.setStorage({ key: 'token', data: token });
Taro.setStorage({ key: 'userInfo', data: token });
Taro.redirectTo({
url: '/pages/Home/Home',
});
} else {
updateUserInfo({
token: token,
});
Taro.hideLoading();
Taro.redirectTo({
url: '/pages/Login/Login',
});
}
})
.catch(err => {
console.log(err);
}); });
}); })
// Taro.setStorage({ key: 'token', data: res.code }); .catch(err => {
}); console.log(err);
});
} }
navToLogin() {
this.loginHandle();
// Taro.navigateTo({
// url: '/pages/Register/Register',
// });
}
render() { render() {
const { loadingText } = this.state; return <View className='Index' />;
return (
<View className='Index'>
<View className='Index-loading-text'>{loadingText}</View>
<Button className='dec_btn' onClick={this.navToLogin}>
登录
</Button>
</View>
);
} }
} }
export default Index as ComponentClass<IProps, PageState>; export default Index as ComponentClass<PageOwnProps, PageState>;
import { createStore, applyMiddleware, compose } from 'redux' import { createStore, applyMiddleware, compose } from 'redux';
import thunkMiddleware from 'redux-thunk' import thunkMiddleware from 'redux-thunk';
import rootReducer from './reducers' import rootReducer from './reducers';
const composeEnhancers = const composeEnhancers =
typeof window === 'object' && typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ // Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize... })
}) : compose : compose;
const middlewares = [ const middlewares = [thunkMiddleware];
thunkMiddleware
]
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
middlewares.push(require('redux-logger').createLogger()) middlewares.push(require('redux-logger').createLogger());
} }
const enhancer = composeEnhancers( const enhancer = composeEnhancers(
applyMiddleware(...middlewares), applyMiddleware(...middlewares),
// other store enhancers if any // other store enhancers if any
) );
export default function configStore () { const store = createStore(rootReducer, enhancer);
const store = createStore(rootReducer, enhancer)
return store export default store;
}
import User from '../../types/User/User'; import User from '../../types/User/User';
import Action from '../../types/Store/Actions'; import Action from '../../types/Store/Actions';
export interface StoreState extends User { export interface UserState extends User {
login: boolean; login?: boolean;
token: string; token?: string;
} }
const INITIAL_STATE = { const INITIAL_STATE = {
...@@ -23,9 +23,9 @@ export const updateUserInfo = (entity: User): Action => ({ ...@@ -23,9 +23,9 @@ export const updateUserInfo = (entity: User): Action => ({
}); });
export default function userinfo( export default function userinfo(
state: StoreState = INITIAL_STATE, state: UserState = INITIAL_STATE,
actions: Action, actions: Action,
): StoreState { ): UserState {
switch (actions.type) { switch (actions.type) {
case 'UPDATE_USERINFO': case 'UPDATE_USERINFO':
return { return {
......
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