Authored by 张丽霞

个人信息模块,review by Redding

... ... @@ -16,6 +16,7 @@ import Mine from './mine/Mine';
import ProductList from './productList/ProductList';
import MyAssets from './myAssets/MyAssets';
import MineGuang from './mineGuang/MineGuang';
import PersonalInfo from './personalInfo/PersonalInfo';
// import Search from './search/Search';
import RedPersonBrand from './redPersonBrand/RedPersonBrand';
... ... @@ -52,6 +53,7 @@ export default function native(platform) {
MyAssets(platform);
MineGuang(platform);
Installment(platform);
PersonalInfo(platform);
if (Platform.OS === 'ios') {
Community(platform);
... ...
'use strict';
import React from 'react';
import ReactNative, {
AppRegistry,
Platform,
StyleSheet,
Dimensions,
TouchableOpacity,
View,
} from 'react-native';
import {
Provider,
connect
} from 'react-redux';
import configureStore from './store/configureStore';
import {Record, List, Map} from 'immutable';
import appInitialState from './reducers/app/appInitialState';
import personalInfoInitialState from './reducers/personalInfo/personalInfoInitialState';
import PersonalInfoContainer from './containers/PersonalInfoContainer';
import {
setPlatform,
setHost,
setServiceHost,
} from './reducers/app/appActions';
function getInitialState() {
const _initState = {
app: (new appInitialState()),
personalInfo: (new personalInfoInitialState()),
};
return _initState;
}
export default function native(platform) {
let YH_PersonalInfo = React.createClass({
render() {
const store = configureStore(getInitialState());
return (
<Provider store={store}>
<PersonalInfoContainer />
</Provider>
);
}
});
AppRegistry.registerComponent('YH_PersonalInfo', () => YH_PersonalInfo);
}
let styles = StyleSheet.create({
});
... ...
'use strict'
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
Platform,
View,
Text,
Image,
} from 'react-native';
import {Map} from 'immutable';
export default class PersonalInfo extends Component {
constructor(props) {
super(props);
}
render() {
let {dataSource} = this.props;
let cellHeight = 44;
if (dataSource.get('id') == 'portrait') {
cellHeight = 60;
}
let withoutBottomLine = dataSource.get('withoutBottomLine');
let imageUrl = '';
if (dataSource.get('id') == 'portrait') {
imageUrl = require('../image/avatar_icon.png');
} else if (dataSource.get('id') == 'VIPLevel') {
imageUrl = require('../image/VIP1.png');
} else if (dataSource.get('id') == 'mineQRCode') {
imageUrl = require('../image/mine_qr.png');
}
return (
<View style={[styles.container,{height: cellHeight + (withoutBottomLine?0.0:0.5)}]}>
<View style={[styles.contentContainer,{height: cellHeight}]}>
<Text style={styles.title}>
{dataSource.get('title')}
</Text>
<View style={styles.contentContainer}>
<Text style={styles.content}>
{dataSource.get('content')}
</Text>
{imageUrl==''?null:
<Image style={styles.arrow}
source={imageUrl}
/>}
<Image style={styles.arrow}
source={require('../image/cell_indicator.png')}
/>
</View>
</View>
{withoutBottomLine ? null:
<View style={{width: width,height: 0.5,backgroundColor: '#e5e5e5',}}/>
}
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
title: {
marginLeft: 15,
},
content:{
color: '#b0b0b0',
marginRight: 14,
fontSize: 12,
},
contentContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
arrow: {
marginRight: 15,
}
});
... ...
'use strict'
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
Platform,
View,
Text,
Image,
ListView,
TouchableOpacity,
} from 'react-native';
import {Map} from 'immutable';
import InfoCell from './InfoCell';
export default class PersonalInfo extends Component {
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
});
}
renderRow(rowData,sectionID,rowID) {
if (rowData.get('id') == 'separate') {
return(
<View style={{width: width,height: 18,backgroundColor: '#e5e5e5',}}/>
);
}
return(
<InfoCell
dataSource={rowData}
/>
);
}
render() {
let {dataSource} = this.props;
let dataList = [0,1,2];
return (
<View style={styles.container}>
<ListView
contentContainerStyle={styles.contentContainer}
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(dataSource.toArray())}
renderRow={this.renderRow}
renderFooter={()=>{
return(
<View style={styles.footer}>
<Image style={styles.bottomImage}
source={require('../image/yoho_icon.png')}
/>
<Text style={{color:'#b0b0b0',fontSize: 11}}>
如果你还使用了我们的其他产品(Yoho!Nowmars)修改个人信息时将同步。
</Text>
</View>
)
}}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#efefef',
},
footer:{
height: 112 * DEVICE_WIDTH_RATIO,
backgroundColor: '#efefef',
alignItems: 'center',
},
bottomImage: {
width: 70,
height: 40,
marginTop: 12,
marginBottom: 12,
}
});
... ...
import keyMirror from 'key-mirror';
export default keyMirror({
SET_TYPE: 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 personalInfoActions from '../reducers/personalInfo/personalInfoActions';
import PersonalInfo from '../components/PersonalInfo';
const actions = [
personalInfoActions,
];
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 PersonalInfoContainer extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
}
render() {
let {personalInfo} = this.props;
let {pageCellList} = personalInfo;
return (
<View style={styles.container}>
<PersonalInfo
dataSource={pageCellList}
/>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(PersonalInfoContainer);
... ...
'use strict';
import ReactNative from 'react-native';
const {
SET_PLATFORM,
SET_CHANNEL,
SET_HOST,
SET_SERVICE_HOST,
SET_AB_VERSION,
} = require('../../constants/actionTypes').default;
export function setPlatform(platform) {
return {
type: SET_PLATFORM,
payload: platform
};
}
export function setChannel(channel) {
return {
type: SET_CHANNEL,
payload: channel
};
}
export function setHost(host) {
return {
type: SET_HOST,
payload: host
};
}
export function setServiceHost(host) {
return {
type: SET_SERVICE_HOST,
payload: host
};
}
export function setABVersion(version) {
return {
type: SET_AB_VERSION,
payload: version
};
}
... ...
'use strict';
import {Record, List, Map} from 'immutable';
let InitialState = Record({
platform: 'ios', // ios, android
channel: 1, // 1 - boy, 2 - girl, 3 - kid, 4 - lifestyle, 5 - yoho
host: 'http://api.yoho.cn',
serviceHost: 'http://service.yoho.cn',
abversion: 'A', //A,B
});
export default InitialState;
... ...
'use strict';
import InitialState from './appInitialState';
const {
SET_PLATFORM,
SET_CHANNEL,
SET_HOST,
SET_SERVICE_HOST,
SET_AB_VERSION,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function appReducer(state = initialState, action) {
if (!(state instanceof InitialState)) return initialState.merge(state);
switch (action.type) {
case SET_PLATFORM:
return state.set('platform', action.payload);
case SET_CHANNEL:
return state.set('channel', action.payload);
case SET_HOST:
return state.set('host', action.payload);
case SET_SERVICE_HOST:
return state.set('serviceHost', action.payload);
case SET_AB_VERSION:
return state.set('abversion', action.payload);
}
return state;
}
... ...
import {combineReducers} from 'redux';
import app from './app/appReducer';
import personalInfo from './personalInfo/personalInfoReducer';
const rootReducer = combineReducers({
app,
personalInfo,
});
export default rootReducer;
... ...
'use strict';
import ReactNative from 'react-native';
import {Platform} from 'react-native';
import PersonalInfoService from '../../services/PersonalInfoService';
import {Record, List, Map} from 'immutable';
const {
SET_TYPE,
} = require('../../constants/actionTypes').default;
... ...
'use strict';
import Immutable,{Record, List, Map} from 'immutable';
let personalInfoCelllist = [
{
id: 'portrait',
title: '头像',
url: '',
},{
id: 'nickname',
title: '昵称',
content: 'berry',
},{
id: 'gender',
title: '性别',
content: 'formale',
},{
id: 'birthDay',
title: '生日',
content: '6月12日',
},{
id: 'VIPLevel',
title: '会员等级',
content: '',
},{
id: 'mineQRCode',
title: '我的二维码',
content: '',
withoutBottomLine: true,
},{
id: 'separate',
},{
id: 'height',
title: '身高',
content: '',
},{
id: 'weight',
title: '体重',
content: '',
withoutBottomLine: true,
},{
id: 'separate',
},{
id: 'addressManage',
title: '地址管理',
content: '',
},{
id: 'accountBind',
title: '账号绑定',
content: '',
withoutBottomLine: true,
}
]
let InitialState = Record({
pageCellList: Immutable.fromJS(personalInfoCelllist),
});
export default InitialState;
... ...
'use strict';
import InitialState from './personalInfoInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_TYPE,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function brandReducer(state=initialState, action) {
// switch(action.type) {
// return state;
// }
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 getUserFavArticleList(params) {
return await this.api.get({
url: '/guang/api/v1/favorite/getUserFavArticleList',
body: {
...params,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async getSimpleArticleList(params) {
return await this.api.get({
url: '/guang/api/v2/article/getSimpleArticleList',
body: {
...params,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async cancelFavorite(params) {
return await this.api.get({
url: '/guang/api/v1/favorite/cancelFavorite',
body: {
...params,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...
/**
* # configureStore.js
*
* A Redux boilerplate setup
*
*/
'use strict';
/**
* ## Imports
*
* redux functions
*/
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
/**
* ## Reducer
* The reducer contains the 4 reducers from
* device, global, auth, profile
*/
import reducer from '../reducers';
const logger = createLogger({
predicate: (getState, action) => process.env.NODE_ENV === `development`
});
/**
* ## creatStoreWithMiddleware
* Like the name...
*/
const createStoreWithMiddleware = applyMiddleware(
thunk,
logger
)(createStore);
/**
* ## configureStore
* @param {Object} the state with for keys:
* device, global, auth, profile
*
*/
export default function configureStore(initialState) {
return createStoreWithMiddleware(reducer, initialState);
};
... ...