Merge branch 'local' into develop
Showing
42 changed files
with
583 additions
and
78 deletions
@@ -44,6 +44,7 @@ const styles = StyleSheet.create({ | @@ -44,6 +44,7 @@ const styles = StyleSheet.create({ | ||
44 | flexDirection: 'row', | 44 | flexDirection: 'row', |
45 | justifyContent: 'center', | 45 | justifyContent: 'center', |
46 | alignItems: 'center', | 46 | alignItems: 'center', |
47 | + width: Dimensions.get('window').width, | ||
47 | height: 44, | 48 | height: 44, |
48 | }, | 49 | }, |
49 | indicator: { | 50 | indicator: { |
@@ -23,7 +23,7 @@ export default class SlicedImage extends React.Component { | @@ -23,7 +23,7 @@ export default class SlicedImage extends React.Component { | ||
23 | width = PixelRatio.getPixelSizeForLayoutSize(width); | 23 | width = PixelRatio.getPixelSizeForLayoutSize(width); |
24 | height = PixelRatio.getPixelSizeForLayoutSize(height); | 24 | height = PixelRatio.getPixelSizeForLayoutSize(height); |
25 | let newSrc = src; | 25 | let newSrc = src; |
26 | - if (src.indexOf('imageView') === -1) { | 26 | + if (src.indexOf('imageView') === -1 && src.indexOf('imageMogr') === -1) { |
27 | newSrc = src + '?imageView2/' + mode + '/w/' + width + '/h/' + height; | 27 | newSrc = src + '?imageView2/' + mode + '/w/' + width + '/h/' + height; |
28 | } else { | 28 | } else { |
29 | newSrc = src.replace('{mode}', mode) | 29 | newSrc = src.replace('{mode}', mode) |
@@ -36,8 +36,7 @@ export default class ProductFilter extends React.Component { | @@ -36,8 +36,7 @@ export default class ProductFilter extends React.Component { | ||
36 | asc: 's_n_desc', | 36 | asc: 's_n_desc', |
37 | desc: 's_n_desc', | 37 | desc: 's_n_desc', |
38 | }, | 38 | }, |
39 | - isAsc: true, | ||
40 | - selected: false, | 39 | + isAsc: false, |
41 | radio: true, | 40 | radio: true, |
42 | }, | 41 | }, |
43 | { | 42 | { |
@@ -47,8 +46,7 @@ export default class ProductFilter extends React.Component { | @@ -47,8 +46,7 @@ export default class ProductFilter extends React.Component { | ||
47 | asc: 's_t_desc', | 46 | asc: 's_t_desc', |
48 | desc: 's_t_desc', | 47 | desc: 's_t_desc', |
49 | }, | 48 | }, |
50 | - isAsc: true, | ||
51 | - selected: false, | 49 | + isAsc: false, |
52 | radio: true, | 50 | radio: true, |
53 | }, | 51 | }, |
54 | { | 52 | { |
@@ -58,8 +56,7 @@ export default class ProductFilter extends React.Component { | @@ -58,8 +56,7 @@ export default class ProductFilter extends React.Component { | ||
58 | asc: 's_p_asc', | 56 | asc: 's_p_asc', |
59 | desc: 's_p_desc', | 57 | desc: 's_p_desc', |
60 | }, | 58 | }, |
61 | - isAsc: true, | ||
62 | - selected: false, | 59 | + isAsc: false, |
63 | radio: false, | 60 | radio: false, |
64 | }, | 61 | }, |
65 | { | 62 | { |
@@ -69,8 +66,7 @@ export default class ProductFilter extends React.Component { | @@ -69,8 +66,7 @@ export default class ProductFilter extends React.Component { | ||
69 | asc: 'p_d_asc', | 66 | asc: 'p_d_asc', |
70 | desc: 'p_d_desc', | 67 | desc: 'p_d_desc', |
71 | }, | 68 | }, |
72 | - isAsc: true, | ||
73 | - selected: false, | 69 | + isAsc: false, |
74 | radio: false, | 70 | radio: false, |
75 | }, | 71 | }, |
76 | ], | 72 | ], |
@@ -105,15 +101,22 @@ export default class ProductFilter extends React.Component { | @@ -105,15 +101,22 @@ export default class ProductFilter extends React.Component { | ||
105 | let colorStyle = rowID == this.state.selectedIndex ? {color: '#444444'} : {color: '#b0b0b0'}; | 101 | let colorStyle = rowID == this.state.selectedIndex ? {color: '#444444'} : {color: '#b0b0b0'}; |
106 | 102 | ||
107 | return ( | 103 | return ( |
108 | - <TouchableOpacity onPress={()=>{ | 104 | + <TouchableOpacity onPress={() => { |
109 | let filters = this.state.filters; | 105 | let filters = this.state.filters; |
110 | let filter = this.state.filters[rowID]; | 106 | let filter = this.state.filters[rowID]; |
107 | + if (filter.radio && this.state.selectedIndex == rowID) { | ||
108 | + return; | ||
109 | + } | ||
110 | + | ||
111 | filter.isAsc = !filter.isAsc; | 111 | filter.isAsc = !filter.isAsc; |
112 | filters[rowID] = filter; | 112 | filters[rowID] = filter; |
113 | this.setState({ | 113 | this.setState({ |
114 | selectedIndex: rowID, | 114 | selectedIndex: rowID, |
115 | filters, | 115 | filters, |
116 | }); | 116 | }); |
117 | + | ||
118 | + let value = filter.isAsc ? filter.value['asc'] : filter.value['desc']; | ||
119 | + this.props.onPressFilter && this.props.onPressFilter(value); | ||
117 | }}> | 120 | }}> |
118 | <View key={'row' + rowID} style={styles.rowContainer}> | 121 | <View key={'row' + rowID} style={styles.rowContainer}> |
119 | <Text style={[styles.name, colorStyle]}>{rowData.name}</Text> | 122 | <Text style={[styles.name, colorStyle]}>{rowData.name}</Text> |
@@ -132,17 +135,18 @@ export default class ProductFilter extends React.Component { | @@ -132,17 +135,18 @@ export default class ProductFilter extends React.Component { | ||
132 | 135 | ||
133 | render() { | 136 | render() { |
134 | 137 | ||
135 | - let {} = this.props; | 138 | + let {style} = this.props; |
136 | 139 | ||
137 | return ( | 140 | return ( |
138 | - <View style={styles.container}> | 141 | + <View style={[styles.container, style]}> |
139 | <ListView | 142 | <ListView |
140 | - contentContainerStyle={styles.contentContainer} | 143 | + contentContainerStyle={[styles.contentContainer, style]} |
141 | enableEmptySections={true} | 144 | enableEmptySections={true} |
142 | dataSource={this.dataSource.cloneWithRows(this.state.filters)} | 145 | dataSource={this.dataSource.cloneWithRows(this.state.filters)} |
143 | renderRow={this._renderRow} | 146 | renderRow={this._renderRow} |
144 | renderSeparator={this._renderSeparator} | 147 | renderSeparator={this._renderSeparator} |
145 | scrollEnabled={false} | 148 | scrollEnabled={false} |
149 | + scrollsToTop={false} | ||
146 | /> | 150 | /> |
147 | </View> | 151 | </View> |
148 | ); | 152 | ); |
@@ -159,9 +163,9 @@ let styles = StyleSheet.create({ | @@ -159,9 +163,9 @@ let styles = StyleSheet.create({ | ||
159 | marginLeft: -1, | 163 | marginLeft: -1, |
160 | width: width + 2, | 164 | width: width + 2, |
161 | height: 37, | 165 | height: 37, |
166 | + borderTopColor: 'transparent', | ||
162 | borderBottomColor: '#e5e5e5', | 167 | borderBottomColor: '#e5e5e5', |
163 | borderWidth: 0.5, | 168 | borderWidth: 0.5, |
164 | - | ||
165 | }, | 169 | }, |
166 | contentContainer: { | 170 | contentContainer: { |
167 | flexDirection: 'row', | 171 | flexDirection: 'row', |
@@ -177,7 +181,8 @@ let styles = StyleSheet.create({ | @@ -177,7 +181,8 @@ let styles = StyleSheet.create({ | ||
177 | color: '#b0b0b0', | 181 | color: '#b0b0b0', |
178 | }, | 182 | }, |
179 | image: { | 183 | image: { |
180 | - | 184 | + marginTop: 2, |
185 | + marginLeft: 2, | ||
181 | }, | 186 | }, |
182 | separator: { | 187 | separator: { |
183 | width: 0.5, | 188 | width: 0.5, |
@@ -12,8 +12,10 @@ import ReactNative, { | @@ -12,8 +12,10 @@ import ReactNative, { | ||
12 | } from 'react-native'; | 12 | } from 'react-native'; |
13 | 13 | ||
14 | import SlicedImage from '../../../common/components/SlicedImage'; | 14 | import SlicedImage from '../../../common/components/SlicedImage'; |
15 | -import LoadingIndicator from '../../../common/components/LoadingIndicator'; | 15 | +import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator'; |
16 | import ProductListCell from './ProductListCell'; | 16 | import ProductListCell from './ProductListCell'; |
17 | +import ProductFilter from './ProductFilter'; | ||
18 | +import ProductShopCell from './ProductShopCell'; | ||
17 | 19 | ||
18 | export default class Search extends Component { | 20 | export default class Search extends Component { |
19 | 21 | ||
@@ -29,27 +31,76 @@ export default class Search extends Component { | @@ -29,27 +31,76 @@ export default class Search extends Component { | ||
29 | } | 31 | } |
30 | 32 | ||
31 | _renderRow(rowData, sectionID, rowID) { | 33 | _renderRow(rowData, sectionID, rowID) { |
34 | + switch (sectionID) { | ||
35 | + case 'shop': | ||
36 | + return ( | ||
37 | + <ProductShopCell | ||
38 | + key={'row' + rowID} | ||
39 | + data={rowData} | ||
40 | + /> | ||
41 | + ); | ||
42 | + case 'placeholder': | ||
43 | + return ( | ||
44 | + <View style={styles.separator}/> | ||
45 | + ); | ||
46 | + case 'filter': | ||
47 | + return ( | ||
48 | + <ProductFilter | ||
49 | + style={styles.filterContainer} | ||
50 | + onPressFilter={this.props.onPressFilter} | ||
51 | + /> | ||
52 | + ); | ||
53 | + | ||
54 | + case 'list': | ||
55 | + let paddingLeft = rowID % 2 == 1 ? rowMarginHorizontal / 2 : rowMarginHorizontal; | ||
56 | + let customStyle = rowID == 0 || rowID == 1 ? {paddingLeft, marginTop: 0} : {paddingLeft}; | ||
57 | + return ( | ||
58 | + <ProductListCell | ||
59 | + style={[styles.listContainer, customStyle]} | ||
60 | + key={'row' + rowID} | ||
61 | + rowID={rowID} | ||
62 | + data={rowData} | ||
63 | + /> | ||
64 | + ); | ||
65 | + default: | ||
66 | + return null; | ||
67 | + | ||
68 | + } | ||
32 | 69 | ||
33 | - return ( | ||
34 | - <ProductListCell | ||
35 | - key={'row' + rowID} | ||
36 | - rowID={rowID} | ||
37 | - data={rowData} | ||
38 | - /> | ||
39 | - ); | ||
40 | } | 70 | } |
41 | 71 | ||
42 | render() { | 72 | render() { |
43 | - let {list} = this.props; | 73 | + let {shop, list, isFetching, isLoadingMore, endReached} = this.props; |
74 | + let dataSource = { | ||
75 | + shop: shop.toArray(), | ||
76 | + filter: ['filter'], | ||
77 | + list: list.toArray(), | ||
78 | + } | ||
44 | 79 | ||
45 | return ( | 80 | return ( |
46 | <View style={styles.container}> | 81 | <View style={styles.container}> |
47 | <ListView | 82 | <ListView |
48 | contentContainerStyle={styles.contentContainer} | 83 | contentContainerStyle={styles.contentContainer} |
49 | enableEmptySections={true} | 84 | enableEmptySections={true} |
50 | - dataSource={this.dataSource.cloneWithRows(list.toArray())} | 85 | + dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)} |
51 | renderRow={this._renderRow} | 86 | renderRow={this._renderRow} |
52 | keyboardDismissMode={'on-drag'} | 87 | keyboardDismissMode={'on-drag'} |
88 | + onEndReached={() => { | ||
89 | + this.props.onEndReached && this.props.onEndReached(); | ||
90 | + }} | ||
91 | + renderFooter={()=>{ | ||
92 | + if (endReached) { | ||
93 | + return <LoadMoreIndicator | ||
94 | + isVisible={true} | ||
95 | + text={'暂无更多'} | ||
96 | + /> | ||
97 | + } else { | ||
98 | + return <LoadMoreIndicator | ||
99 | + isVisible={isLoadingMore} | ||
100 | + animating={isFetching} | ||
101 | + /> | ||
102 | + } | ||
103 | + }} | ||
53 | /> | 104 | /> |
54 | 105 | ||
55 | </View> | 106 | </View> |
@@ -66,13 +117,21 @@ let rowMarginHorizontal = (width - rowWidth * 2) / 3; | @@ -66,13 +117,21 @@ let rowMarginHorizontal = (width - rowWidth * 2) / 3; | ||
66 | let styles = StyleSheet.create({ | 117 | let styles = StyleSheet.create({ |
67 | container: { | 118 | container: { |
68 | flex: 1, | 119 | flex: 1, |
69 | - | ||
70 | backgroundColor: 'white', | 120 | backgroundColor: 'white', |
71 | }, | 121 | }, |
72 | contentContainer: { | 122 | contentContainer: { |
73 | flexDirection: 'row', | 123 | flexDirection: 'row', |
74 | flexWrap: 'wrap', | 124 | flexWrap: 'wrap', |
75 | - justifyContent: 'space-between', | ||
76 | - marginHorizontal: rowMarginHorizontal, | 125 | + }, |
126 | + filterContainer: { | ||
127 | + | ||
128 | + }, | ||
129 | + listContainer: { | ||
130 | + width: width / 2, | ||
131 | + }, | ||
132 | + separator: { | ||
133 | + width, | ||
134 | + height: 16, | ||
135 | + backgroundColor: '#f0f0f0', | ||
77 | }, | 136 | }, |
78 | }); | 137 | }); |
@@ -12,7 +12,8 @@ import ReactNative, { | @@ -12,7 +12,8 @@ import ReactNative, { | ||
12 | } from 'react-native'; | 12 | } from 'react-native'; |
13 | 13 | ||
14 | import SlicedImage from '../../../common/components/SlicedImage'; | 14 | import SlicedImage from '../../../common/components/SlicedImage'; |
15 | -import LoadingIndicator from '../../../common/components/LoadingIndicator'; | 15 | +import Tags from './Tags'; |
16 | + | ||
16 | 17 | ||
17 | export default class Search extends Component { | 18 | export default class Search extends Component { |
18 | 19 | ||
@@ -23,12 +24,29 @@ export default class Search extends Component { | @@ -23,12 +24,29 @@ export default class Search extends Component { | ||
23 | 24 | ||
24 | 25 | ||
25 | render() { | 26 | render() { |
26 | - let {rowID, data} = this.props; | ||
27 | - let url = data.get('default_images').replace('{width}', rowWidth).replace('{height}', imageHeight);; | 27 | + let {rowID, data, style} = this.props; |
28 | + let url = data.get('default_images').replace('{width}', rowWidth).replace('{height}', imageHeight); | ||
29 | + url = SlicedImage.getSlicedUrl(data.get('default_images'), 290, 386, 2); | ||
28 | return ( | 30 | return ( |
29 | - <View style={[styles.container]}> | ||
30 | - <Image style={styles.image} source={{uri: url}}/> | ||
31 | - <Text>{data.get('product_name')}</Text> | 31 | + <View style={[styles.container, style]}> |
32 | + <Tags/> | ||
33 | + <View style={styles.imageContainer}> | ||
34 | + <Image style={styles.image} source={{uri: url}}> | ||
35 | + <Image style={styles.almostSoldOutImage} source={require('../../images/tag/tip_jjsq.png')}/> | ||
36 | + <Image style={styles.soldOutImage} source={require('../../images/tag/outlet_sellout_bg.png')}/> | ||
37 | + </Image> | ||
38 | + | ||
39 | + </View> | ||
40 | + <View style={styles.nameContainer}> | ||
41 | + <Text style={styles.name} numberOfLines={2}>{data.get('product_name')}</Text> | ||
42 | + </View> | ||
43 | + <View style={styles.priceContainer}> | ||
44 | + <Text style={styles.nowPrice} numberOfLines={1}>{'¥' + data.get('sales_price')}</Text> | ||
45 | + <View style={styles.oldPriceContainer}> | ||
46 | + <Text style={styles.oldPrice} numberOfLines={1}>{'¥' + data.get('market_price')}</Text> | ||
47 | + <View style={styles.deleteLine}/> | ||
48 | + </View> | ||
49 | + </View> | ||
32 | </View> | 50 | </View> |
33 | ); | 51 | ); |
34 | } | 52 | } |
@@ -36,20 +54,26 @@ export default class Search extends Component { | @@ -36,20 +54,26 @@ export default class Search extends Component { | ||
36 | 54 | ||
37 | let {width, height} = Dimensions.get('window'); | 55 | let {width, height} = Dimensions.get('window'); |
38 | 56 | ||
39 | -const WIDTH_RATIO = width / 320; | ||
40 | -let rowWidth = Math.ceil(137.5 * WIDTH_RATIO); | ||
41 | -let rowHeight = Math.ceil(254 * WIDTH_RATIO); | ||
42 | -let rowMarginTop = Math.ceil(10 * WIDTH_RATIO); | 57 | +const DEVICE_WIDTH_RATIO = width / 320; |
58 | +let rowWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO); | ||
59 | +let rowHeight = Math.ceil(254 * DEVICE_WIDTH_RATIO); | ||
60 | +let rowMarginTop = Math.ceil(10 * DEVICE_WIDTH_RATIO); | ||
43 | 61 | ||
44 | const IMAGE_WIDTH = 145; | 62 | const IMAGE_WIDTH = 145; |
45 | const IMAGE_HEIGHT = 193; | 63 | const IMAGE_HEIGHT = 193; |
46 | const IMAGE_RATIO = IMAGE_HEIGHT / IMAGE_WIDTH; | 64 | const IMAGE_RATIO = IMAGE_HEIGHT / IMAGE_WIDTH; |
47 | -let imageTop = 14 * WIDTH_RATIO; | 65 | +let imageTop = 14 * DEVICE_WIDTH_RATIO; |
48 | let imageHeight = rowWidth * IMAGE_RATIO; | 66 | let imageHeight = rowWidth * IMAGE_RATIO; |
49 | 67 | ||
68 | +let almostSoldOutImageHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO); | ||
69 | +let almostSoldOutImageTop = imageHeight - almostSoldOutImageHeight; | ||
70 | + | ||
71 | +let nameMarginTop = Math.ceil(7 * DEVICE_WIDTH_RATIO); | ||
72 | +let nameHeight = Math.ceil(36 * DEVICE_WIDTH_RATIO); | ||
73 | + | ||
50 | let styles = StyleSheet.create({ | 74 | let styles = StyleSheet.create({ |
51 | container: { | 75 | container: { |
52 | - backgroundColor: 'gray', | 76 | + // backgroundColor: 'gray', |
53 | width: rowWidth, | 77 | width: rowWidth, |
54 | height: rowHeight, | 78 | height: rowHeight, |
55 | marginTop: rowMarginTop, | 79 | marginTop: rowMarginTop, |
@@ -59,18 +83,70 @@ let styles = StyleSheet.create({ | @@ -59,18 +83,70 @@ let styles = StyleSheet.create({ | ||
59 | height: rowHeight, | 83 | height: rowHeight, |
60 | 84 | ||
61 | }, | 85 | }, |
86 | + imageContainer: { | ||
87 | + width: rowWidth, | ||
88 | + height: imageHeight, | ||
89 | + backgroundColor: '#f0f0f0', | ||
90 | + }, | ||
62 | image: { | 91 | image: { |
63 | - top: imageTop, | 92 | + // top: imageTop, |
93 | + width: rowWidth, | ||
94 | + height: imageHeight, | ||
95 | + backgroundColor: '#f0f0f0', | ||
96 | + }, | ||
97 | + soldOutImage: { | ||
98 | + position: 'absolute', | ||
99 | + top: 0, | ||
100 | + left: 0, | ||
64 | width: rowWidth, | 101 | width: rowWidth, |
65 | height: imageHeight, | 102 | height: imageHeight, |
66 | }, | 103 | }, |
67 | - separator: { | ||
68 | - height: 15, | 104 | + almostSoldOutImage: { |
105 | + top: almostSoldOutImageTop, | ||
106 | + width: rowWidth, | ||
107 | + height: almostSoldOutImageHeight, | ||
108 | + backgroundColor: '#ff9e0d', | ||
109 | + }, | ||
110 | + nameContainer: { | ||
111 | + justifyContent: 'center', | ||
112 | + marginTop: nameMarginTop, | ||
113 | + width: rowWidth, | ||
114 | + height: nameHeight, | ||
115 | + // backgroundColor: 'red', | ||
116 | + }, | ||
117 | + name: { | ||
118 | + fontFamily: 'STHeitiSC-Light', | ||
119 | + fontSize: 12, | ||
120 | + color: '#444444', | ||
121 | + }, | ||
122 | + priceContainer: { | ||
123 | + flexDirection: 'row', | ||
124 | + }, | ||
125 | + nowPrice: { | ||
126 | + fontSize: 12, | ||
127 | + color: '#d0021b', | ||
128 | + }, | ||
129 | + oldPriceContainer: { | ||
130 | + // flex: 1, | ||
131 | + flexDirection: 'row', | ||
132 | + marginLeft: 5, | ||
133 | + // backgroundColor: 'red', | ||
134 | + }, | ||
135 | + oldPrice: { | ||
136 | + fontSize: 12, | ||
137 | + color: '#b0b0b0', | ||
138 | + height: 16, | ||
69 | }, | 139 | }, |
70 | - line: { | ||
71 | - marginHorizontal: 30, | ||
72 | - top: 10 , | ||
73 | - height: 1, | ||
74 | - backgroundColor: '#e5e5e5', | 140 | + deleteLine: { |
141 | + position: 'absolute', | ||
142 | + // flex: 1, | ||
143 | + top: (16 / 2) - 0.5, | ||
144 | + left: 0, | ||
145 | + right: 0, | ||
146 | + // marginLeft: 0, | ||
147 | + // marginRight: 0, | ||
148 | + // width: 50, | ||
149 | + height: 1, | ||
150 | + backgroundColor: '#b0b0b0', | ||
75 | }, | 151 | }, |
76 | }); | 152 | }); |
1 | +'use strict'; | ||
2 | + | ||
3 | +import React, {Component} from 'react'; | ||
4 | +import ReactNative, { | ||
5 | + View, | ||
6 | + Text, | ||
7 | + Image, | ||
8 | + StyleSheet, | ||
9 | + Dimensions, | ||
10 | + TouchableOpacity, | ||
11 | +} from 'react-native'; | ||
12 | + | ||
13 | +import SlicedImage from '../../../common/components/SlicedImage'; | ||
14 | + | ||
15 | +export default class ProductShopCell extends Component { | ||
16 | + | ||
17 | + constructor(props) { | ||
18 | + super(props); | ||
19 | + | ||
20 | + } | ||
21 | + | ||
22 | + | ||
23 | + render() { | ||
24 | + let {data} = this.props; | ||
25 | + // 品牌 | ||
26 | + let icon = data.get('brand_ico'); | ||
27 | + let name = data.get('brand_name'); | ||
28 | + // 店铺 | ||
29 | + if (data.get('shops_type') == 2) { | ||
30 | + icon = data.get('shop_logo'); | ||
31 | + name = data.get('shop_name'); | ||
32 | + } | ||
33 | + | ||
34 | + return ( | ||
35 | + <View style={styles.container}> | ||
36 | + <TouchableOpacity style={styles.content} onPress={() => { | ||
37 | + this.props.onPressShop && this.props.onPressShop(data); | ||
38 | + }}> | ||
39 | + <View style={styles.content}> | ||
40 | + <View style={styles.leftContainer}> | ||
41 | + <SlicedImage style={styles.icon} source={{uri: icon}}/> | ||
42 | + <Text style={styles.title}>{name}</Text> | ||
43 | + </View> | ||
44 | + <View style={styles.rightContainer}> | ||
45 | + <Text style={styles.desc}>进入店铺</Text> | ||
46 | + <Image style={styles.arrow} source={require('../../images/shared_next_icon.png')}/> | ||
47 | + </View> | ||
48 | + </View> | ||
49 | + </TouchableOpacity> | ||
50 | + <View style={styles.separator}/> | ||
51 | + </View> | ||
52 | + ); | ||
53 | + } | ||
54 | +} | ||
55 | + | ||
56 | +let {width, height} = Dimensions.get('window'); | ||
57 | + | ||
58 | +let styles = StyleSheet.create({ | ||
59 | + container: { | ||
60 | + width: width, | ||
61 | + height: 65, | ||
62 | + }, | ||
63 | + content: { | ||
64 | + flexDirection: 'row', | ||
65 | + alignItems: 'center', | ||
66 | + alignSelf: 'flex-start', | ||
67 | + justifyContent: 'space-between', | ||
68 | + width: width, | ||
69 | + height: 49, | ||
70 | + }, | ||
71 | + leftContainer: { | ||
72 | + flexDirection: 'row', | ||
73 | + alignItems: 'center', | ||
74 | + height: 49, | ||
75 | + }, | ||
76 | + icon: { | ||
77 | + marginLeft: 5, | ||
78 | + width: 50, | ||
79 | + height: 49, | ||
80 | + resizeMode: 'contain', | ||
81 | + }, | ||
82 | + title: { | ||
83 | + marginLeft: 5, | ||
84 | + width: 150, | ||
85 | + fontSize: 15, | ||
86 | + }, | ||
87 | + rightContainer: { | ||
88 | + flexDirection: 'row', | ||
89 | + alignItems: 'center', | ||
90 | + alignSelf: 'flex-end', | ||
91 | + height: 49, | ||
92 | + }, | ||
93 | + desc: { | ||
94 | + marginRight: 10 , | ||
95 | + width: 50, | ||
96 | + fontSize: 12, | ||
97 | + color: '#b0b0b0', | ||
98 | + }, | ||
99 | + arrow: { | ||
100 | + right: 5, | ||
101 | + width: 20, | ||
102 | + height: 49, | ||
103 | + resizeMode: 'contain', | ||
104 | + }, | ||
105 | + separator: { | ||
106 | + position: 'absolute', | ||
107 | + left: 0, | ||
108 | + top: 49, | ||
109 | + width, | ||
110 | + height: 16, | ||
111 | + backgroundColor: '#f0f0f0', | ||
112 | + }, | ||
113 | +}); |
@@ -25,7 +25,6 @@ export default class SearchResult extends React.Component { | @@ -25,7 +25,6 @@ export default class SearchResult extends React.Component { | ||
25 | 25 | ||
26 | return ( | 26 | return ( |
27 | <View style={styles.container}> | 27 | <View style={styles.container}> |
28 | - <ProductFilter/> | ||
29 | <ProductList | 28 | <ProductList |
30 | list={list} | 29 | list={list} |
31 | /> | 30 | /> |
js/search/components/search/Tags.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import React from 'react'; | ||
4 | +import ReactNative from 'react-native'; | ||
5 | + | ||
6 | +const { | ||
7 | + View, | ||
8 | + Image, | ||
9 | + Text, | ||
10 | + ListView, | ||
11 | + Dimensions, | ||
12 | + StyleSheet, | ||
13 | +} = ReactNative; | ||
14 | + | ||
15 | +export default class Tags extends React.Component { | ||
16 | + | ||
17 | + constructor(props) { | ||
18 | + super (props); | ||
19 | + | ||
20 | + this.config = { | ||
21 | + is_discount: { | ||
22 | + image: require('../../images/tag/tip_sale.png'), | ||
23 | + width: 30, | ||
24 | + }, // YH_ProductTagTypeSale | ||
25 | + resale: { | ||
26 | + image: require('../../images/tag/tip_zdz.png'), | ||
27 | + width: 45, | ||
28 | + }, // YH_ProductTagTypeReSale | ||
29 | + 'mid-year': { | ||
30 | + image: require('../../images/tag/tip_nzrc.png'), | ||
31 | + width: 45, | ||
32 | + }, // YH_ProductTagTypeSaleMiddle | ||
33 | + 'year-end': { | ||
34 | + image: require('../../images/tag/tip_nzdc.png'), | ||
35 | + width: 45, | ||
36 | + }, // YH_ProductTagTypeSaleHot | ||
37 | + is_new: { | ||
38 | + image: require('../../images/tag/tip_new.png'), | ||
39 | + width: 30, | ||
40 | + }, // YH_ProductTagTypeNew | ||
41 | + is_yohood: { | ||
42 | + image: require('../../images/tag/tip_xpj.png'), | ||
43 | + width: 45, | ||
44 | + }, // YH_ProductTagTypeYohood | ||
45 | + is_limited: { | ||
46 | + image: require('../../images/tag/tip_xl_product.png'), | ||
47 | + width: 30, | ||
48 | + }, // YH_ProductTagTypeLimited | ||
49 | + is_in_stock: { | ||
50 | + image: require('../../images/tag/tip_gnzf.png'), | ||
51 | + width: 45, | ||
52 | + }, // YH_ProductTagTypeInland | ||
53 | + is_deposit_advance: { | ||
54 | + image: require('../../images/tag/tip_advance.png'), | ||
55 | + width: 30, | ||
56 | + }, // YH_ProductTagTypeDeposit | ||
57 | + default: { | ||
58 | + image: '', | ||
59 | + width: 45, | ||
60 | + }, | ||
61 | + }; | ||
62 | + | ||
63 | + this._renderRow = this._renderRow.bind(this); | ||
64 | + | ||
65 | + this.dataSource = new ListView.DataSource({ | ||
66 | + rowHasChanged: (r1, r2) => r1 != r2, | ||
67 | + }); | ||
68 | + } | ||
69 | + | ||
70 | + _renderRow(rowData, sectionID, rowID) { | ||
71 | + let item = this.config[rowData]; | ||
72 | + if (!item) { | ||
73 | + return null; | ||
74 | + } | ||
75 | + | ||
76 | + let width = Math.ceil(item.width * DEVICE_WIDTH_RATIO); | ||
77 | + let marginLeft = rowID == 0 ? 0 : 2; | ||
78 | + let iconStyle = {width, height: tagHeight, marginLeft}; | ||
79 | + | ||
80 | + return ( | ||
81 | + <Image style={[styles.icon, iconStyle]} source={item.image}/> | ||
82 | + ); | ||
83 | + } | ||
84 | + | ||
85 | + render() { | ||
86 | + | ||
87 | + let {style} = this.props; | ||
88 | + let tags = ['is_discount', 'resale', ]; | ||
89 | + | ||
90 | + return ( | ||
91 | + <View style={[styles.container]}> | ||
92 | + <ListView | ||
93 | + style={[styles.container]} | ||
94 | + contentContainerStyle={[styles.contentContainer]} | ||
95 | + enableEmptySections={true} | ||
96 | + dataSource={this.dataSource.cloneWithRows(tags)} | ||
97 | + renderRow={this._renderRow} | ||
98 | + scrollEnabled={false} | ||
99 | + scrollsToTop={false} | ||
100 | + horizontal={true} | ||
101 | + showsHorizontalScrollIndicator={false} | ||
102 | + /> | ||
103 | + </View> | ||
104 | + ); | ||
105 | + } | ||
106 | +} | ||
107 | + | ||
108 | +let {width, height} = Dimensions.get('window'); | ||
109 | + | ||
110 | +const DEVICE_WIDTH_RATIO = width / 320; | ||
111 | +let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO); | ||
112 | + | ||
113 | +let styles = StyleSheet.create({ | ||
114 | + container: { | ||
115 | + | ||
116 | + }, | ||
117 | + contentContainer: { | ||
118 | + height: tagHeight, | ||
119 | + }, | ||
120 | + icon: { | ||
121 | + resizeMode: 'contain', | ||
122 | + }, | ||
123 | +}); |
@@ -7,11 +7,14 @@ export default keyMirror({ | @@ -7,11 +7,14 @@ export default keyMirror({ | ||
7 | 7 | ||
8 | SET_KEYWORD: null, | 8 | SET_KEYWORD: null, |
9 | SET_SEARCH_STATUS: null, | 9 | SET_SEARCH_STATUS: null, |
10 | + SET_FILTER: null, | ||
10 | 11 | ||
11 | SEARCH_REQUEST: null, | 12 | SEARCH_REQUEST: null, |
12 | SEARCH_SUCCESS: null, | 13 | SEARCH_SUCCESS: null, |
13 | SEARCH_FAILURE: null, | 14 | SEARCH_FAILURE: null, |
14 | 15 | ||
16 | + RESET_LIST_PAGE_INFO: null, | ||
17 | + | ||
15 | JUMP_URL_REQUEST: null, | 18 | JUMP_URL_REQUEST: null, |
16 | JUMP_URL_SUCCESS: null, | 19 | JUMP_URL_SUCCESS: null, |
17 | JUMP_URL_FAILURE: null, | 20 | JUMP_URL_FAILURE: null, |
@@ -18,6 +18,8 @@ import * as searchActions from '../reducers/search/searchActions'; | @@ -18,6 +18,8 @@ import * as searchActions from '../reducers/search/searchActions'; | ||
18 | import SearchKeyword from '../components/search/SearchKeyword'; | 18 | import SearchKeyword from '../components/search/SearchKeyword'; |
19 | import FuzzySearch from '../components/search/FuzzySearch'; | 19 | import FuzzySearch from '../components/search/FuzzySearch'; |
20 | import SearchResult from '../components/search/SearchResult'; | 20 | import SearchResult from '../components/search/SearchResult'; |
21 | +import ProductList from '../components/search/ProductList'; | ||
22 | +import LoadingIndicator from '../../common/components/LoadingIndicator'; | ||
21 | 23 | ||
22 | const actions = [ | 24 | const actions = [ |
23 | searchActions, | 25 | searchActions, |
@@ -48,6 +50,8 @@ class SearchContainer extends Component { | @@ -48,6 +50,8 @@ class SearchContainer extends Component { | ||
48 | 50 | ||
49 | this._onPressKeyword = this._onPressKeyword.bind(this); | 51 | this._onPressKeyword = this._onPressKeyword.bind(this); |
50 | this._onPressClearHistory = this._onPressClearHistory.bind(this); | 52 | this._onPressClearHistory = this._onPressClearHistory.bind(this); |
53 | + this._onPressFilter = this._onPressFilter.bind(this); | ||
54 | + this._onEndReached = this._onEndReached.bind(this); | ||
51 | 55 | ||
52 | this.subscription = NativeAppEventEmitter.addListener( | 56 | this.subscription = NativeAppEventEmitter.addListener( |
53 | "SearchKeywordDidChangeEvent", | 57 | "SearchKeywordDidChangeEvent", |
@@ -59,6 +63,7 @@ class SearchContainer extends Component { | @@ -59,6 +63,7 @@ class SearchContainer extends Component { | ||
59 | this.subscription2 = NativeAppEventEmitter.addListener( | 63 | this.subscription2 = NativeAppEventEmitter.addListener( |
60 | "SearchButtonDidClickEvent", | 64 | "SearchButtonDidClickEvent", |
61 | (event) => { | 65 | (event) => { |
66 | + this.props.actions.resetListPageInfo(); | ||
62 | this.props.actions.searchButtonPressed(event.keyword); | 67 | this.props.actions.searchButtonPressed(event.keyword); |
63 | } | 68 | } |
64 | ); | 69 | ); |
@@ -76,6 +81,7 @@ class SearchContainer extends Component { | @@ -76,6 +81,7 @@ class SearchContainer extends Component { | ||
76 | } | 81 | } |
77 | 82 | ||
78 | _onPressKeyword(keyword) { | 83 | _onPressKeyword(keyword) { |
84 | + this.props.actions.resetListPageInfo(); | ||
79 | this.props.actions.searchButtonPressed(keyword); | 85 | this.props.actions.searchButtonPressed(keyword); |
80 | } | 86 | } |
81 | 87 | ||
@@ -83,29 +89,47 @@ class SearchContainer extends Component { | @@ -83,29 +89,47 @@ class SearchContainer extends Component { | ||
83 | this.props.actions.clearSearchHistory(); | 89 | this.props.actions.clearSearchHistory(); |
84 | } | 90 | } |
85 | 91 | ||
92 | + _onPressFilter(value) { | ||
93 | + this.props.actions.resetListPageInfo(); | ||
94 | + this.props.actions.setFilter(value); | ||
95 | + this.props.actions.searchProductList(this.props.search.keyword, true); | ||
96 | + } | ||
97 | + | ||
98 | + _onEndReached() { | ||
99 | + this.props.actions.searchProductList(this.props.search.keyword); | ||
100 | + } | ||
86 | 101 | ||
87 | _renderSearch() { | 102 | _renderSearch() { |
88 | - let {status, keyword, placeholder, searchHistory, hotKeyword, fuzzySearch, productList} = this.props.search; | 103 | + let {status, keyword, placeholder, searchHistory, hotKeyword, fuzzySearch, jumpUrl, productList} = this.props.search; |
89 | if (status == 0) { | 104 | if (status == 0) { |
90 | return ( | 105 | return ( |
91 | <SearchKeyword | 106 | <SearchKeyword |
92 | - history={searchHistory.list} | ||
93 | - hot={hotKeyword.list} | ||
94 | - onPressKeyword={this._onPressKeyword} | ||
95 | - onPressClearHistory={this._onPressClearHistory} | 107 | + history={searchHistory.list} |
108 | + hot={hotKeyword.list} | ||
109 | + onPressKeyword={this._onPressKeyword} | ||
110 | + onPressClearHistory={this._onPressClearHistory} | ||
96 | /> | 111 | /> |
97 | ); | 112 | ); |
98 | } else if (status == 1) { | 113 | } else if (status == 1) { |
99 | return ( | 114 | return ( |
100 | <FuzzySearch | 115 | <FuzzySearch |
101 | - list={fuzzySearch.list} | ||
102 | - onPressKeyword={this._onPressKeyword} | 116 | + list={fuzzySearch.list} |
117 | + onPressKeyword={this._onPressKeyword} | ||
103 | /> | 118 | /> |
104 | ); | 119 | ); |
105 | } else if (status == 2) { | 120 | } else if (status == 2) { |
121 | + console.log('currentPage: ' + productList.currentPage) | ||
122 | + console.log('isFetching: ' + productList.isFetching) | ||
123 | + let isLoadingMore = productList.isFetching && productList.currentPage > 0; | ||
106 | return ( | 124 | return ( |
107 | - <SearchResult | ||
108 | - list={productList.list} | 125 | + <ProductList |
126 | + shop={productList.shopOrBrand} | ||
127 | + list={productList.list} | ||
128 | + isFetching={productList.isFetching} | ||
129 | + isLoadingMore={isLoadingMore} | ||
130 | + endReached={productList.endReached} | ||
131 | + onPressFilter={this._onPressFilter} | ||
132 | + onEndReached={this._onEndReached} | ||
109 | /> | 133 | /> |
110 | ); | 134 | ); |
111 | } | 135 | } |
@@ -114,9 +138,15 @@ class SearchContainer extends Component { | @@ -114,9 +138,15 @@ class SearchContainer extends Component { | ||
114 | } | 138 | } |
115 | 139 | ||
116 | render() { | 140 | render() { |
141 | + let {jumpUrl, productList} = this.props.search; | ||
142 | + let showLoading = jumpUrl.isFetching || (productList.isFetching && productList.currentPage == 0); | ||
117 | return ( | 143 | return ( |
118 | <View style={styles.container}> | 144 | <View style={styles.container}> |
119 | {this._renderSearch()} | 145 | {this._renderSearch()} |
146 | + | ||
147 | + <LoadingIndicator | ||
148 | + isVisible={showLoading} | ||
149 | + /> | ||
120 | </View> | 150 | </View> |
121 | ); | 151 | ); |
122 | } | 152 | } |

29.2 KB

29.2 KB
js/search/images/tag/tip@2x_yohood.png
0 → 100644

1.28 KB
js/search/images/tag/tip@3x_yohood.png
0 → 100644

1.45 KB
js/search/images/tag/tip_advance@2x.png
0 → 100644

743 Bytes
js/search/images/tag/tip_advance@3x.png
0 → 100644

1.09 KB
js/search/images/tag/tip_gnzf@2x.png
0 → 100644

1.31 KB
js/search/images/tag/tip_gnzf@3x.png
0 → 100644

1.91 KB
js/search/images/tag/tip_jjsq@2x.png
0 → 100644

1.45 KB
js/search/images/tag/tip_jjsq@3x.png
0 → 100644

2.19 KB
js/search/images/tag/tip_jjsq_s@2x.png
0 → 100644

1.33 KB
js/search/images/tag/tip_jjsq_s@3x.png
0 → 100644

1.98 KB
js/search/images/tag/tip_new@2x.png
0 → 100644

814 Bytes
js/search/images/tag/tip_new@3x.png
0 → 100644

1.06 KB
js/search/images/tag/tip_nzdc@2x.png
0 → 100644

1.29 KB
js/search/images/tag/tip_nzdc@3x.png
0 → 100644

1.94 KB
js/search/images/tag/tip_nzrc@2x.png
0 → 100644

1.16 KB
js/search/images/tag/tip_nzrc@3x.png
0 → 100644

1.73 KB
js/search/images/tag/tip_pntk@2x.png
0 → 100644

1.51 KB
js/search/images/tag/tip_pntk@3x.png
0 → 100644

2.21 KB
js/search/images/tag/tip_sale@2x.png
0 → 100644

752 Bytes
js/search/images/tag/tip_sale@3x.png
0 → 100644

1 KB
js/search/images/tag/tip_xl_product@2x.png
0 → 100644

789 Bytes
js/search/images/tag/tip_xl_product@3x.png
0 → 100644

1.07 KB
js/search/images/tag/tip_xpj@2x.png
0 → 100644

1.24 KB
js/search/images/tag/tip_xpj@3x.png
0 → 100644

1.92 KB
js/search/images/tag/tip_zdz@2x.png
0 → 100644

1.02 KB
js/search/images/tag/tip_zdz@3x.png
0 → 100644

1.54 KB
@@ -6,9 +6,11 @@ import SearchService from '../../services/SearchService'; | @@ -6,9 +6,11 @@ import SearchService from '../../services/SearchService'; | ||
6 | const { | 6 | const { |
7 | SET_KEYWORD, | 7 | SET_KEYWORD, |
8 | SET_SEARCH_STATUS, | 8 | SET_SEARCH_STATUS, |
9 | + SET_FILTER, | ||
9 | SEARCH_REQUEST, | 10 | SEARCH_REQUEST, |
10 | SEARCH_SUCCESS, | 11 | SEARCH_SUCCESS, |
11 | SEARCH_FAILURE, | 12 | SEARCH_FAILURE, |
13 | + RESET_LIST_PAGE_INFO, | ||
12 | JUMP_URL_REQUEST, | 14 | JUMP_URL_REQUEST, |
13 | JUMP_URL_SUCCESS, | 15 | JUMP_URL_SUCCESS, |
14 | JUMP_URL_FAILURE, | 16 | JUMP_URL_FAILURE, |
@@ -31,6 +33,7 @@ const { | @@ -31,6 +33,7 @@ const { | ||
31 | 33 | ||
32 | export function searchKeywordChanged(keyword) { | 34 | export function searchKeywordChanged(keyword) { |
33 | return (dispatch, getState) => { | 35 | return (dispatch, getState) => { |
36 | + console.log(keyword) | ||
34 | let status = 0; | 37 | let status = 0; |
35 | if (keyword) { | 38 | if (keyword) { |
36 | status = 1; | 39 | status = 1; |
@@ -49,16 +52,13 @@ export function searchButtonPressed(keyword) { | @@ -49,16 +52,13 @@ export function searchButtonPressed(keyword) { | ||
49 | if (!keyword) { | 52 | if (!keyword) { |
50 | let {app, search} = getState(); | 53 | let {app, search} = getState(); |
51 | keyword = search.placeholder | 54 | keyword = search.placeholder |
52 | - dispatch(setKeyword(keyword)); | ||
53 | } | 55 | } |
54 | - | 56 | + dispatch(setKeyword(keyword)); |
55 | dispatch(insertSearchHistory(keyword)); | 57 | dispatch(insertSearchHistory(keyword)); |
56 | 58 | ||
57 | ReactNative.NativeModules.YH_SearchHelper.setSearchKeyword(keyword); | 59 | ReactNative.NativeModules.YH_SearchHelper.setSearchKeyword(keyword); |
58 | ReactNative.NativeModules.YH_SearchHelper.resignSearchBar(); | 60 | ReactNative.NativeModules.YH_SearchHelper.resignSearchBar(); |
59 | 61 | ||
60 | - // let status = 2; | ||
61 | - // dispatch(setSearchStatus(status)); | ||
62 | dispatch(jumpUrl(keyword)); | 62 | dispatch(jumpUrl(keyword)); |
63 | }; | 63 | }; |
64 | } | 64 | } |
@@ -77,6 +77,19 @@ export function setSearchStatus(status) { | @@ -77,6 +77,19 @@ export function setSearchStatus(status) { | ||
77 | }; | 77 | }; |
78 | } | 78 | } |
79 | 79 | ||
80 | +export function setFilter(value) { | ||
81 | + return { | ||
82 | + type: SET_FILTER, | ||
83 | + payload: value | ||
84 | + }; | ||
85 | +} | ||
86 | + | ||
87 | +export function resetListPageInfo() { | ||
88 | + return { | ||
89 | + type: RESET_LIST_PAGE_INFO, | ||
90 | + } | ||
91 | +} | ||
92 | + | ||
80 | export function searchRequest() { | 93 | export function searchRequest() { |
81 | return { | 94 | return { |
82 | type: SEARCH_REQUEST, | 95 | type: SEARCH_REQUEST, |
@@ -97,29 +110,45 @@ export function searchFailure(error) { | @@ -97,29 +110,45 @@ export function searchFailure(error) { | ||
97 | }; | 110 | }; |
98 | } | 111 | } |
99 | 112 | ||
100 | -export function searchProductList(keyword, uid, sourcePage) { | 113 | +export function searchProductList(keyword, reload=false) { |
101 | return (dispatch, getState) => { | 114 | return (dispatch, getState) => { |
102 | let {app, search} = getState(); | 115 | let {app, search} = getState(); |
103 | - // if (search.productList.isFetching) { | ||
104 | - // return; | ||
105 | - // } | 116 | + let {productList} = search; |
117 | + if (reload) { | ||
118 | + | ||
119 | + } else { | ||
120 | + if (productList.isFetching || productList.endReached || productList.error) { | ||
121 | + return; | ||
122 | + } | ||
123 | + } | ||
106 | 124 | ||
107 | - let fetchList = (keyword, order, uid, page, sourcePage) => { | 125 | + let fetchList = (keyword, order, uid, page, pageSize, sourcePage) => { |
108 | dispatch(searchRequest()); | 126 | dispatch(searchRequest()); |
109 | - return new SearchService(app.host).searchProductList(keyword, order, uid, page, sourcePage) | 127 | + return new SearchService(app.host).searchProductList(keyword, order, uid, page, pageSize, sourcePage) |
110 | .then(json => { | 128 | .then(json => { |
129 | + let payload = parseProductList(json); | ||
130 | + payload.endReached = payload.currentPage == payload.pageCount; | ||
131 | + | ||
132 | + if (productList.currentPage > 1) { | ||
133 | + let oldList = productList.list.toJS(); | ||
134 | + let list = [...oldList, ...payload.list]; | ||
135 | + payload.list = list; | ||
136 | + } | ||
137 | + | ||
111 | dispatch(setSearchStatus(2)); | 138 | dispatch(setSearchStatus(2)); |
112 | - dispatch(searchSuccess(json.product_list)); | 139 | + dispatch(searchSuccess(payload)); |
113 | }) | 140 | }) |
114 | .catch(error => { | 141 | .catch(error => { |
115 | dispatch(searchFailure(error)); | 142 | dispatch(searchFailure(error)); |
116 | }); | 143 | }); |
117 | } | 144 | } |
118 | 145 | ||
146 | + | ||
119 | let uid = 0; | 147 | let uid = 0; |
120 | let sourcePage = ''; | 148 | let sourcePage = ''; |
121 | - let order = 's_n_desc'; | ||
122 | - let page = 1; | 149 | + let order = productList.filter; |
150 | + let page = productList.currentPage + 1; | ||
151 | + let pageSize = productList.pageSize; | ||
123 | ReactNative.NativeModules.YH_CommonHelper.sourcePage('YH_SearchProListVC') | 152 | ReactNative.NativeModules.YH_CommonHelper.sourcePage('YH_SearchProListVC') |
124 | .then(data => { | 153 | .then(data => { |
125 | sourcePage = data; | 154 | sourcePage = data; |
@@ -127,14 +156,43 @@ export function searchProductList(keyword, uid, sourcePage) { | @@ -127,14 +156,43 @@ export function searchProductList(keyword, uid, sourcePage) { | ||
127 | }) | 156 | }) |
128 | .then(data => { | 157 | .then(data => { |
129 | uid = data; | 158 | uid = data; |
130 | - fetchList(keyword, order, uid, page, sourcePage); | 159 | + fetchList(keyword, order, uid, page, pageSize, sourcePage); |
131 | }) | 160 | }) |
132 | .catch(error => { | 161 | .catch(error => { |
133 | - fetchList(keyword, order, uid, page, sourcePage); | 162 | + fetchList(keyword, order, uid, page, pageSize, sourcePage); |
134 | }); | 163 | }); |
135 | } | 164 | } |
136 | } | 165 | } |
137 | 166 | ||
167 | +function parseProductList(json) { | ||
168 | + let currentPage = json && json.page ? json.page : 1; | ||
169 | + let pageCount = json && json.page_total ? json.page_total : 0; | ||
170 | + let total = json && json.total ? json.total : 0; | ||
171 | + | ||
172 | + let shopOrBrand = []; | ||
173 | + if (currentPage == 1) { | ||
174 | + shopOrBrand = json && json.shop ? json.shop : []; | ||
175 | + if (!shopOrBrand || shopOrBrand.length == 0) { | ||
176 | + let brand = json && json.brand; | ||
177 | + if (brand) { | ||
178 | + shopOrBrand.push(brand); | ||
179 | + } | ||
180 | + } | ||
181 | + } | ||
182 | + | ||
183 | + shopOrBrand = shopOrBrand ? shopOrBrand : []; | ||
184 | + | ||
185 | + let list = json && json.product_list ? json.product_list : []; | ||
186 | + | ||
187 | + return { | ||
188 | + list, | ||
189 | + shopOrBrand, | ||
190 | + currentPage, | ||
191 | + pageCount, | ||
192 | + total, | ||
193 | + }; | ||
194 | +} | ||
195 | + | ||
138 | export function jumpUrlRequest() { | 196 | export function jumpUrlRequest() { |
139 | return { | 197 | return { |
140 | type: JUMP_URL_REQUEST, | 198 | type: JUMP_URL_REQUEST, |
@@ -172,12 +230,12 @@ export function jumpUrl(keyword) { | @@ -172,12 +230,12 @@ export function jumpUrl(keyword) { | ||
172 | if (jumpUrl) { | 230 | if (jumpUrl) { |
173 | ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(jumpUrl); | 231 | ReactNative.NativeModules.YH_CommonHelper.jumpWithUrl(jumpUrl); |
174 | } else { | 232 | } else { |
175 | - dispatch(searchProductList(keyword, uid, sourcePage)); | 233 | + dispatch(searchProductList(keyword, true)); |
176 | } | 234 | } |
177 | }) | 235 | }) |
178 | .catch(error => { | 236 | .catch(error => { |
179 | dispatch(jumpUrlFailure(error)); | 237 | dispatch(jumpUrlFailure(error)); |
180 | - dispatch(searchProductList(keyword, uid, sourcePage)); | 238 | + dispatch(searchProductList(keyword, true)); |
181 | }); | 239 | }); |
182 | } | 240 | } |
183 | 241 |
@@ -28,6 +28,12 @@ let InitialState = Record({ | @@ -28,6 +28,12 @@ let InitialState = Record({ | ||
28 | isFetching: false, | 28 | isFetching: false, |
29 | error: null, | 29 | error: null, |
30 | list: List(), | 30 | list: List(), |
31 | + shopOrBrand: List(), | ||
32 | + filter: 's_n_desc', | ||
33 | + currentPage: 0, | ||
34 | + pageCount: 0, | ||
35 | + pageSize: 6,//60, | ||
36 | + total: 0, | ||
31 | endReached: false, | 37 | endReached: false, |
32 | })), | 38 | })), |
33 | }); | 39 | }); |
@@ -6,9 +6,11 @@ import Immutable, {Map} from 'immutable'; | @@ -6,9 +6,11 @@ import Immutable, {Map} from 'immutable'; | ||
6 | const { | 6 | const { |
7 | SET_KEYWORD, | 7 | SET_KEYWORD, |
8 | SET_SEARCH_STATUS, | 8 | SET_SEARCH_STATUS, |
9 | + SET_FILTER, | ||
9 | SEARCH_REQUEST, | 10 | SEARCH_REQUEST, |
10 | SEARCH_SUCCESS, | 11 | SEARCH_SUCCESS, |
11 | SEARCH_FAILURE, | 12 | SEARCH_FAILURE, |
13 | + RESET_LIST_PAGE_INFO, | ||
12 | JUMP_URL_REQUEST, | 14 | JUMP_URL_REQUEST, |
13 | JUMP_URL_SUCCESS, | 15 | JUMP_URL_SUCCESS, |
14 | JUMP_URL_FAILURE, | 16 | JUMP_URL_FAILURE, |
@@ -41,15 +43,44 @@ export default function searchReducer(state=initialState, action) { | @@ -41,15 +43,44 @@ export default function searchReducer(state=initialState, action) { | ||
41 | return state.set('status', action.payload); | 43 | return state.set('status', action.payload); |
42 | } | 44 | } |
43 | 45 | ||
46 | + case SET_FILTER: { | ||
47 | + return state.setIn(['productList', 'filter'], action.payload); | ||
48 | + } | ||
49 | + | ||
50 | + case RESET_LIST_PAGE_INFO: { | ||
51 | + return state.setIn(['productList', 'currentPage'], 0) | ||
52 | + .setIn(['productList', 'pageCount'], 0) | ||
53 | + .setIn(['productList', 'total'], 0) | ||
54 | + .setIn(['productList', 'endReached'], false); | ||
55 | + } | ||
56 | + | ||
44 | case SEARCH_REQUEST: { | 57 | case SEARCH_REQUEST: { |
45 | return state.setIn(['productList', 'isFetching'], true) | 58 | return state.setIn(['productList', 'isFetching'], true) |
46 | .setIn(['productList', 'error'], null); | 59 | .setIn(['productList', 'error'], null); |
47 | } | 60 | } |
48 | 61 | ||
49 | case SEARCH_SUCCESS: { | 62 | case SEARCH_SUCCESS: { |
50 | - return state.setIn(['productList', 'isFetching'], false) | 63 | + let { |
64 | + list, | ||
65 | + shopOrBrand, | ||
66 | + currentPage, | ||
67 | + pageCount, | ||
68 | + total, | ||
69 | + endReached, | ||
70 | + } = action.payload; | ||
71 | + | ||
72 | + let newState = state.setIn(['productList', 'isFetching'], false) | ||
51 | .setIn(['productList', 'error'], null) | 73 | .setIn(['productList', 'error'], null) |
52 | - .setIn(['productList', 'list'], Immutable.fromJS(action.payload)); | 74 | + .setIn(['productList', 'list'], Immutable.fromJS(list)) |
75 | + .setIn(['productList', 'currentPage'], currentPage) | ||
76 | + .setIn(['productList', 'pageCount'], pageCount) | ||
77 | + .setIn(['productList', 'total'], total) | ||
78 | + .setIn(['productList', 'endReached'], endReached); | ||
79 | + if (currentPage == 1) { | ||
80 | + newState = newState.setIn(['productList', 'shopOrBrand'], Immutable.fromJS(shopOrBrand)); | ||
81 | + } | ||
82 | + | ||
83 | + return newState; | ||
53 | } | 84 | } |
54 | 85 | ||
55 | case SEARCH_FAILURE: { | 86 | case SEARCH_FAILURE: { |
@@ -63,12 +63,13 @@ export default class SearchService { | @@ -63,12 +63,13 @@ export default class SearchService { | ||
63 | }); | 63 | }); |
64 | } | 64 | } |
65 | 65 | ||
66 | - async searchProductList(query='', order='s_n_desc', uid=0, page=1, fromPage='', limit=60, v=7) { | 66 | + async searchProductList(query='', order='s_n_desc', uid=0, page=1, limit=60, fromPage='', v=7) { |
67 | return await this.api.get({ | 67 | return await this.api.get({ |
68 | url: '', | 68 | url: '', |
69 | body: { | 69 | body: { |
70 | method: 'app.search.li', | 70 | method: 'app.search.li', |
71 | query, | 71 | query, |
72 | + order, | ||
72 | uid, | 73 | uid, |
73 | page, | 74 | page, |
74 | limit, | 75 | limit, |
-
Please register or login to post a comment