Authored by 盖剑秋

My order list data. reviewed by redding.

... ... @@ -33,6 +33,10 @@ import {
setProductSKN,
} from './reducers/detail/detailActions';
import {
setFirstShowIndex
} from './reducers/list/listActions';
function getInitialState() {
const _initState = {
app: (new appInitialState()),
... ... @@ -55,6 +59,7 @@ export default function native(platform) {
let type = this.props.type;
if (type == 'list') {
store.dispatch(setFirstShowIndex(this.props.firstShowIndex));
return (
<Provider store={store}>
<ListContainer />
... ...
... ... @@ -3,9 +3,9 @@
import React, {Component} from 'react';
import Immutable, {Map} from 'immutable';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator';
import ListCell from './ListCell';
import ListBannerSwiper from './ListBannerSwiper';
import ListContent from './ListContent';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import {DefaultTabBar} from 'react-native-scrollable-tab-view';
import ReactNative, {
View,
... ... @@ -24,74 +24,41 @@ export default class List extends Component {
constructor(props) {
super(props);
this.renderRow = this.renderRow.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
sectionHeaderHasChanged: (s1, s2) => !Immutable.is(s1, s2),
});
}
renderRow(rowData,sectionID,rowID,highlightRow) {
switch (sectionID) {
case 'banner': {
return <ListBannerSwiper resource={rowData} onPressBanner={this.props.onPressBanner}/>
}
break;
case 'list': {
return <ListCell resource={rowData} onPressDetail={this.props.onPressDetail}/>;
}
break;
}
return null;
}
render() {
let {products, banner} = this.props.resource;
let isProductListFetching = products.isFetching;
let isFetching = (isProductListFetching && products.page == 0) || banner.isFetching;
let list = products.list && products.list.toJS();
let bannerData = [];
if (banner.data && banner.data.toJS()) {
let bannerDataArray = banner.data.toJS();
if (bannerDataArray.length > 0) {
bannerData = bannerDataArray[0].data;
}
}
let dataBlob = {
'banner': bannerData.length ? [bannerData] : [],
'list': list ? list : [],
};
return (
<View style={styles.container}>
{!isFetching?
<ListView
contentContainerStyle={styles.contentContainer}
enableEmptySections={true}
showsVerticalScrollIndicator={false}
dataSource={this.dataSource.cloneWithRowsAndSections(dataBlob)}
renderRow={this.renderRow}
onEndReached={() => {
if (list && list.length) {
this.props.onEndReached && this.props.onEndReached();
<ScrollableTabView
initialPage={2}
renderTabBar={() => <DefaultTabBar
underlineHeight={0}
activeTextColor={'black'}
inactiveTextColor={'gray'}
style={{height: 30}}/>
}
}}
renderFooter={()=>{
if (list && list.length && isProductListFetching) {
return <LoadMoreIndicator
isVisible={true}
animating={true}
/>;
} else {
return null;
}
}}
>
<ListContent style={{backgroundColor: 'red'}}
tabLabel={'全部'}
type={'all'}
getOrderListByType={this.props.getOrderListByType}
/>
<ListContent style={{ backgroundColor: 'green'}}
tabLabel={'待付款'}
type={'onPay'}
getOrderListByType={this.props.getOrderListByType}
/>
:<LoadingIndicator
isVisible={isFetching}
/>}
<ListContent style={{backgroundColor: 'orange'}}
tabLabel={'待发货'}
type={'onDelivery'}
getOrderListByType={this.props.getOrderListByType}
/>
<ListContent style={{backgroundColor: 'blue'}}
tabLabel={'待收货'}
type={'onReceive'}
getOrderListByType={this.props.getOrderListByType}
/>
</ScrollableTabView>
</View>
);
}
... ... @@ -99,11 +66,6 @@ export default class List extends Component {
let {width, height} = Dimensions.get('window');
let rowWidth = Math.ceil(137.5 * width / 320);
let rowHeight = Math.ceil(254 * width / 320);
let rowMarginTop = Math.ceil(10 * width / 320);
let rowMarginHorizontal = (width - rowWidth * 2) / 3;
let styles = StyleSheet.create({
container: {
flex: 1,
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
import Swiper from 'react-native-swiper';
import ImmutablePropTypes from 'react-immutable-proptypes';
import SlicedImage from '../../../common/components/SlicedImage';
import Immutable, {Map} from 'immutable';
const {
View,
Image,
TouchableOpacity,
StyleSheet,
Dimensions,
Platform,
} = ReactNative;
export default class ListBannerSwiper extends React.Component {
constructor(props) {
super (props);
this.dot = <View
style={{
backgroundColor:'rgba(0,0,0,.2)',
width: 6,
height: 6,
borderRadius: 3,
marginLeft: 3,
marginRight: 3,
marginTop: (Platform.OS === 'ios')?3:23,
marginBottom: 0,
}}
/>;
this.activeDot = <View
style={{
backgroundColor:'white',
width: 6,
height: 6,
borderRadius: 3,
marginLeft: 3,
marginRight: 3,
marginTop: 3,
marginBottom: 0,
}}
/>;
}
render() {
let {resource} = this.props;
return (
<View style={styles.container}>
<Swiper
style={styles.banner}
showsButtons={false}
loop={true}
autoplay={true}
autoplayTimeout={2}
paginationStyle={{bottom: 8}}
dot={this.dot}
activeDot={(Platform.OS === 'ios')?this.activeDot:null}
width={width}
height={height}
>
{resource.map((item, i) => {
return (
<TouchableOpacity
key={i}
activeOpacity={1}
onPress={() => {
this.props.onPressBanner && this.props.onPressBanner(item.url);
}}
>
<SlicedImage source={{uri: item.src}} style={{width, height}}/>
</TouchableOpacity>
);
})}
</Swiper>
</View>
);
}
}
let {width} = Dimensions.get('window');
let height = Math.ceil((310 / 640) * width) + 40;
let styles = StyleSheet.create({
container: {
width: width,
height: height,
backgroundColor:'#f0f0f0',
},
banner: {
},
});
... ... @@ -17,36 +17,22 @@ import ReactNative, {
export default class ListCell extends Component {
export default class ListContent extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log(this.props.tabLabel);
this.props.getOrderListByType(this.props.type);
}
render() {
let data = this.props.resource;
if (!data) {
return null;
}
let {
default_images,
product_skn,
phrase,
product_name,
} = data;
default_images = default_images.replace('{width}', 240).replace('{height}', 320).replace('{mode}',2);
return (
<TouchableOpacity style={styles.container} onPress={() => {this.props.onPressDetail && this.props.onPressDetail(product_skn)}}>
<View style={styles.container}>
<Image style={styles.image} source={{uri:default_images}}/>
<View style={[styles.container, this.props.style]}>
<View style={styles.rightPannel}>
<Text numberOfLines={2} style={styles.title}>{product_name}</Text>
<Text numberOfLines={4} style={styles.phrase}>{phrase}</Text>
</View>
</View>
</TouchableOpacity>
);
}
}
... ... @@ -55,43 +41,7 @@ let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
width: width,
flexDirection: 'row',
height: 180,
},
image: {
marginTop: 10,
marginLeft: 15,
marginRight: 15,
width: 120,
height: 160,
backgroundColor: '#e0e0e0',
},
rightPannel: {
width: width - 150,
height: 180,
flexDirection: 'column',
borderColor: '#ededed',
borderBottomWidth: 1,
},
title: {
fontSize: 15,
width: width - 150 - 15,
marginTop: 20,
marginBottom: 0,
color: '#444444',
// backgroundColor: 'red',
},
phrase: {
marginTop: 6,
width: width - 150 - 15,
fontSize: 13,
color: '#b0b0b0',
lineHeight: 20,
// backgroundColor: 'red',
},
});
... ...
... ... @@ -7,7 +7,7 @@ export default keyMirror({
SET_SERVICE_HOST: null,
SET_CHANNEL: null,
SET_SINGLE_HOST: null,
SET_FIRST_SHOW_INDEX: null,
SET_PRODUCT_SKN: null,
GET_DETAIL_REQUEST: null,
GET_DETAIL_SUCCESS: null,
... ... @@ -19,9 +19,9 @@ export default keyMirror({
SET_FAVORITE_STATUS: null,
// 列表
GET_PRODUCT_LIST_REQUEST: null,
GET_PRODUCT_LIST_SUCCESS: null,
GET_PRODUCT_LIST_FAILURE: null,
GET_ORDER_LIST_REQUEST: null,
GET_ORDER_LIST_SUCCESS: null,
GET_ORDER_LIST_FAILURE: null,
// 列表资源位
FETCH_BANNER_REQUEST: null,
... ...
... ... @@ -46,48 +46,35 @@ function mapDispatchToProps(dispatch) {
class ListContainer extends Component {
constructor(props) {
super(props);
this._onPressDetail = this._onPressDetail.bind(this);
this._onPressBanner = this._onPressBanner.bind(this);
this._onEndReached = this._onEndReached.bind(this);
this._getOrderListByType = this._getOrderListByType.bind(this);
}
componentDidMount() {
this.props.actions.fetchBanner();
this.props.actions.getProductList();
}
componentWillUnmount() {
}
_onPressDetail(product_skn) {
if (!product_skn) {
return;
}
ReactNative.NativeModules.YH_CommonHelper.pushGoodGoodsRecommendDetailWithProductSKN(product_skn + '');
}
componentWillUnmount() {
_onPressBanner(url) {
if (!url) {
return;
}
ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(url);
}
_onEndReached() {
_onEndReached(type) {
InteractionManager.runAfterInteractions(() => {
this.props.actions.getProductList();
this.props.actions.getOrderListByType(type);
});
}
_getOrderListByType(type) {
this.props.actions.getOrderListByType(type);
}
render() {
let {list} = this.props;
return (
<List
resource={list}
onPressDetail={this._onPressDetail}
onEndReached={this._onEndReached}
onPressBanner={this._onPressBanner}
getOrderListByType={this._getOrderListByType}
/>
);
}
... ...
... ... @@ -6,27 +6,38 @@ import ListService from '../../services/ListService';
import helper from '../../../common/utils/helper';
const {
GET_PRODUCT_LIST_REQUEST,
GET_PRODUCT_LIST_SUCCESS,
GET_PRODUCT_LIST_FAILURE,
FETCH_BANNER_REQUEST,
FETCH_BANNER_SUCCESS,
FETCH_BANNER_FAILURE,
GET_ORDER_LIST_REQUEST,
GET_ORDER_LIST_SUCCESS,
GET_ORDER_LIST_FAILURE,
SET_FIRST_SHOW_INDEX,
} = require('../../constants/actionTypes').default;
export function getProductList() {
export function setFirstShowIndex(firstShowIndex) {
return {
type: SET_FIRST_SHOW_INDEX,
payload: firstShowIndex,
}
}
export function getOrderListByType(type) {
return (dispatch, getState) => {
let {app, list} = getState();
let {products} = list;
if (products.isFetching || products.endReached || products.error) {
let currentList = list.get(type);
let typeMap = list.get('typeMap');
let currentType = typeMap.get(type);
let page = currentList.currentPage + 1;
let pageSize = currentList.pageSize;
if (currentList.isFetching || currentList.endReached || currentList.error) {
return;
}
let fetchList = (channel, gender, uid, page, pageSize) => {
dispatch(getProductListRequest());
return new ListService(app.serviceHost).getProductListData(channel, gender, uid, page, pageSize)
return new ListService(app.host).getOrderListByType(currentType, page, pageSize)
.then(json => {
console.log(json);
let payload = parseProductList(json);
payload.endReached = payload.currentPage == payload.pageCount;
... ... @@ -40,24 +51,7 @@ export function getProductList() {
.catch(error => {
dispatch(getProductListFailure(error));
});
};
let channel = app.channel;
let gender = '';
let uid = 0;
let page = products.currentPage + 1;
let pageSize = products.pageSize;
Promise.all([
ReactNative.NativeModules.YH_CommonHelper.currentGender(),
ReactNative.NativeModules.RNNativeConfig.uid(),
]).then(result => {
gender = result[0];
uid = result[1];
fetchList(channel, gender, uid, page, pageSize);
}).catch(error => {
});
};
}
... ... @@ -77,59 +71,20 @@ function parseProductList(json) {
export function getProductListRequest() {
return {
type: GET_PRODUCT_LIST_REQUEST,
type: GET_ORDER_LIST_REQUEST,
};
}
export function getProductListSuccess(json) {
return {
type: GET_PRODUCT_LIST_SUCCESS,
type: GET_ORDER_LIST_SUCCESS,
payload: json
};
}
export function getProductListFailure(error) {
return {
type: GET_PRODUCT_LIST_FAILURE,
payload: error
};
}
export function fetchBanner() {
return (dispatch, getState) => {
let {app, list} = getState();
let {banner} = list;
if (banner.isFetching || banner.error) {
return;
}
dispatch(fetchBannerRequest());
return new ListService(app.serviceHost).fetchBannerData()
.then(json => {
dispatch(fetchBannerSuccess(json));
})
.catch(error => {
dispatch(fetchBannerFailure(error));
});
}
}
export function fetchBannerRequest() {
return {
type: FETCH_BANNER_REQUEST
};
}
export function fetchBannerSuccess(json) {
return {
type: FETCH_BANNER_SUCCESS,
payload: json
};
}
export function fetchBannerFailure(error) {
return {
type: FETCH_BANNER_FAILURE,
type: GET_ORDER_LIST_FAILURE,
payload: error
};
}
... ...
... ... @@ -2,22 +2,32 @@
import {Record, List, Map} from 'immutable';
let InitialState = Record({
banner: new (Record({
isFetching: false,
error: null,
data: null,
})),
products: new (Record({
let templet = new(Record({
firstLoad: true,
isFetching: false,
error: null,
list: null,
currentPage: 0,
pageCount: 0,
pageSize: 20,
pageSize: 60,//60,
total: 0,
endReached: false,
})),
}));
let typeMap = new(Record({
all: '1',
onPay: '2',
onDelivery: '3',
onReceive: '4',
}));
let InitialState = Record({
firstShowIndex: 0,
all: templet,
onPay: templet,
onDelivery: templet,
onReceive: templet,
typeMap,
});
export default InitialState;
... ...
... ... @@ -4,22 +4,24 @@ import InitialState from './listInitialState';
import Immutable, {Map} from 'immutable';
const {
GET_PRODUCT_LIST_REQUEST,
GET_PRODUCT_LIST_SUCCESS,
GET_PRODUCT_LIST_FAILURE,
FETCH_BANNER_REQUEST,
FETCH_BANNER_SUCCESS,
FETCH_BANNER_FAILURE,
GET_ORDER_LIST_REQUEST,
GET_ORDER_LIST_SUCCESS,
GET_ORDER_LIST_FAILURE,
SET_FIRST_SHOW_INDEX,
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function listReducer(state=initialState, action) {
switch(action.type) {
case GET_PRODUCT_LIST_REQUEST: {
return state.setIn(['products', 'isFetching'], true);
case SET_FIRST_SHOW_INDEX: {
return state.set('firstShowIndex', action.payload);
}
case GET_ORDER_LIST_REQUEST: {
return state;
}
case GET_PRODUCT_LIST_SUCCESS: {
case GET_ORDER_LIST_SUCCESS: {
let {
list,
currentPage,
... ... @@ -28,30 +30,12 @@ export default function listReducer(state=initialState, action) {
endReached,
} = action.payload;
let newState = state.setIn(['products', 'isFetching'], false)
.setIn(['products', 'error'], null)
.setIn(['products', 'list'], Immutable.fromJS(list))
.setIn(['products', 'currentPage'], currentPage)
.setIn(['products', 'pageCount'], pageCount)
.setIn(['products', 'total'], total)
.setIn(['products', 'endReached'], endReached);
let newState = state
return newState;
}
case GET_PRODUCT_LIST_FAILURE: {
return state.setIn(['products', 'isFetching'], false)
.setIn(['products', 'error'], action.payload);
}
case FETCH_BANNER_REQUEST: {
return state.setIn(['banner', 'isFetching'], true);
}
case FETCH_BANNER_SUCCESS: {
return state.setIn(['banner', 'isFetching'], false)
.setIn(['banner', 'data'], Immutable.fromJS(action.payload));
}
case FETCH_BANNER_FAILURE: {
return state.setIn(['banner', 'isFetching'], false)
.setIn(['banner', 'error'], action.payload);
case GET_ORDER_LIST_FAILURE: {
return state;
}
}
... ...
... ... @@ -12,41 +12,15 @@ export default class ListService {
this.api = new Request(baseURL);
}
async getProductListData(channel, gender, uid, page, pageSize) {
// this.api = new Request('http://dev-api.yohops.com:9999');
async getOrderListByType(type = '1', page, pageSize) {
return await this.api.get({
url: '',
body: {
method: 'app.search.good',
// debug: 'XYZ',
uid: uid,
method: 'app.SpaceOrders.get',
limit: pageSize,
page: page,
yh_channel: channel,
gender: gender,
app_type: '0'
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async fetchBannerData() {
// this.api = new Request('http://service-test3.yohops.com:9999');
let content_code = 'efe8847a09c501c363ed94f87e32c0d7';
let fromPage = '';
return await this.api.get({
url: '/operations/api/v5/resource/get',
body: {
fromPage,
content_code
type,
}
})
.then((json) => {
... ...