Authored by lixia.zhang

用户注销、条款、原因页面,review by 孙凯

... ... @@ -23,7 +23,10 @@ import {Record, List, Map} from 'immutable';
import appInitialState from './reducers/app/appInitialState';
import userLogoutInitialState from './reducers/userLogout/userLogoutInitialState';
import userLogoutReasonInitialState from './reducers/userLogoutReason/userLogoutReasonInitialState';
import UserLogoutContainer from './containers/UserLogoutContainer';
import UserLogoutClause from './containers/LogoutClauseContainer';
import UserLogoutReasonContainer from './containers/UserLogoutReasonContainer';
import {setPlatform, setHost, setChannel, setServiceHost} from './reducers/app/appActions';
... ... @@ -31,6 +34,7 @@ function getInitialState() {
const _initState = {
app: (new appInitialState()),
userLogout: (new userLogoutInitialState()),
userLogoutReason :(new userLogoutReasonInitialState()),
};
return _initState;
}
... ... @@ -40,17 +44,33 @@ export default function native(platform) {
let YH_UserLogout = React.createClass({
render() {
let type = this.props.type;
const store = configureStore(getInitialState());
store.dispatch(setPlatform(platform));
store.dispatch(setHost(this.props.host));
store.dispatch(setChannel(this.props.channelId));
store.dispatch(setServiceHost(this.props.serviceHost));
if (type == 'userLogoutClause') {
return (
<Provider store={store}>
<UserLogoutClause />
</Provider>
);
} else if (type == 'userLogouReason') {
return (
<Provider store={store}>
<UserLogoutReasonContainer />
</Provider>
);
} else {
return (
<Provider store={store}>
<UserLogoutContainer />
</Provider>
);
}
}
});
AppRegistry.registerComponent('YH_UserLogout', () => YH_UserLogout);
... ...
/**
* sub app userLogout
* @author: lixia.zhang
* @date: 2018/04/13
*/
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
StyleSheet,
Image,
Text,
TouchableOpacity
} from 'react-native';
export default class LogoutClause extends Component {
constructor(props) {
super(props);
this.state = {readedClause: false}
}
render() {
return (
<View style={styles.container}>
<View style={styles.titleContainer}>
<Text style={styles.title}>《有货账户注销条款》</Text>
</View>
<View style={styles.contentContainer}>
<Text style={styles.content}>
在您注销您的YOHO!BUY账户之前,请您充分阅读、理解并同意下列事项,当您按照注销页面提示填写信息、阅读并同意本《注销须知》及相关条款与条件且完成全部注销程序后,即表示您已充分阅读、理解并接受本《注销须知》的全部内容。阅读本《注销须知》的过程中,如果您不同意相关任何条款和条件约定,请您立即停止账户注销程序。
</Text>
<Text style={styles.content}>
我们在此善意的提醒您,您注销帐号的行为会给您的售后维权带来诸多的不便,且注销YOHO!BUY账户后,您的个人信息我们只会在有货商城的前台系统中去除,使其保持不可被检索、访问的状态,或对其进行匿名化处理。您知晓并理解,根据相关法律规定相关交易记录须在有货后台保存2年甚至更长时间。
</Text>
<Text style={styles.content}>
1.您所申请注销等YOHO!BUY账户应该是您依照用户服务协议注册并由本公司提供给您本人的账户。您应当按照本公司规定的程序或网站上的提示进行YOHO!BUY账户注销。
</Text>
<Text style={styles.content}>
2.如您需要注销账户,您的账户需同时满足以下条件:
</Text>
<Text style={styles.content}>
1)您申请注销的YOHO!BUY账户应当处于正常状态,即您的YOHO!BUY的账户信息和用户信息是最新、完整、正确且无任何账户被限制的纪录。
</Text>
<Text style={styles.content}>
2)在最近一个月内,账户没有进行更改密码、更改绑定信息等敏感操作,账户没有被盗、被封等风险。
</Text>
<Text style={styles.content}>
3)账户在有货商城系统中无欠款;
</Text>
</View>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0'
},
title: {
fontSize: 14,
color: '#444444'
},
titleContainer: {
alignItems:'center',
marginTop: 19,
marginBottom:15
},
contentContainer: {
},
content: {
color: '#444444',
fontSize: 14,
lineHeight: 24
}
});
... ...
... ... @@ -9,7 +9,11 @@
import React, {Component} from 'react';
import ReactNative, {
View,
StyleSheet
StyleSheet,
Image,
Text,
TouchableOpacity,
Modal
} from 'react-native';
... ... @@ -17,12 +21,95 @@ export default class UserLogout extends Component {
constructor(props) {
super(props);
this.state = {readedClause: false}
}
render() {
return (
<View style={styles.container}>
<View style = {styles.topLogoContainer}>
<Image
style={styles.icon}
source={require('../../images/icon.png')}
/>
<Text style={styles.logoutText}>申请注销有货账号</Text>
</View>
<View style={styles.textContainer}>
<Text style={[styles.text,styles.textTitle]}>注销您的有货账户后您将:</Text>
<Text style={styles.text}>1.账户信息、会员权益将被清除,且无法恢复。</Text>
<Text style={styles.text}>2.账户内有货币、优惠券、礼品卡等将被清除且无法恢复。</Text>
<Text style={styles.text}>3.交易记录将被清除。</Text>
<Text style={styles.text}>4.无法使用该账户登录授权或绑定关系的app和网站。</Text>
</View>
<View style={styles.clauseContainer}>
<TouchableOpacity
activeOpacity={1.0}
style={{flexDirection: 'row'}}
onPress={() => {
this.setState(previousState => {
return { readedClause: !previousState.readedClause };
});
}}>
<Image
style={styles.check}
source={this.state.readedClause == false ? require('../../images/weixuan.png'): require('../../images/xuanze.png')}
/>
<Text>我已阅读并同意以下协议</Text>
</TouchableOpacity>
<TouchableOpacity
activeOpacity={1.0}
onPress={() => {
this.props.onPressLogoutClause && this.props.onPressLogoutClause();
}}>
<Text style={{color:'red'}}>《有货注销条款》</Text>
</TouchableOpacity>
</View>
<View style={[styles.confirmBtn,{backgroundColor:this.state.readedClause?'#444444':'#b0b0b0'}]}>
<TouchableOpacity
onPress={() => {
if(this.state.readedClause) {
this.props.updateLogoutModalState && this.props.updateLogoutModalState(true);
}
}}>
<Text style={styles.confirmText}>注销帐号</Text>
</TouchableOpacity>
</View>
<Modal
animationType={"fade"}
transparent={true}
visible={this.props.showConfirmLogoutModal}
>
<View style={styles.modalContainer}>
<View style={styles.modalView}>
<View style={styles.confirmTitleContainer}>
<View style={{marginTop:40,marginBottom:29}}>
<Text style={styles.confirmTitle}>确认注销帐号吗?</Text>
<Text style={styles.confirmTitle}>注销帐号将无法恢复!</Text>
</View>
</View>
<View style={{width:'100%',height:0.5,backgroundColor:'#e0e0e0'}}/>
<View style={styles.confirmBtnContainer}>
<TouchableOpacity
style={{width:'49%',alignItems:'center',height:45.5}}
onPress={() => {
this.props.updateLogoutModalState && this.props.updateLogoutModalState(false);
}}>
<Text style={{lineHeight:44,fontSize:17,color:'#444444',letterSpacing:-0.41}}>放弃</Text>
</TouchableOpacity>
<View style={{width:0.5,height:45,backgroundColor:'#e0e0e0'}}/>
<TouchableOpacity
style={{width:'49%',alignItems:'center',height:45.5}}
onPress={() => {
this.props.confirmLogoutAction && this.props.confirmLogoutAction();
}}>
<Text style={{lineHeight:44,fontSize:17,color:'#d0021b',letterSpacing:-0.41}}>确定</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
</View>
);
}
... ... @@ -31,6 +118,92 @@ export default class UserLogout extends Component {
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0',
},
topLogoContainer:{
height: 138,
alignItems: 'center',
},
icon: {
width: 54,
height: 54,
marginTop: 20,
marginBottom: 14,
},
logoutText: {
fontSize: 17,
color: '#444444'
},
textContainer:{
backgroundColor: 'white',
paddingTop: 9,
paddingBottom: 9,
},
textTitle: {
fontWeight: 'bold',
},
text: {
fontSize: 15,
color: '#444444',
marginTop: 11,
marginBottom:11,
marginLeft:16,
marginRight:18
},
clauseContainer: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: 12,
marginBottom: 21
},
check: {
width: 14,
height: 14,
marginRight: 5.5,
},
confirmBtn: {
marginLeft: 15,
marginRight: 15,
height: 44,
borderRadius: 5,
alignItems: 'center',
},
confirmText: {
textAlign: 'center',
lineHeight: 43,
color: 'white',
fontSize: 16
},
modalContainer: {
flex: 1,
justifyContent: 'center',
backgroundColor:'rgba(0, 0, 0, 0.4)',
marginTop: 64
},
modalView: {
marginTop: -64,
borderRadius: 10,
alignItems: 'center',
backgroundColor:'#ffffff',
marginLeft: 53,
marginRight:53,
},
confirmBtnContainer: {
width: '100%',
height: 45.5,
flexDirection: 'row',
justifyContent: 'space-between',
},
confirmTitleContainer: {
height:118,
alignItems:'center'
},
confirmTitle: {
color: '#444444',
fontSize: 14,
lineHeight: 24.5,
textAlign: 'center',
letterSpacing: -0.09,
}
});
... ...
/**
* sub app userLogout
* @author: lixia.zhang
* @date: 2018/04/13
*/
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
StyleSheet,
Image,
Text,
TouchableOpacity,
TextInput,
Modal
} from 'react-native';
export default class UserLogoutReason extends Component {
constructor(props) {
super(props);
this.state = {text: ''}
}
render() {
return (
<View style={styles.container}>
<Text style={styles.tip}>
请填写注销原因
</Text>
<View style={styles.textInputContainer}>
<TextInput
style={styles.inputText}
multiline={true}
placeholder="原因..."
placeholderTextColor='#b0b0b0'
onChangeText={(text) => {
this.setState({text});
this.props.enableSubmitBtn && this.props.enableSubmitBtn(text == "" ? false : true)
}}/>
</View>
<View style={[styles.submitBtn,{backgroundColor:this.props.submitBtnEnable?'#444444':'#b0b0b0'}]}>
<TouchableOpacity
onPress={() => {
this.props.showLogoutReasonModalAction && this.props.showLogoutReasonModalAction(true)
}}>
<Text style={styles.submitText}>提交</Text>
</TouchableOpacity>
</View>
<Modal
animationType={"fade"}
transparent={true}
visible={this.props.showModalFlag}
>
<View style={styles.modalContainer}>
<View style={styles.modalView}>
<View style={{marginTop:15,marginBottom:15}}>
<Text style={styles.modalTitle}>请输入短信验证码</Text>
</View>
<View style={styles.modalTextInputContainer}>
<TextInput
style={styles.modalTextInput}
placeholder="请输入手机号"
placeholderTextColor='#b0b0b0'
keyboardType="numeric"
maxLength={11}
onChangeText={(text) => {
}}/>
</View>
<View style={[styles.modalTextInputContainer,{flexDirection:'row', marginTop: 15}]}>
<TextInput
style={[styles.modalTextInput,{width:151}]}
placeholder="请输入手机验证码"
placeholderTextColor='#b0b0b0'
keyboardType="numeric"
maxLength={11}
onChangeText={(text) => {
}}/>
<TouchableOpacity style={{width:70,height:35,marginRight:5}}>
<Text style={{lineHeight:30,textAlign:'right',fontSize:14,color:'#444444',letterSpacing:-0.34}}>获取</Text>
</TouchableOpacity>
</View>
<View style={{flexDirection:'row',alignItems:'center', justifyContent:'space-between',marginTop:2,width:240}}>
<Text style={{fontSize:12,color:'#b0b0b0',lineHeight:42,textAlign:'left'}}>请将下列图片点击翻转至正确方向</Text>
<TouchableOpacity style={{width:40,height:42}}>
<Text style={{textAlign:'right',fontSize:12,color:'#d0021b',letterSpacing:-0.34,lineHeight:42}}>换一批</Text>
</TouchableOpacity>
</View>
<TouchableOpacity
style={{width:'49%',alignItems:'center',height:45.5}}
onPress={() => {
this.props.showLogoutReasonModalAction && this.props.showLogoutReasonModalAction(false);
}}>
<Text style={{lineHeight:44,fontSize:17,color:'#d0021b',letterSpacing:-0.41,fontFamily:'PingFang-SC-Medium'}}>确定</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f0f0'
},
tip: {
marginTop: 10,
marginBottom: 10,
marginLeft: 7.5,
fontSize: 14,
color: '#444444',
letterSpacing: -0.34,
},
inputText: {
height: 150,
backgroundColor: 'white',
fontSize: 15,
letterSpacing: -0.36,
padding: 10,
color: '#444444',
borderWidth: 0.5,
borderColor: '#e0e0e0'
},
textInputContainer: {
marginLeft: 15,
marginRight: 15,
borderRadius: 10,
alignItems: 'center'
},
submitBtn: {
marginLeft: 15,
marginRight: 15,
marginTop: 30,
height: 44,
borderRadius: 5,
alignItems: 'center',
},
submitText: {
textAlign: 'center',
lineHeight: 43,
color: 'white',
fontSize: 16
},
modalContainer: {
flex: 1,
justifyContent: 'center',
backgroundColor:'rgba(0, 0, 0, 0.4)',
},
modalView: {
borderRadius: 10,
alignItems: 'center',
backgroundColor:'#ffffff',
marginLeft: 53,
marginRight:52,
height: 270,
},
modalTitle: {
fontSize: 17,
color: '#444444',
lineHeight: 23,
letterSpacing: -0.1,
fontFamily: 'PingFang-SC-Medium'
},
modalTextInputContainer: {
width: 240,
height: 35,
borderWidth: 0.5,
borderColor: '#e0e0e0',
},
modalTextInput: {
fontSize: 13,
width: 240,
height: 35,
marginLeft:3,
}
});
... ...
... ... @@ -11,4 +11,9 @@ export default keyMirror({
SET_CHANNEL: null,
SET_HOST: null,
SET_SERVICE_HOST: null,
UPDATE_LOGOUT_MODAL_STATE: null,
ENABLE_SUBMIT_BTN: null,
SHOW_LOGOUT_REASON_MODAL: null
});
... ...
/**
* sub app userLogout
* @author: lixia.zhang
* @date: 2018/04/13
*/
'use strict'
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as userLogoutActions from '../reducers/userLogout/userLogoutActions';
import LogoutClause from '../components/userLogout/LogoutClause';
const actions = [
userLogoutActions,
];
function mapStateToProps(state) {
return {
...state
};
}
function mapDispatchToProps(dispatch) {
const creators = Map()
.merge(...actions)
.filter(value => typeof value === 'function')
.toObject();
return {
actions: bindActionCreators(creators, dispatch),
dispatch
};
}
class LogoutClauseContainer extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
}
componentWillUnmount() {
}
render() {
return (
<LogoutClause
/>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LogoutClauseContainer);
... ...
... ... @@ -9,7 +9,7 @@
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
Dimensions
} from 'react-native'
import {bindActionCreators} from 'redux';
... ... @@ -44,6 +44,9 @@ function mapDispatchToProps(dispatch) {
class UserLogoutContainer extends Component {
constructor(props) {
super(props);
this._onPressLogoutClause = this._onPressLogoutClause.bind(this);
this._confirmLogoutAction = this._confirmLogoutAction.bind(this);
this._updateLogoutModalState = this._updateLogoutModalState.bind(this);
}
componentDidMount() {
... ... @@ -54,9 +57,26 @@ class UserLogoutContainer extends Component {
}
_onPressLogoutClause() {
this.props.actions.onPressLogoutClause();
}
_confirmLogoutAction() {
this.props.actions.confirmLogoutAction();
}
_updateLogoutModalState(flag) {
this.props.actions.updateLogoutModalState(flag);
}
render() {
let {showConfirmLogoutModal} = this.props.userLogout;
return (
<UserLogout
showConfirmLogoutModal = {showConfirmLogoutModal}
onPressLogoutClause = {this._onPressLogoutClause}
confirmLogoutAction = {this._confirmLogoutAction}
updateLogoutModalState = {this._updateLogoutModalState}
/>
);
}
... ...
/**
* sub app userLogout
* @author: lixia.zhang
* @date: 2018/04/17
*/
'use strict'
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as userLogoutReasonActions from '../reducers/userLogoutReason/userLogoutReasonActions';
import UserLogoutReason from '../components/userLogout/UserLogoutReason';
const actions = [
userLogoutReasonActions,
];
function mapStateToProps(state) {
return {
...state
};
}
function mapDispatchToProps(dispatch) {
const creators = Map()
.merge(...actions)
.filter(value => typeof value === 'function')
.toObject();
return {
actions: bindActionCreators(creators, dispatch),
dispatch
};
}
class UserLogoutReasonContainer extends Component {
constructor(props) {
super(props);
this._enableSubmitBtn = this._enableSubmitBtn.bind(this);
this._showLogoutReasonModalAction = this._showLogoutReasonModalAction.bind(this);
}
componentDidMount() {
}
componentWillUnmount() {
}
_enableSubmitBtn(state) {
this.props.actions.enableSubmitBtn(state)
}
_showLogoutReasonModalAction(state) {
this.props.actions.showLogoutReasonModal(state)
}
render() {
let {submitBtnEnable,showModalFlag} = this.props.userLogoutReason;
return (
<UserLogoutReason
enableSubmitBtn={this._enableSubmitBtn}
showLogoutReasonModalAction={this._showLogoutReasonModalAction}
submitBtnEnable={submitBtnEnable}
showModalFlag={showModalFlag}
/>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(UserLogoutReasonContainer);
... ...
... ... @@ -7,11 +7,13 @@
import {combineReducers} from 'redux';
import app from './app/appReducer';
import userLogout from './userLogout/userLogoutReducer';
import userLogoutReason from './userLogoutReason/userLogoutReasonReducer';
const rootReducer = combineReducers({
app,
userLogout
userLogout,
userLogoutReason,
});
export default rootReducer;
... ...
... ... @@ -10,6 +10,27 @@ import ReactNative from 'react-native';
import UserLogoutService from '../../services/UserLogoutService';
const {
CUSTOM_TYPE //replace with u defind type
UPDATE_LOGOUT_MODAL_STATE //replace with u defind type
} = require('../../constants/actionTypes').default;
export function onPressLogoutClause() {
return (dispatch, getState) => {
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.userLogoutClause","params":{"title":"有货账户注销条款","type":"userLogoutClause"}}`;
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
}
export function updateLogoutModalState(flag) {
return{
type:UPDATE_LOGOUT_MODAL_STATE,
payload: flag
}
}
export function confirmLogoutAction() {
return (dispatch, getState) => {
dispatch(updateLogoutModalState(false));
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.userLogoutReason","params":{"title":"注销原因","type":"userLogouReason"}}`;
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
}
\ No newline at end of file
... ...
... ... @@ -9,7 +9,8 @@
import {Record, List, Map} from 'immutable';
let InitialState = Record({
isFetching: false
isFetching: false,
showConfirmLogoutModal: false
});
export default InitialState;
... ...
... ... @@ -10,12 +10,17 @@ import InitialState from './userLogoutInitialState';
import Immutable, {Map} from 'immutable';
const {
CUSTOM_TYPE //replace with u defind type
UPDATE_LOGOUT_MODAL_STATE //replace with u defind type
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function userLogoutReducer(state=initialState, action) {
switch(action.type) {
case UPDATE_LOGOUT_MODAL_STATE:{
return state.set('showConfirmLogoutModal',action.payload ? action.payload : false);
}
}
return state;
}
... ...
/**
* sub app userLogout
* @author: lixia.zhang
* @date: 2018/04/13
*/
'use strict';
import ReactNative from 'react-native';
import UserLogoutService from '../../services/UserLogoutService';
const {
ENABLE_SUBMIT_BTN,
SHOW_LOGOUT_REASON_MODAL
} = require('../../constants/actionTypes').default;
export function enableSubmitBtn(flag) {
return{
type:ENABLE_SUBMIT_BTN,
payload: flag
}
}
export function showLogoutReasonModal(state) {
return{
type:SHOW_LOGOUT_REASON_MODAL,
payload: state
}
}
export function confirmLogoutAction() {
return (dispatch, getState) => {
dispatch(updateLogoutModalState(false));
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.userLogoutReason","params":{"title":"注销原因","type":"userLogouReason"}}`;
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
}
\ No newline at end of file
... ...
/**
* sub app userLogout
* @author: lixia.zhang
* @date: 2018/04/13
*/
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
showModalFlag: false,
submitBtnEnable: false
});
export default InitialState;
... ...
/**
* sub app userLogout
* @author: lixia.zhang
* @date: 2018/04/13
*/
'use strict';
import InitialState from './userLogoutReasonInitialState';
import Immutable, {Map} from 'immutable';
const {
ENABLE_SUBMIT_BTN,
SHOW_LOGOUT_REASON_MODAL
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function userLogoutReasonReducer(state = initialState, action) {
switch(action.type) {
case ENABLE_SUBMIT_BTN:{
return state.set('submitBtnEnable',action.payload);
}
case SHOW_LOGOUT_REASON_MODAL: {
return state.set('showModalFlag',action.payload);
}
}
return state;
}
... ...