Authored by ZhangTonghai

Merge branch '5.6.0' of http://git.yoho.cn/mobile/YH_RNComponent into 5.6.0

... ... @@ -30,6 +30,7 @@ import RepayRecordListContainer from './containers/RepayRecordListContainer';
import InstallmentAccountContainer from './containers/InstallmentAccountContainer';
import InstallmentMyCardContainer from './containers/InstallmentMyCardContainer';
import InstallmentMyCardDetailContainer from './containers/InstallmentMyCardDetailContainer';
import InstallmentMyCardAddContainer from './containers/InstallmentMyCardAddContainer';
import {
... ... @@ -127,13 +128,19 @@ export default function native(platform) {
} else if (type == 'installMyCard') {
return (
<Provider store={store}>
<InstallmentMyCardDetailContainer />
<InstallmentMyCardContainer />
</Provider>
)
} else if (type == 'installMyCardDetail') {
return (
<Provider store={store}>
<InstallmentMyCardContainer />
<InstallmentMyCardDetailContainer />
</Provider>
)
} else if (type == 'installMyCardAdd') {
return (
<Provider store={store}>
<InstallmentMyCardAddContainer />
</Provider>
)
}
... ...
'use strict';
import React from 'react';
import ReactNative, {
View,
Text,
TextInput,
Image,
StyleSheet,
Dimensions,
PixelRatio,
TouchableOpacity,
Alert,
} from 'react-native';
import Immutable, {Map} from 'immutable';
import Toast from '../../../common/components/Toast';
export default class BankCardAdd extends React.Component {
constructor(props) {
super(props);
this.bankCardNoChange = this.bankCardNoChange.bind(this);
this.phoneChange = this.phoneChange.bind(this);
this.state = {
newCardNo: "",
phone: "",
};
}
bankCardNoChange(event) {
let value = event.nativeEvent.text;
let cardNo = value.replace(/\s/g, '');
let newCardNo = value.replace(/[^\d]/g, '').replace(/(\d{4})(?=\d)/g, '$1 ');
this.setState({newCardNo: newCardNo});
}
phoneChange(event) {
this.setState({phone: event.nativeEvent.text});
}
onPressNext() {
console.log(this.state.toJS());
}
onPressSupportBank() {
let bankList = ['农业银行', '中国银行', '工商银行', '建设银行', '光大银行', '兴业银行', '邮储银行', '民生银行', '中信银行', '广发银行', '平安银行'];
let banks = bankList.join('、');
Alert.alert('支持银行', `${banks}`, [
{text: '我知道了', onPress: () => {this.props.onPressCardNoQuestion && this.props.onPressCardNoQuestion()}}
]);
}
render() {
let bankName = "农业银行";
let cardNo = "4561";
let userName = "**聪";
let mobile = "*****5865";
let isMaster = false;
let cardDesc = isMaster ? "主卡,用于支付验证和还款验证。" : "副卡,仅用于还款验证。";
let cardTip = isMaster ? "如果您更换银行预留手机号,请先新增其他还款银行卡,并将新增银行卡切换为主卡。然后解除绑定此卡,重新绑定即可。"
: "如果您更换银行预留手机号,请先将银行卡解除绑定,再次重新绑定即可。";
return (
<View style={styles.container}>
<View style={styles.cardInfoTop}></View>
<View style={styles.cardInfoFullLine}></View>
<View style={styles.cardInfoContainer}>
<Text style={styles.cardInfoLabel}>持卡人</Text>
<Text style={styles.cardInfoData}>{userName}</Text>
</View>
<View style={styles.cardInfoLine}></View>
<View style={styles.cardInfoContainer}>
<Text style={styles.cardInfoLabel}>银行卡</Text>
<TextInput
autoCapitalize="none"
placeholder={"请输入本人银行卡号"}
value={this.state.newCardNo}
onChange={this.bankCardNoChange}
style={styles.textInput}
maxLength={23}
underlineColorAndroid="transparent"
keyboardType={"numeric"}
onFocus={() => {
this.props.onFocus && this.props.onFocus(refId);
}}
/>
<TouchableOpacity style={styles.touchContainer} onPress={() => {
this.onPressSupportBank && this.onPressSupportBank();}}>
<Image style={styles.questionCardNo} source={require("../../image/question_icon.png")}/>
</TouchableOpacity>
</View>
<View style={styles.cardInfoLine}></View>
<View style={styles.cardInfoContainer}>
<Text style={styles.cardInfoLabel}></Text>
<Image style={styles.cardInfoImg} source={require("../../image/bank/ABC.png")}/>
<Text style={styles.cardInfoData}>{bankName}</Text>
</View>
<View style={styles.cardInfoLine}></View>
<View style={styles.cardInfoContainer}>
<Text style={styles.cardInfoLabel}>手机号</Text>
<TextInput
autoCapitalize="none"
placeholder={"请输入银行预留手机号"}
value={this.state.phone}
onChange={this.phoneChange}
style={styles.textInput}
maxLength={11}
underlineColorAndroid="transparent"
keyboardType={"numeric"}
onFocus={() => {
this.props.onFocus && this.props.onFocus(refId);
}}
/>
</View>
<View style={styles.cardInfoFullLine}></View>
<View style={styles.cardTipContainer}>
<View style={styles.buttonContainer}>
<TouchableOpacity activeOpacity={1} onPress={() => {
console.log(JSON.stringify(this.state));
this.props.onPressAddCard && this.props.onPressAddCard();}}>
<Text style={styles.addButton}>下一步</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
};
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#ffffff",
},
cardInfoTop:{
width: width,
height: 10 * DEVICE_WIDTH_RATIO,
backgroundColor: "#f0f0f0",
},
cardInfoFullLine:{
width: width,
height: 0.5 * DEVICE_WIDTH_RATIO,
backgroundColor: "#b4b4b4",
},
cardInfoContainer:{
width: width,
height: 44 * DEVICE_WIDTH_RATIO,
backgroundColor: "#ffffff",
flexDirection: 'row',
alignItems: 'center',
},
cardInfoLabel:{
width: 100 * DEVICE_WIDTH_RATIO,
paddingLeft: 15 * DEVICE_WIDTH_RATIO,
fontSize: 14 * DEVICE_WIDTH_RATIO,
},
cardInfoData:{
width: 150 * DEVICE_WIDTH_RATIO,
fontSize: 13 * DEVICE_WIDTH_RATIO,
},
textInput: {
width: 180 * DEVICE_WIDTH_RATIO,
height: 20 * DEVICE_WIDTH_RATIO,
fontSize: 12 * DEVICE_WIDTH_RATIO,
padding: 0,
marginTop: 4 * DEVICE_WIDTH_RATIO,
},
touchContainer:{
width: 20* DEVICE_WIDTH_RATIO,
height: 20 * DEVICE_WIDTH_RATIO,
marginTop: 4 * DEVICE_WIDTH_RATIO,
marginLeft: 12 * DEVICE_WIDTH_RATIO,
},
questionCardNo: {
width: 14 * DEVICE_WIDTH_RATIO,
height: 14 * DEVICE_WIDTH_RATIO,
marginTop: 3 * DEVICE_WIDTH_RATIO,
marginLeft: 3 * DEVICE_WIDTH_RATIO,
},
cardInfoImg:{
width: 16 * DEVICE_WIDTH_RATIO,
height: 16 * DEVICE_WIDTH_RATIO,
marginRight: 10 * DEVICE_WIDTH_RATIO,
},
cardInfoLine:{
width: width - 15 * DEVICE_WIDTH_RATIO,
height: 0.5 * DEVICE_WIDTH_RATIO,
marginLeft: 15 * DEVICE_WIDTH_RATIO,
backgroundColor: "#b4b4b4",
},
cardTipContainer:{
flex: 1,
backgroundColor: "#f0f0f0",
},
buttonContainer:{
width: width,
height: 100,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingTop: 20 * DEVICE_WIDTH_RATIO,
},
addButton:{
width: 220 * DEVICE_WIDTH_RATIO,
height: 44 * DEVICE_WIDTH_RATIO,
fontSize:14 * DEVICE_WIDTH_RATIO,
paddingTop:12 * DEVICE_WIDTH_RATIO,
marginLeft: 8 * DEVICE_WIDTH_RATIO,
color: '#ffffff',
textAlign: 'center',
borderColor:'#444444',
borderWidth:2,
borderRadius: 6,
backgroundColor:'#444444',
},
});
... ...
'use strict'
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
Platform,
View,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
Text,
ListView,
TouchableOpacity,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as cardListActions from '../reducers/bankCardList/cardListActions';
import ServerError from '../components/installment/ServerError';
import BankCardAdd from '../components/installment/BankCardAdd';
const actions = [
cardListActions,
];
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 InstallmentMyCardAddContainer extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
// this.props.actions.getBankCards();
}
render() {
return (
<BankCardAdd
style={styles.container}
/>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(InstallmentMyCardAddContainer);
... ...
... ... @@ -20,8 +20,9 @@ import {Record, List, Map} from 'immutable';
import appInitialState from './reducers/app/appInitialState';
import personalInfoInitialState from './reducers/personalInfo/personalInfoInitialState';
import vipLevelInitialState from './reducers/vipLevel/vipLevelInitialState';
import PersonalInfoContainer from './containers/PersonalInfoContainer';
import VIPLevelContainer from './containers/VIPLevelContainer';
import {
setPlatform,
... ... @@ -29,10 +30,15 @@ import {
setServiceHost,
} from './reducers/app/appActions';
import {
setNickname,
} from './reducers/vipLevel/vipLevelActions';
function getInitialState() {
const _initState = {
app: (new appInitialState()),
personalInfo: (new personalInfoInitialState()),
vipLevel: (new vipLevelInitialState()),
};
return _initState;
}
... ... @@ -42,12 +48,21 @@ export default function native(platform) {
let YH_PersonalInfo = React.createClass({
render() {
const store = configureStore(getInitialState());
return (
<Provider store={store}>
<PersonalInfoContainer />
</Provider>
);
if (this.props.type == 'VIPLevel') {
let nickname = this.props.nickname;
store.dispatch(setNickname(nickname));
return(
<Provider store={store}>
<VIPLevelContainer />
</Provider>
);
} else {
return (
<Provider store={store}>
<PersonalInfoContainer />
</Provider>
);
}
}
});
... ...
'use strict'
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
Platform,
View,
Text,
Image,
ListView,
TouchableOpacity,
} from 'react-native';
import {Map} from 'immutable';
import VIPPrivilegeCell from './VIPPrivilegeCell';
import VIPLevelHeader from './VIPLevelHeader';
export default class VIPLevel extends Component {
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
this.renderFooter = this.renderFooter.bind(this);
this.renderHeader = this.renderHeader.bind(this);
this.renderSectionHeader = this.renderSectionHeader.bind(this);
this.renderSeparator = this.renderSeparator.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
});
}
renderFooter() {
let {vipInfo} = this.props;
return(
<View style={styles.footer}>
{vipInfo.get('enjoy_preferential') && vipInfo.get('enjoy_preferential').size ?
<View style={{width: width,height: 15,backgroundColor: '#e5e5e5',}}/>
:null
}
<TouchableOpacity activeOpacity={1.0} onPress={() => {
this.props.onPressAllVIPPrivilegeCell && this.props.onPressAllVIPPrivilegeCell();
}}>
<View style={styles.allPrivilegeCell}>
<Text style={{marginLeft: 15, fontSize: 15}}>
查看全部VIP特权
</Text>
<Image style={{marginRight: 15}}
source={require('../image/cell_indicator.png')}
/>
</View>
</TouchableOpacity>
</View>
);
}
renderHeader() {
let {nickname, vipInfo, vipShowPageInfo} = this.props;
return(
<VIPLevelHeader
nickname={nickname}
vipInfo={vipInfo}
vipShowPageInfo={vipShowPageInfo}
/>
);
}
renderSectionHeader(sectionData, sectionID) {
if (!sectionData.length) {
return null;
}
return(
<View style={styles.sectionHeader}>
<Text style={{lineHeight:38,fontSize:17,color:'#444444',height:58}}>
当前可享受的特权
</Text>
<View style={{width: width,height: 0.5,backgroundColor: '#e5e5e5',}}/>
</View>
);
}
renderRow(rowData,sectionID,rowID) {
return(
<VIPPrivilegeCell
dataSource={rowData}
onPressPrivilegeCell={this.props.onPressPrivilegeCell}
/>
);
}
renderSeparator(sectionID, rowID, adjacentRowHighlighted) {
return(
<View style={{width: width,height: 0.5,backgroundColor: '#e5e5e5',}}/>
);
}
render() {
let {nickname, isFetching, vipInfo} = this.props;
let dataSource = {};
if (vipInfo.get('enjoy_preferential') && vipInfo.get('enjoy_preferential').size) {
dataSource = {'privilegeSection':vipInfo.get('enjoy_preferential').toArray()};
}
return (
<View style={styles.container}>
<ListView
contentContainerStyle={styles.contentContainer}
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)}
renderRow={this.renderRow}
renderFooter={this.renderFooter}
renderHeader={this.renderHeader}
renderSectionHeader={this.renderSectionHeader}
renderSeparator={this.renderSeparator}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ebebeb',
},
allPrivilegeCell: {
height: 44 * DEVICE_WIDTH_RATIO,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: 'white',
},
sectionHeader: {
height: 59,
paddingLeft: 15,
backgroundColor:'white',
},
});
... ...
'use strict'
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
Platform,
View,
Text,
Image,
TouchableOpacity,
} from 'react-native';
import {Map} from 'immutable';
export default class VIPLevelHeader extends Component {
constructor(props) {
super(props);
}
render() {
let {nickname, vipInfo, vipShowPageInfo} = this.props;
vipInfo = vipInfo.toJS();
let vipImageUrl = '';
let VIPLevel = vipInfo.current_vip_level;
switch (VIPLevel) {
case '1':
vipImageUrl = require('../image/mine_vip_1.png');
break;
case '2':
vipImageUrl = require('../image/mine_vip_2.png');
break;
case '3':
vipImageUrl = require('../image/mine_vip_3.png');
break;
default:
vipImageUrl = '';
}
let nextLevelTipMessage = '您已升至最高等级啦!'
if (VIPLevel != '3') {
}
return (
<TouchableOpacity activeOpacity={1.0} onPress={() => {
this.props.onPressPrivilegeCell && this.props.onPressPrivilegeCell(dataSource);
}}>
<View style={[styles.container, {height: 260}]}>
<View style={styles.nickname}>
<Text style={{marginLeft:17, color:'#444444'}}>
{nickname}
</Text>
{vipImageUrl !='' ?
<Image style={{marginLeft:10}}
source={vipImageUrl}
/>:null
}
</View>
{VIPLevel == '3'?
<Text style={{marginLeft:15,marginTop:5,fontSize:12,color:'#b0b0b0'}}>
您已升至最高等级啦!
</Text>
:<Text style={{marginLeft:15,marginTop:5,fontSize:12,color:'#b0b0b0'}}>
还差
<Text style={{marginLeft:15,color:'#444444'}}>
¥{vipShowPageInfo.get('upgradeNeedCost')}
</Text>
就可以升级为{vipInfo.next_vip_title}
</Text>
}
<Text style={{marginLeft:15,marginTop:5,fontSize:12,color:'#b0b0b0'}}>
(VIP金额累计需订单成功签收满15天且无退换货)
</Text>
<Text style={{marginLeft:15,marginTop:5,fontSize:12,color:'#444444'}}>
年度累计金额:
<Text style={{marginLeft:5,fontSize:17,color:'#d0021b'}}>
¥{vipInfo.current_year_cost}
</Text>
</Text>
<View style={styles.nextLevelNeedProcess}>
{VIPLevel == '3'?null:
<View style={styles.nextLevelCost}>
<Text style={{color:'#b0b0b0',fontSize:13,color:'#b0b0b0'}}>
¥0.00{vipInfo.next_need_cost}
</Text>
</View>
}
<View style={styles.nextLevelCompletedProcess}>
</View>
</View>
<View style={styles.curAndNextVIPTitle}>
<Text style={{marginLeft:15,fontSize:12,color:'#444444',fontStyle:'italic'}}>
{vipInfo.current_vip_title}
</Text>
{vipInfo.next_vip_title =='3' ?
<Text style={{marginRight:15,fontSize:12,color:'#444444',fontStyle: 'italic'}}>
{vipInfo.next_vip_title}
</Text>:null
}
</View>
<View style={{width: width,height: 15,backgroundColor: '#e5e5e5',}}/>
<View style={styles.totalCost}>
<Text style={{marginLeft:15,fontSize:17,color:'#444444'}}>
年度累计金额:
</Text>
<Text style={{marginRight:15,fontSize:14,color:'#444444'}}>
¥{vipInfo.current_year_cost}
</Text>
</View>
<View style={{height: 1.0,backgroundColor: '#e5e5e5',marginLeft:15}}/>
<View style={styles.totalCost}>
<Text style={{marginLeft:15,fontSize:17,color:'#444444'}}>
历史消费总金额:
</Text>
<Text style={{marginRight:15,fontSize:14,color:'#444444'}}>
¥{vipInfo.current_total_cost}
</Text>
</View>
<View style={{width: width,height: 15,backgroundColor: '#e5e5e5',}}/>
</View>
</TouchableOpacity>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
nickname: {
flexDirection: 'row',
marginTop: 15,
},
nextLevelNeedProcess: {
position: 'relative',
marginTop: 10,
height: 10,
width: width - 30,
marginLeft: 15,
backgroundColor: '#b0b0b0',
borderRadius: 5,
},
nextLevelCompletedProcess: {
position: 'absolute',
bottom: 0,
left: 0,
height: 10,
width: width - 30,
backgroundColor: '#c40016',
borderRadius: 5,
},
nextLevelCost: {
position: 'absolute',
top: 0,
right: 0,
marginTop: -17,
backgroundColor: 'white',
},
curAndNextVIPTitle: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 5,
marginTop: 5,
},
totalCost: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
height: 44,
}
});
... ...
'use strict'
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
Platform,
View,
Text,
Image,
TouchableOpacity,
} from 'react-native';
import {Map} from 'immutable';
import YH_Image from '../../common/components/YH_Image';
export default class VIPPrivilegeCell extends Component {
constructor(props) {
super(props);
}
render() {
let {dataSource} = this.props;
return (
<TouchableOpacity activeOpacity={1.0} onPress={() => {
this.props.onPressPrivilegeCell && this.props.onPressPrivilegeCell(dataSource);
}}>
<View style={styles.container}>
<YH_Image url={dataSource.get('pic')} style={styles.image} />
<View style={styles.descriptionContainer}>
<Text style={styles.title}>
{dataSource.get('title')}
</Text>
<Text style={styles.description}>
{dataSource.get('description')}
</Text>
</View>
</View>
</TouchableOpacity>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
flexDirection: 'row',
height: 69,
},
image: {
marginLeft: 15,
width: 35,
height: 35,
marginTop: 17,
},
descriptionContainer: {
height: 69,
width: width - 80,
justifyContent: 'center',
},
title: {
textAlign: 'left',
fontSize: 12,
marginBottom: 8,
},
description: {
textAlign: 'left',
fontSize: 12,
lineHeight: 15,
color: '#b0b0b0',
}
});
... ...
... ... @@ -6,6 +6,10 @@ export default keyMirror({
FETCH_PROFILE_REQUEST: null,
FETCH_PROFILE_SUCCESS: null,
FETCH_PROFILE_FAILURE: null,
UPDATE_PAGE_CELL_LIST: null,
SET_NICKNAME: null,
FETCH_VIP_INFO_REQUEST: null,
FETCH_VIP_INFO_SUCCESS: null,
FETCH_VIP_INFO_FAILURE: null,
});
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as vipLevelActions from '../reducers/vipLevel/vipLevelActions';
import VIPLevel from '../components/VIPLevel';
const actions = [
vipLevelActions,
];
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 VIPLevelContainer extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
this.props.actions.fetchVIPInfo();
}
render() {
let {vipLevel} = this.props;
let {nickname, isFetching, vipInfo, vipShowPageInfo} = vipLevel;
return (
<View style={styles.container}>
<VIPLevel
nickname={nickname}
isFetching={isFetching}
vipInfo={vipInfo}
vipShowPageInfo={vipShowPageInfo}
/>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(VIPLevelContainer);
... ...
import {combineReducers} from 'redux';
import app from './app/appReducer';
import personalInfo from './personalInfo/personalInfoReducer';
import vipLevel from './vipLevel/vipLevelReducer';
const rootReducer = combineReducers({
app,
personalInfo,
vipLevel,
});
export default rootReducer;
... ...
'use strict';
import ReactNative from 'react-native';
import {Platform} from 'react-native';
import VIPLevelService from '../../services/VIPLevelService';
import {Record, List, Map} from 'immutable';
const {
SET_NICKNAME,
FETCH_VIP_INFO_REQUEST,
FETCH_VIP_INFO_SUCCESS,
FETCH_VIP_INFO_FAILURE,
} = require('../../constants/actionTypes').default;
export function fetchVIPInfoRequest() {
return{
type: FETCH_VIP_INFO_REQUEST,
}
}
export function fetchVIPInfoSuccess(object) {
return{
type: FETCH_VIP_INFO_SUCCESS,
payload: object,
}
}
export function fetchVIPInfoFailure(error) {
return{
type: FETCH_VIP_INFO_FAILURE,
payload: error,
}
}
export function setNickname(nickname) {
return{
type: SET_NICKNAME,
payload: nickname,
}
}
export function fetchVIPInfo() {
return(dispatch, getState) => {
let {app, vipLevel} = getState();
let fetchVIP = (uid) => {
dispatch(fetchVIPInfoRequest());
return new VIPLevelService(app.host).getVIPInfo(uid)
.then(json => {
let vipShowPageInfo = processVIPInfo(json);
dispatch(fetchVIPInfoSuccess({
vipInfo: json,
upgradeNeedCost: vipShowPageInfo.upgradeNeedCost,
vipNextLevelProgress: vipShowPageInfo.vipNextLevelProgress,
}));
})
.catch(error => {
dispatch(fetchVIPInfoFailure(error));
});
}
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
fetchVIP(uid);
})
.catch(error => {
fetchVIP(0);
});
}
}
function processVIPInfo(json) {
let upgradeNeedCost = 0.0;
let nextNeedCost = 0.0;
if (!json.upgrade_need_cost || json.upgrade_need_cost =='') {
upgradeNeedCost = 0.0;
} else {
upgradeNeedCost = parseFloat(json.upgrade_need_cost);
}
if (!json.next_need_cost || json.next_need_cost =='') {
nextNeedCost = 0.0;
} else {
nextNeedCost = parseFloat(json.next_need_cost);
}
let currentLevelCost = 0.0;
if (nextNeedCost - upgradeNeedCost >= 0) {
currentLevelCost = nextNeedCost - upgradeNeedCost;
}
let vipNextLevelProgress = 1.0;
if (nextNeedCost == 0.0) {
vipNextLevelProgress = 1.0;
}else{
vipNextLevelProgress = currentLevelCost/nextNeedCost;
}
return({upgradeNeedCost,vipNextLevelProgress})
}
... ...
'use strict';
import Immutable,{Record, List, Map} from 'immutable';
let InitialState = Record({
nickname: '',
isFetching: false,
vipInfo: Map(),
vipShowPageInfo: new(Record({
upgradeNeedCost: 0.0,
vipNextLevelProgress: 0.0,
}))
});
export default InitialState;
... ...
'use strict';
import InitialState from './vipLevelInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_NICKNAME,
FETCH_VIP_INFO_REQUEST,
FETCH_VIP_INFO_SUCCESS,
FETCH_VIP_INFO_FAILURE,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function brandReducer(state=initialState, action) {
switch(action.type) {
case FETCH_VIP_INFO_REQUEST:
return state.set('isFetching', true);
case FETCH_VIP_INFO_FAILURE:
return state.set('isFetching', false);
case FETCH_VIP_INFO_SUCCESS:
return state.set('isFetching', false)
.set('vipInfo', Immutable.fromJS(action.payload.vipInfo))
.setIn(['vipShowPageInfo', 'upgradeNeedCost'], action.payload.upgradeNeedCost)
.setIn(['vipShowPageInfo', 'vipNextLevelProgress'], action.payload.vipNextLevelProgress);
case SET_NICKNAME:
return state.set('nickname', action.payload);
}
return state;
}
... ...
'use strict';
import Request from '../../common/services/NativeRequest';
export default class MineGuangService {
constructor (host) {
let baseURL = 'http://api.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request(baseURL);
}
async getVIPInfo(uid) {
return await this.api.get({
url: '',
body: {
method: 'app.passport.vip',
uid,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...