Authored by 王海元

cps4 recommend product --review by 朱傲哲

... ... @@ -23,7 +23,7 @@ import TalentRankContainer from './containers/TalentRankContainer';
import ShareDetailContainer from './containers/ShareDetailContainer';
import {setChannel, setHost, setPlatform, setServiceHost} from './reducers/app/appActions';
import {setOrderCode} from './reducers/alliance/allianceActions';
import {setSrc, setJumpUrl, setOrderCode} from './reducers/alliance/allianceActions';
function getInitialState() {
... ... @@ -88,6 +88,8 @@ export default function native(platform) {
</Provider>
);
} else if (type === 'recommendProduct') {
store.dispatch(setSrc(this.props.src));
store.dispatch(setJumpUrl(this.props.jumpUrl));
return (
<Provider store={store}>
<RecommendContainer/>
... ...
... ... @@ -8,6 +8,7 @@ import WithdrawModal from "./WithdrawModal";
import ScrollableTabView from 'react-native-scrollable-tab-view';
import TabStatistics from '../components/TabStatistics';
import Statistics from "./Statistics";
import ReactNative from "react-native";
const tabTitles = ['昨日', '本月', '上月'];
... ... @@ -32,6 +33,7 @@ export default class Data extends Component {
isShowHelp,
isShowSure,
isShowWithdrawal,
statisticsInfo
} = this.props;
let bindStatus = this.props.settlementInfo.settlementInfoData.hasBankCard;
... ... @@ -101,10 +103,11 @@ export default class Data extends Component {
locked={true}
scrollWithoutAnimation={true}
renderTabBar={() => <TabStatistics tabNames={tabTitles}/>}
onChangeTab={(obj) => {this.props.changeTab && this.props.changeTab(obj.i + 1);}}
>
<Statistics/>
<Statistics/>
<Statistics/>
<Statistics statisticsInfo={statisticsInfo}/>
<Statistics statisticsInfo={statisticsInfo}/>
<Statistics statisticsInfo={statisticsInfo}/>
</ScrollableTabView>
</View>
);
... ...
... ... @@ -86,6 +86,7 @@ export default class Home extends Component {
return (
<ImageFour
resource={rowData.get('data')}
jumpWithUrl={this.props.jumpWithUrl}
resourceJumpWithUrl={this.props.resourceJumpWithUrl}
/>
);
... ...
... ... @@ -4,6 +4,7 @@ import React, {Component} from 'react';
import {DeviceEventEmitter, Dimensions, Image, ListView, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import {Immutable} from "immutable";
import SingleImage from './floor/SingleImage';
import YH_Image from '../../common/components/YH_Image';
export default class Mine extends Component {
... ... @@ -33,13 +34,15 @@ export default class Mine extends Component {
let bindStyle = bindStatus ? {color: '#444444'} : {color: '#D0021B'};
let isBind = bindStatus ? '已绑定' : '未绑定';
let bindType = bindStatus ? '2' : '1'; // 2绑定,1未绑定
let ico = this.props.profile.head_ico;
let imageUrl = YH_Image.getSlicedUrl(ico, 50, 50, 2);
let nickname = this.props.profile.nickname;
return (
<View>
<View style={styles.headerBackground}>
<Image style={styles.headIcon} source={require('../images/select_mine.png')}
resizeMode={'contain'}/>
<YH_Image style={styles.headIcon} url={imageUrl} circle={true}/>
<View style={styles.textView}>
<Text style={styles.nicknameText}>有货</Text>
<Text style={styles.nicknameText}>{nickname}</Text>
</View>
</View>
<View style={{height: 10, backgroundColor: '#f0f0f0'}}/>
... ... @@ -104,6 +107,7 @@ let styles = StyleSheet.create({
headIcon: {
width: 50,
height: 50,
marginRight:10,
},
textView: {
flexDirection: 'column',
... ...
... ... @@ -19,28 +19,29 @@ export default class Statistics extends Component {
}
render() {
let {statisticsInfo} = this.props;
return (
<View style={styles.container}>
<View style={styles.statisticsView}>
<View style={{width: width / 2, paddingLeft: 30}}>
<Text style={styles.numberText}>¥99.9</Text>
<Text style={styles.numberText}>¥{statisticsInfo.orderAmountSum}</Text>
<Text style={styles.tipsText}>预估订单收入</Text>
</View>
<View style={styles.spaceView}/>
<View style={{width: width / 2, paddingLeft: 30}}>
<Text style={styles.numberText}>¥9.9</Text>
<Text style={styles.numberText}>¥{statisticsInfo.extraAmountSum}</Text>
<Text style={styles.tipsText}>预估其他收入</Text>
</View>
</View>
<View style={styles.lineView}/>
<View style={styles.statisticsView}>
<View style={{width: width / 2, paddingLeft: 30}}>
<Text style={styles.numberText}>99</Text>
<Text style={styles.numberText}>{statisticsInfo.orderNum}</Text>
<Text style={styles.tipsText}>订单数</Text>
</View>
<View style={styles.spaceView}/>
<View style={{width: width / 2, paddingLeft: 30}}>
<Text style={styles.numberText}>999</Text>
<Text style={styles.numberText}>{statisticsInfo.clickNum}</Text>
<Text style={styles.tipsText}>点击数</Text>
</View>
</View>
... ...
... ... @@ -48,7 +48,11 @@ export default class ImageFour extends React.Component {
yh_exposureData={item.yh_exposureData}
style={{width: sliderWidth, height: sliderHeight}}
onPress={() => {
this.props.resourceJumpWithUrl && this.props.resourceJumpWithUrl(item.url);
if (i === 3) {
this.props.jumpWithUrl && this.props.jumpWithUrl('达人排行', 'talentRank');
} else {
this.props.resourceJumpWithUrl && this.props.resourceJumpWithUrl(item.url);
}
}}
>
<YH_Image
... ...
... ... @@ -74,7 +74,7 @@ export default class CategorySelector extends Component {
}}
>
<View style={[styles.categoryContainer, {marginLeft}]}>
<Text style={[styles.categoryName, {color, fontWeight}]}>{rowData.get('category_name')}</Text>
<Text style={[styles.categoryName, {color, fontWeight}]}>{rowData.get('sort_name')}</Text>
</View>
</TouchableOpacity>
);
... ...
'use strict';
import React, {Component} from 'react';
import {Animated, Dimensions, Easing, Image, Platform, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import {Dimensions, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import YH_Image from '../../../common/components/YH_Image';
import DeleteLineText from '../../../common/components/DeleteLineText';
export default class ProductCell extends Component {
constructor(props) {
super(props);
this.renderBottomView = this.renderBottomView.bind(this);
}
renderBottomView() {
let data = this.props.data;
let showSoldOut = data.get('storage', 0) == 0;
if (showSoldOut) {
return (
<View style={[styles.bottomView, styles.soldOutContainer]}>
<Text style={styles.soldOut}>最高返</Text>
<Text style={[styles.soldOut, {marginLeft: 4, fontSize: 16}]}>¥100</Text>
</View>
);
}
let showOffShelf = data.get('status', 0) == 0 ? true : false;
let showReduce = data.get('price_down', 0) == 0 ? false : true;
if (true) {
let reduceStr = '¥' + (parseFloat(data.get('price_down'))).toFixed(2);
return (
<View style={[styles.bottomView, styles.reduceContainer]}>
<Text style={styles.reduceText} numberOfLines={1}>
{'已降'} <Text style={{color: '#d0021b'}}>{'¥100'}</Text>
</Text>
</View>
);
}
return null;
}
render() {
let data = this.props.data;
let prdImage = YH_Image.getSlicedUrl(data.get('image', ''), 76, 102, 2);
let salePrice = 0; // 售卖价
let originPrice = 0; // 原价
let salePriceStr = ''; // 拼接的售卖价
let originPriceStr = ''; // 拼接的原价
let showOriginPrice = true; // 是否显示原价
let salePriceColor = '#d0021b'; // 不显示原价时,售卖价颜色
salePrice = parseFloat(data.get('sales_price'));
originPrice = parseFloat(data.get('market_price'));
salePriceStr = '¥' + salePrice.toFixed(2);
originPriceStr = '¥' + originPrice.toFixed(2);
if (!originPrice || (salePrice == originPrice)) {
showOriginPrice = false;
salePriceColor = '#444444';
}
let {editing, editedRow, rowID} = this.props;
let prdImage = YH_Image.getSlicedUrl(data.get('default_images', ''), 80, 109, 2);
let yh_exposureData = this.props.yh_exposureData ? this.props.yh_exposureData : null;
return (
<View>
<View style={styles.fatherContainer}>
<TouchableOpacity yh_exposureData={yh_exposureData} activeOpacity={1} style={[styles.container]}
onPress={() => {
this.props.onPressProduct && this.props.onPressProduct(data);
}}>
<TouchableOpacity
yh_exposureData={yh_exposureData} activeOpacity={1} style={[styles.container]}
onPress={() => {
this.props.onPressProduct && this.props.onPressProduct(data.get('product_skn'));
}}>
<View style={styles.container}>
<YH_Image style={styles.prdImage} url={prdImage}/>
<Text style={styles.prdName} numberOfLines={2}>{data.get('product_name', '')}</Text>
<View style={styles.priceContainer}>
<Text style={[styles.nowPrice, {color: salePriceColor}]} numberOfLines={1}>{salePriceStr}</Text>
{showOriginPrice
? <DeleteLineText style={styles.oldPriceContainer} textStyle={styles.oldPrice}
lineStyle={styles.deleteLine} text={originPriceStr}/>
: null}
<Text style={styles.nowPrice} numberOfLines={1}>¥{data.get('sales_price')}</Text>
</View>
<View style={[styles.bottomView, styles.returnTextContainer]}>
<Text style={styles.returnText}>最高返</Text>
<Text style={[styles.returnText, {
marginLeft: 4,
fontSize: 16
}]}>¥{data.get('rebates_amount')}</Text>
</View>
{this.renderBottomView()}
<View style={styles.shareContainer}>
<Text style={styles.share}>去分享</Text>
</View>
... ... @@ -105,10 +49,8 @@ export default class ProductCell extends Component {
};
let {width} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 375;
let nameWidth = width - 15 - 80 - 15 - 15;
let topLeftWidth = width - Math.ceil(84 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
fatherContainer: {
... ... @@ -119,48 +61,8 @@ let styles = StyleSheet.create({
},
container: {
flexDirection: 'row',
// justifyContent: 'space-between',
// alignItems: 'center',
width: width,
},
deleteContainer: {
width: 40,
height: 70,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'white',
paddingLeft: 5
},
deleteCircle: {
width: 22,
height: 22,
borderRadius: 11,
backgroundColor: 'red',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
},
deleteBar: {
width: 11,
height: 1.5,
backgroundColor: 'white'
},
tailContainer: {
width: 70,
height: 122,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'red'
},
tailText: {
color: 'white',
fontSize: 17,
backgroundColor: 'red'
},
leftContainer: {
flexDirection: 'row'
},
prdImage: {
width: 80,
height: 109
... ... @@ -168,6 +70,7 @@ let styles = StyleSheet.create({
prdName: {
fontFamily: 'PingFang-SC-Regular',
fontSize: 14,
color: '#444444',
marginTop: 3,
marginLeft: 15,
width: nameWidth,
... ... @@ -181,25 +84,7 @@ let styles = StyleSheet.create({
},
nowPrice: {
fontSize: 14,
color: '#d0021b',
},
oldPriceContainer: {
flexDirection: 'row',
marginLeft: 5,
marginTop: 2
},
oldPrice: {
fontSize: 12,
color: '#b0b0b0',
height: 16
},
deleteLine: {
position: 'absolute',
top: (16 / 2) - 1,
left: 0,
right: 0,
height: 1,
backgroundColor: '#b0b0b0'
color: '#B0B0B0',
},
bottomView: {
position: 'absolute',
... ... @@ -207,10 +92,10 @@ let styles = StyleSheet.create({
bottom: 11,
width: nameWidth,
},
soldOutContainer: {
returnTextContainer: {
flexDirection: 'row',
},
soldOut: {
returnText: {
fontSize: 14,
color: '#D0021B',
textAlign: 'center',
... ... @@ -231,19 +116,6 @@ let styles = StyleSheet.create({
color: 'white',
textAlign: 'center',
},
reduceContainer: {
flexDirection: 'row',
},
reduceImage: {
width: 15,
height: 15
},
reduceText: {
marginLeft: 2,
fontSize: 12,
color: '#b0b0b0',
width: nameWidth - 15 - 2
},
separator: {
width,
height: 1,
... ...
'use strict';
import React, {Component} from 'react';
import {Dimensions, ListView, StyleSheet, View,} from 'react-native';
import {Dimensions, ListView, StyleSheet, TouchableOpacity, View} from 'react-native';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
import ProductCell from './ProductCell';
import CategorySelector from './CategorySelector';
import Immutables,{Immutable} from "immutable";
import YH_Image from "../../../common/components/YH_Image";
let hotRecommend = Immutables.fromJS({
count: "8",
order_by: "100",
sort_name: "热门推荐",
sort_id: "0"
});
export default class Recommend extends Component {
... ... @@ -14,47 +21,74 @@ export default class Recommend extends Component {
super(props);
this.renderRow = this.renderRow.bind(this);
this.renderSectionHeader = this.renderSectionHeader.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2),
});
this.listView = null;
}
renderSectionHeader() {
let {isFetching, categoryList, selectedCategoryIndex} = this.props.data;
return (
<CategorySelector
data={categoryList}
selectedCategoryIndex={selectedCategoryIndex}
onPressCategory={(rowData, rowID) => {
this.listView && this.listView.scrollTo({x: 0, y: 0, animated: false});
this.props.onPressCategory && this.props.onPressCategory(rowData, rowID);
}}
/>
);
}
renderRow(rowData, sectionID, rowID) {
let {yh_exposureData} = rowData.toJS();
return (
<ProductCell
key={'row' + rowID}
data={rowData}
yh_exposureData={yh_exposureData}
onPressProduct={this.props.onPressProduct}
/>
);
let sliderHeight = 118 * DEVICE_WIDTH_RATIO;
let imageUrl = YH_Image.getSlicedUrl(this.props.src, width, sliderHeight, 2);
switch (sectionID) {
case 'resourceList': {
return (
<TouchableOpacity
activeOpacity={1}
style={{width: width, height: sliderHeight}}
onPress={() => {
this.props.resourceJumpWithUrl && this.props.resourceJumpWithUrl(this.props.jumpUrl);
}}
>
<YH_Image
url={imageUrl}
style={{width: width, height: sliderHeight}}
/>
</TouchableOpacity>
);
}
case 'categoryList': {
let {productList, selectedCategoryIndex} = this.props.data;
let categoryList = productList.msort_list.unshift(hotRecommend);
return (
<CategorySelector
data={categoryList}
selectedCategoryIndex={0}
onPressCategory={(rowData, rowID) => {
// this.listView && this.listView.scrollTo({x: 0, y: 0, animated: false});
// this.props.onPressCategory && this.props.onPressCategory(rowData, rowID);
}}
/>
);
}
case 'productList': {
return (
<ProductCell
key={'row' + rowID}
data={rowData}
onPressProduct={this.props.onPressProduct}
/>
);
}
default:
return null;
}
}
render() {
let {productList} = this.props.data;
let {isFetching, productList, categoryList, selectedCategoryIndex , currentPage, page_total} = this.props.data;
let isLoading = (productList.size === 0 && isFetching);
let isLoading = (productList.size === 0);
let showList = productList.size > 0;
let dataSource = {
resourceList: this.props.src ? ['resourceList'] : [],
categoryList: productList.msort_list ? productList.msort_list.toArray() : [],
productList: productList.product_list ? productList.product_list.toArray() : [],
};
return (
<View style={styles.container}>
<LoadingIndicator isVisible={isLoading}/>
... ... @@ -64,14 +98,12 @@ export default class Recommend extends Component {
}}
enableEmptySections={true}
yh_viewVisible={true}
dataSource={this.dataSource.cloneWithRows(productList.toArray())}
dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)}
renderRow={this.renderRow}
renderSectionHeader={this.renderSectionHeader}
onEndReached={() => {
if (productList && productList.size > 0 && currentPage < page_total) {
this.props.onEndReached && this.props.onEndReached();
}
// if (productList && productList.size > 0 && currentPage < page_total) {
// this.props.onEndReached && this.props.onEndReached();
// }
}}
/> : null}
</View>
... ... @@ -80,6 +112,7 @@ export default class Recommend extends Component {
}
let {width} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 375;
let styles = StyleSheet.create({
container: {
... ...
... ... @@ -14,6 +14,8 @@ export default keyMirror({
DISMISS_SURE_DIALOG: null,
SET_ORDER_CODE: null,
SET_SRC: null,
SET_JUMP_URL: null,
SHOW_WITHDRAW_DIALOG: null,
DISMISS_WITHDRAW_DIALOG: null,
... ... @@ -61,6 +63,10 @@ export default keyMirror({
TOP_LIST_SUCCESS: null,
TOP_LIST_FAILURE: null,
PRODUCT_LIST_REQUEST: null,
PRODUCT_LIST_SUCCESS: null,
PRODUCT_LIST_FAILURE: null,
GET_BANK_CARD_REQUEST: null,
GET_BANK_CARD_SUCCESS: null,
GET_BANK_CARD_FAILURE: null,
... ... @@ -95,4 +101,12 @@ export default keyMirror({
HISTORY_CLEAR_REQUEST: null,
HISTORY_CLEAR_SUCCESS: null,
HISTORY_CLEAR_FAILURE: null,
STATISTICS_REQUEST: null,
STATISTICS_SUCCESS: null,
STATISTICS_FAILURE: null,
GET_MINEUSERINFO_REQUEST: null,
GET_MINEUSERINFO_SUCCESS: null,
GET_MINEUSERINFO_FAILURE: null,
});
... ...
... ... @@ -48,6 +48,7 @@ class DataContainer extends Component {
this._hiddenSureDialog = this._hiddenSureDialog.bind(this);
this._showWithDrawDialog = this._showWithDrawDialog.bind(this);
this._hiddenWithDrawDialog = this._hiddenWithDrawDialog.bind(this);
this._changeTab = this._changeTab.bind(this);
this._jumpWithUrl = this._jumpWithUrl.bind(this);
this._resourceJumpWithUrl = this._resourceJumpWithUrl.bind(this);
this._refreshSettlementInfo = this._refreshSettlementInfo.bind(this);
... ... @@ -92,8 +93,12 @@ class DataContainer extends Component {
this.props.actions.getSettlementInfo();
}
_jumpWithUrl(title = '', type = '', orderCode = '') {
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.minealliance","params":{"title":"${title}","type":"${type}","order_code":"${orderCode}"}}`;
_changeTab(type){
this.props.actions.getStatisticsInfo(type);
}
_jumpWithUrl(title = '', type = '') {
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.minealliance","params":{"title":"${title}","type":"${type}"}}`;
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
... ... @@ -103,6 +108,9 @@ class DataContainer extends Component {
}
_resourceJumpWithUrl(url) {
if (!url) {
return
}
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
... ... @@ -113,6 +121,7 @@ class DataContainer extends Component {
showWithdrawalDialog,
settlementInfo,
addSettlement,
statisticsInfo,
} = this.props.alliance;
let tip = this.state.tips;
let isFetching = settlementInfo.isFetching;
... ... @@ -124,6 +133,7 @@ class DataContainer extends Component {
isShowWithdrawal={showWithdrawalDialog}
settlementInfo={settlementInfo}
addSettlement={addSettlement}
statisticsInfo={statisticsInfo}
tips={tip}
showHelpDialog={this._showHelpDialog}
hiddenHelpDialog={this._hiddenHelpDialog}
... ... @@ -131,6 +141,7 @@ class DataContainer extends Component {
hiddenSureDialog={this._hiddenSureDialog}
showWithdrawalDialog={this._showWithDrawDialog}
hiddenWithDrawDialog={this._hiddenWithDrawDialog}
changeTab={this._changeTab}
jumpWithUrl={this._jumpWithUrl}
refreshSettlementInfo={this._refreshSettlementInfo}
resourceJumpWithUrl={this._resourceJumpWithUrl}
... ...
... ... @@ -46,6 +46,7 @@ class HomeContainer extends Component {
this._hiddenGuideDialog = this._hiddenGuideDialog.bind(this);
this._onPressProduct = this._onPressProduct.bind(this);
this._jumpWithUrl = this._jumpWithUrl.bind(this);
this._resourceJumpWithUrl = this._resourceJumpWithUrl.bind(this);
this._onEndReached = this._onEndReached.bind(this);
... ... @@ -87,6 +88,11 @@ class HomeContainer extends Component {
});
}
_jumpWithUrl(title = '', type = '', orderCode = '') {
let url = `http://m.yohobuy.com?openby:yohobuy={"action":"go.minealliance","params":{"title":"${title}","type":"${type}","order_code":"${orderCode}"}}`;
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
_resourceJumpWithUrl(url) {
if (!url) {
return;
... ... @@ -134,6 +140,7 @@ class HomeContainer extends Component {
resourceInfo={resourceInfo}
topList={topList}
hiddenGuideDialog={this._hiddenGuideDialog}
jumpWithUrl={this._jumpWithUrl}
resourceJumpWithUrl={this._resourceJumpWithUrl}
onPressProduct={this._onPressProduct}
onEndReached={this._onEndReached}
... ...
... ... @@ -42,6 +42,7 @@ class MineContainer extends Component {
}
componentDidMount() {
this.props.actions.getMineUserInfo();
this.props.actions.getSettlementInfo();
this.props.actions.getMineResourceInfo();
}
... ... @@ -69,6 +70,7 @@ class MineContainer extends Component {
render() {
let {
profile,
settlementInfo,
mineResourceInfo,
} = this.props.alliance;
... ... @@ -76,6 +78,7 @@ class MineContainer extends Component {
return (
<View style={styles.container}>
<Mine
profile={profile}
settlementInfo={settlementInfo}
mineResourceInfo={mineResourceInfo}
jumpWithUrl={this._jumpWithUrl}
... ...
... ... @@ -7,11 +7,13 @@ import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as recommendActions from '../reducers/recommend/recommendActions';
import * as appActions from '../reducers/app/appActions';
import Recommend from '../components/recommend/Recommend';
const actions = [
appActions,
recommendActions,
];
... ... @@ -38,14 +40,21 @@ class RecommendContainer extends Component {
constructor(props) {
super(props);
this._resourceJumpWithUrl = this._resourceJumpWithUrl.bind(this);
this.onPressCategory = this.onPressCategory.bind(this);
this.onPressProduct = this.onPressProduct.bind(this);
this.onEndReached = this.onEndReached.bind(this);
}
componentDidMount() {
this.props.actions.historySortList();
this.props.actions.historyList(0);
this.props.actions.getProductList();
}
_resourceJumpWithUrl(url) {
if (!url) {
return
}
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
onPressCategory(data, index) {
... ... @@ -63,13 +72,16 @@ class RecommendContainer extends Component {
}
onEndReached() {
this.props.actions.historyList();
this.props.actions.getProductList();
}
render() {
return (
<Recommend
data={this.props.recommend}
data={this.props.app}
src={this.props.alliance.src}
jumpUrl={this.props.alliance.jumpUrl}
resourceJumpWithUrl={this._resourceJumpWithUrl}
onPressCategory={this.onPressCategory}
onPressProduct={this.onPressProduct}
onEndReached={this.onEndReached}
... ...
... ... @@ -19,6 +19,8 @@ const {
DISMISS_BANK_INFO_DIALOG,
SET_ORDER_CODE,
SET_SRC,
SET_JUMP_URL,
SETTLEMENT_INFO_REQUEST,
SETTLEMENT_INFO_SUCCESS,
... ... @@ -76,6 +78,14 @@ const {
BIND_BANK_CARD_SUCCESS,
BIND_BANK_CARD_FAILURE,
STATISTICS_REQUEST,
STATISTICS_SUCCESS,
STATISTICS_FAILURE,
GET_MINEUSERINFO_REQUEST,
GET_MINEUSERINFO_SUCCESS,
GET_MINEUSERINFO_FAILURE,
} = require('../../constants/actionTypes').default;
export function showHelpDialog() {
... ... @@ -133,6 +143,20 @@ export function setOrderCode(orderCode) {
};
}
export function setSrc(src) {
return {
type: SET_SRC,
payload: src,
};
}
export function setJumpUrl(jumpUrl) {
return {
type: SET_JUMP_URL,
payload: jumpUrl,
};
}
export function settlementInfoRequest() {
return {
type: SETTLEMENT_INFO_REQUEST,
... ... @@ -413,6 +437,46 @@ export function bindBankCardFailure(error) {
};
}
export function getStatisticsInfoRequest() {
return {
type: STATISTICS_REQUEST,
};
}
export function getStatisticsInfoSuccess(json) {
return {
type: STATISTICS_SUCCESS,
payload: json,
}
}
export function getStatisticsInfoFailure() {
return {
type: STATISTICS_FAILURE,
payload: error
}
}
export function getMineUserInfoRequest() {
return {
type: GET_MINEUSERINFO_REQUEST,
};
}
export function getMineUserInfoSuccess(json) {
return {
type: GET_MINEUSERINFO_SUCCESS,
payload: json,
}
}
export function getMineUserInfoFailure() {
return {
type: GET_MINEUSERINFO_FAILURE,
payload: error
}
}
export function getSettlementInfo() {
return (dispatch, getState) => {
let {app} = getState();
... ... @@ -835,3 +899,53 @@ function exposeProductListData(json) {
res.product_list = list;
return res;
}
export function getStatisticsInfo(queryTimeType) {
return (dispatch, getState) => {
let {app} = getState();
let fetchStatisticsInfo = (uid) => {
dispatch(getStatisticsInfoRequest());
return new AllianceService(app.host).fetchStatisticsInfo(uid, queryTimeType)
.then(json => {
dispatch(getStatisticsInfoSuccess(json));
})
.catch(error => {
dispatch(getStatisticsInfoFailure());
});
};
let uid = 0;
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
fetchStatisticsInfo(uid)
})
.catch(error => {
fetchStatisticsInfo(uid)
});
}
}
export function getMineUserInfo() {
return (dispatch, getState) => {
let {app} = getState();
let funGetMineUserInfo = () => {
dispatch(getMineUserInfoRequest());
return new AllianceService(app.host).getMineUserInfo()
.then(json => {
dispatch(getMineUserInfoSuccess(json));
})
.catch(error => {
dispatch(getMineUserInfoFailure());
});
};
// 从native端获取登录状态,如果没有,才调用getMineUserInfoFailure,设置uid为0
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(data => {
funGetMineUserInfo();
})
.catch(error => {
});
}
}
... ...
... ... @@ -5,6 +5,8 @@ import {List, Map, Record} from 'immutable';
let InitialState = Record({
orderCode: 0,
src: '',
jumpUrl: '',
showHelpDialog: false,
showSureDialog: false,
showWithdrawalDialog: false,
... ... @@ -120,6 +122,25 @@ let InitialState = Record({
error: null,
})),
statisticsInfo: new (Record({
isFetching: false,
error: null,
orderNum: 0,
clickNum: 0,
orderAmountSum: 0,
extraAmountSum: 0,
})),
/** 个人信息state */
profile: new (Record({
isFetching: false,
error: null,
head_ico: '',
nickname: '',
profile_name: '',
username: '',
})),
});
export default InitialState;
... ...
... ... @@ -17,6 +17,8 @@ const {
DISMISS_BANK_INFO_DIALOG,
SET_ORDER_CODE,
SET_SRC,
SET_JUMP_URL,
SETTLEMENT_INFO_REQUEST,
SETTLEMENT_INFO_SUCCESS,
... ... @@ -74,6 +76,14 @@ const {
BIND_BANK_CARD_SUCCESS,
BIND_BANK_CARD_FAILURE,
STATISTICS_REQUEST,
STATISTICS_SUCCESS,
STATISTICS_FAILURE,
GET_MINEUSERINFO_REQUEST,
GET_MINEUSERINFO_SUCCESS,
GET_MINEUSERINFO_FAILURE,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
... ... @@ -116,6 +126,14 @@ export default function couponReducer(state = initialState, action) {
return state.set('orderCode', action.payload);
}
case SET_SRC: {
return state.set('src', action.payload);
}
case SET_JUMP_URL: {
return state.set('jumpUrl', action.payload);
}
case SETTLEMENT_INFO_REQUEST: {
return state.setIn(['settlementInfo', 'isFetching'], true)
.setIn(['settlementInfo', 'error'], null);
... ... @@ -400,6 +418,46 @@ export default function couponReducer(state = initialState, action) {
return state.setIn(['bindBankCardResult', 'isFetching'], false)
.setIn(['bindBankCardResult', 'error'], null);
}
case STATISTICS_REQUEST:
return state.setIn(['statisticsInfo', 'isFetching'], true);
case STATISTICS_SUCCESS: {
let {
orderNum,
clickNum,
orderAmountSum,
extraAmountSum,
} = action.payload;
return state.setIn(['statisticsInfo', 'isFetching'], false)
.setIn(['statisticsInfo', 'orderNum'], orderNum)
.setIn(['statisticsInfo', 'clickNum'], clickNum)
.setIn(['statisticsInfo', 'orderAmountSum'], orderAmountSum)
.setIn(['statisticsInfo', 'extraAmountSum'], extraAmountSum);
}
case STATISTICS_FAILURE:
return state.setIn(['statisticsInfo', 'isFetching'], false)
.setIn(['statisticsInfo', 'error'], null);
case GET_MINEUSERINFO_REQUEST:
return state.setIn(['profile', 'isFetching'], true);
case GET_MINEUSERINFO_SUCCESS: {
let {
head_ico,
nickname,
profile_name,
username,
} = action.payload;
return state.setIn(['profile', 'isFetching'], false)
.setIn(['profile', 'head_ico'], head_ico)
.setIn(['profile', 'nickname'], nickname)
.setIn(['profile', 'profile_name'], profile_name)
.setIn(['profile', 'username'], username);
}
case GET_MINEUSERINFO_FAILURE:
return state.setIn(['profile', 'isFetching'], false)
.setIn(['profile', 'error'], null);
}
return state;
... ...
'use strict';
import ReactNative from 'react-native';
import AppService from '../../services/AppService';
const Platform = require('Platform');
const {
SET_PLATFORM,
SET_CHANNEL,
SET_HOST,
SET_SERVICE_HOST
SET_SERVICE_HOST,
PRODUCT_LIST_REQUEST,
PRODUCT_LIST_SUCCESS,
PRODUCT_LIST_FAILURE,
} = require('../../constants/actionTypes').default;
export function setPlatform(platform) {
... ... @@ -34,3 +44,103 @@ export function setServiceHost(host) {
payload: host
};
}
export function productListRequest() {
return {
type: PRODUCT_LIST_REQUEST,
};
}
export function productListSuccess(json) {
return {
type: PRODUCT_LIST_SUCCESS,
payload: json
};
}
export function productListFailure(error) {
return {
type: PRODUCT_LIST_FAILURE,
payload: error
};
}
export function getProductList() {
return (dispatch, getState) => {
let {app} = getState();
let list = app.productList;
/**
* page: 0, //当前页面
* page_size: 20, //每页显示的数量
* total: 0, //总共多少条
* page_total: 0, //总共多少页
* endReached: false, //到达底部
*/
if (list.isFetching || list.endReached || list.error || (!list.endReached && list.page_total === 1)) {
return;
}
let page = list.page + 1;
let pageSize = list.page_size;
console.log(pageSize);
let fetchProductList = (uid) => {
dispatch(productListRequest());
return new AppService(app.host).fetchProductList(uid, page, pageSize)
.then(json => {
let payload = json;
try {
payload = exposeProductListData(json);
} catch (e) {
}
payload.endReached = (payload.page === payload.page_total) && (payload.page_total !== 1);
if (payload.page > 1) {
let oldList = list.product_list.toJS();
let newList = [...oldList, ...payload.product_list];
payload.product_list = newList;
}
dispatch(productListSuccess(payload));
})
.catch(error => {
dispatch(productListFailure(error));
});
};
let uid = 0;
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
fetchProductList(uid)
})
.catch(error => {
fetchProductList(uid)
});
};
}
function exposeProductListData(json) {
let list = json ? json.product_list : [];
let res = json;
if (!list) {
return list;
}
let pageName = 'iFP_Alliance';
if (Platform.OS === 'android') {
pageName = 'aFP_Alliance';
}
for (var i = 0; i < list.length; i++) {
let item = list[i];
let skn = item.product_skn;
let inFloorIndex = parseInt(i) + 1 + '';
item.yh_exposureData = {
P_NAME: pageName,
I_INDEX: inFloorIndex,
PRD_SKN: skn,
exposureEnd: 1,
};
}
res.product_list = list;
return res;
}
... ...
'use strict';
import {Record} from 'immutable';
import {List, Record} 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://api.yoho.cn',
productList: new (Record({
isFetching: false,
error: null,
page: 0, //当前页面
page_size: 20, //每页显示的数量
total: 0, //总共多少条
page_total: 0, //总共多少页
endReached: false, //到达底部
product_list: List(),
msort_list: List(),
})),
});
export default InitialState;
... ...
'use strict';
import InitialState from './appInitialState';
import Immutable from "immutable";
const {
SET_PLATFORM,
SET_CHANNEL,
SET_HOST,
SET_SERVICE_HOST,
PRODUCT_LIST_REQUEST,
PRODUCT_LIST_SUCCESS,
PRODUCT_LIST_FAILURE,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
... ... @@ -23,6 +27,33 @@ export default function appReducer(state = initialState, action) {
return state.set('host', action.payload);
case SET_SERVICE_HOST:
return state.set('serviceHost', action.payload);
case PRODUCT_LIST_REQUEST: {
return state.setIn(['productList', 'isFetching'], true)
.setIn(['productList', 'error'], null);
}
case PRODUCT_LIST_SUCCESS: {
let {
page,
page_total,
endReached,
product_list,
msort_list,
} = action.payload;
return state.setIn(['productList', 'isFetching'], false)
.setIn(['productList', 'page'], page)
.setIn(['productList', 'page_total'], page_total)
.setIn(['productList', 'endReached'], endReached)
.setIn(['productList', 'product_list'], Immutable.fromJS(product_list))
.setIn(['productList', 'msort_list'], Immutable.fromJS(msort_list))
.setIn(['productList', 'error'], null);
}
case PRODUCT_LIST_FAILURE: {
return state.setIn(['productList', 'isFetching'], false)
.setIn(['productList', 'error'], action.payload);
}
}
return state;
... ...
... ... @@ -237,4 +237,41 @@ export default class AllianceService {
});
}
//(统计信息)
async fetchStatisticsInfo(uid, queryTimeType) {
return await this.api.get({
url: '',
body: {
uid,
queryTimeType,
method: 'app.union.shareOrder.getStatisticsInfo',
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
/**
* 获取用户个人信息
*/
async getMineUserInfo(fromPage = 'aFP_Alliance') {
return await this.api.get({
url: '',
body: {
method: 'app.passport.profile',
fromPage,
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...
'use strict';
import Request from '../../common/services/NativeRequest';
export default class AppService {
constructor(host) {
let baseURL = 'http://api.yoho.cn';
if (host) {
baseURL = host;
}
this.api = new Request(baseURL);
}
async fetchProductList(uid, page, limit = 20, msort = 0, product_pool = 680) {
return await this.api.get({
url: '',
body: {
method: 'app.search.cpsPool.productList',
uid,
page,
limit,
// msort,
product_pool,
debug: 'XYZ'
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async fetchProductInfo(uid = 0, product_skn) {
return await this.api.get({
url: '',
body: {
method: 'app.union.shareOrder.getProductInfo',
uid,
product_skn
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
}
... ...