Authored by 张丽霞

个人信息模块,review by Redding

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