Showing
7 changed files
with
395 additions
and
3 deletions
@@ -4,6 +4,8 @@ import React, {Component} from 'react'; | @@ -4,6 +4,8 @@ import React, {Component} from 'react'; | ||
4 | import Immutable, {Map} from 'immutable'; | 4 | import Immutable, {Map} from 'immutable'; |
5 | import DetailBrand from './DetailBrand'; | 5 | import DetailBrand from './DetailBrand'; |
6 | import OtherArticle from './OtherArticle'; | 6 | import OtherArticle from './OtherArticle'; |
7 | +import SingleImage from './SingleImage'; | ||
8 | +import DetailText from './DetailText'; | ||
7 | 9 | ||
8 | import ReactNative, { | 10 | import ReactNative, { |
9 | View, | 11 | View, |
@@ -43,9 +45,33 @@ export default class Detail extends Component { | @@ -43,9 +45,33 @@ export default class Detail extends Component { | ||
43 | renderRow(rowData,sectionID,rowID,highlightRow) { | 45 | renderRow(rowData,sectionID,rowID,highlightRow) { |
44 | 46 | ||
45 | if (sectionID == 'detailList') { | 47 | if (sectionID == 'detailList') { |
46 | - return ( | ||
47 | - <Text>aaaaaa</Text> | ||
48 | - ); | 48 | + let template_name = rowData.get('template_name'); |
49 | + if (template_name == 'text') { | ||
50 | + return ( | ||
51 | + <DetailText resource={rowData}/> | ||
52 | + ); | ||
53 | + }else if (template_name == 'single_image') { | ||
54 | + return ( | ||
55 | + <SingleImage resource={rowData}/> | ||
56 | + ); | ||
57 | + }else if (template_name == 'small_image') { | ||
58 | + return ( | ||
59 | + <Text>small_image</Text> | ||
60 | + ); | ||
61 | + }else if (template_name == 'weixinPublic') { | ||
62 | + return ( | ||
63 | + <Text>weixinPublic</Text> | ||
64 | + ); | ||
65 | + }else if (template_name == 'collocation') { | ||
66 | + return ( | ||
67 | + <Text>collocation</Text> | ||
68 | + ); | ||
69 | + }else if (template_name == 'moreLink') { | ||
70 | + return ( | ||
71 | + <Text>moreLink</Text> | ||
72 | + ); | ||
73 | + } | ||
74 | + | ||
49 | }else if (sectionID == 'detailBrand') { | 75 | }else if (sectionID == 'detailBrand') { |
50 | return ( | 76 | return ( |
51 | <DetailBrand resource={rowData}/> | 77 | <DetailBrand resource={rowData}/> |
js/guang/components/detail/DetailText.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import React from 'react'; | ||
4 | +import ReactNative from 'react-native'; | ||
5 | +import Immutable, {Map} from 'immutable'; | ||
6 | + | ||
7 | +const { | ||
8 | + AppRegistry, | ||
9 | + StyleSheet, | ||
10 | + View, | ||
11 | + Dimensions, | ||
12 | + TouchableOpacity, | ||
13 | + WebView, | ||
14 | +} = ReactNative; | ||
15 | + | ||
16 | + | ||
17 | +const BODY_TAG_PATTERN = /\<\/ *body\>/; | ||
18 | + | ||
19 | +var script = ` | ||
20 | +;(function() { | ||
21 | +var wrapper = document.createElement("div"); | ||
22 | +wrapper.id = "height-wrapper"; | ||
23 | +while (document.body.firstChild) { | ||
24 | + wrapper.appendChild(document.body.firstChild); | ||
25 | +} | ||
26 | +document.body.appendChild(wrapper); | ||
27 | +var i = 0; | ||
28 | +function updateHeight() { | ||
29 | + document.title = wrapper.clientHeight; | ||
30 | + window.location.hash = ++i; | ||
31 | +} | ||
32 | +updateHeight(); | ||
33 | +window.addEventListener("load", function() { | ||
34 | + updateHeight(); | ||
35 | + setTimeout(updateHeight, 1000); | ||
36 | +}); | ||
37 | +window.addEventListener("resize", updateHeight); | ||
38 | +}()); | ||
39 | +`; | ||
40 | + | ||
41 | + | ||
42 | +const style = ` | ||
43 | +<style> | ||
44 | +body, html, #height-wrapper { | ||
45 | + margin: 0; | ||
46 | + padding: 0; | ||
47 | +} | ||
48 | +#height-wrapper { | ||
49 | + position: absolute; | ||
50 | + top: 0; | ||
51 | + left: 0; | ||
52 | + right: 0; | ||
53 | +} | ||
54 | +</style> | ||
55 | +<script> | ||
56 | +${script} | ||
57 | +</script> | ||
58 | +`; | ||
59 | + | ||
60 | +const codeInject = (html) => html.replace(BODY_TAG_PATTERN, style + "</body>"); | ||
61 | + | ||
62 | +export default class DetailText extends React.Component { | ||
63 | + constructor(props) { | ||
64 | + super(props); | ||
65 | + this.handleNavigationChange = this.handleNavigationChange.bind(this); | ||
66 | + this.state = { | ||
67 | + realContentHeight : 10, | ||
68 | + }; | ||
69 | + } | ||
70 | + | ||
71 | + handleNavigationChange(navState) { | ||
72 | + | ||
73 | + let heightT = parseInt(navState.title, 10) || 0; // turn NaN to 0 | ||
74 | + this.setState({ | ||
75 | + realContentHeight: heightT, | ||
76 | + }); | ||
77 | + } | ||
78 | + | ||
79 | + | ||
80 | + render() { | ||
81 | + let {resource} = this.props; | ||
82 | + let template_name = resource.get('data'); | ||
83 | + let text = template_name.get('text'); | ||
84 | + | ||
85 | + text = '<html><body>' + text + '</body></html>'; | ||
86 | + | ||
87 | + return ( | ||
88 | + <View style={{width: width,height: this.state.realContentHeight}}> | ||
89 | + <WebView style={{width: width,height: this.state.realContentHeight}} | ||
90 | + source= {{html: codeInject(text)}} | ||
91 | + scrollEnabled={false} | ||
92 | + onNavigationStateChange={this.handleNavigationChange} | ||
93 | + > | ||
94 | + </WebView> | ||
95 | + </View> | ||
96 | + ); | ||
97 | + return null; | ||
98 | + } | ||
99 | +}; | ||
100 | + | ||
101 | + | ||
102 | +let {width, height} = Dimensions.get('window'); | ||
103 | + | ||
104 | +let styles = StyleSheet.create({ | ||
105 | + webview_style: { | ||
106 | + backgroundColor: 'red', | ||
107 | + height: 100, | ||
108 | + }, | ||
109 | +}); |
js/guang/components/detail/SingleImage.js
0 → 100644
1 | +'use strict'; | ||
2 | + | ||
3 | +import React from 'react'; | ||
4 | +import ReactNative from 'react-native'; | ||
5 | +import Immutable, {Map} from 'immutable'; | ||
6 | + | ||
7 | +const { | ||
8 | + AppRegistry, | ||
9 | + StyleSheet, | ||
10 | + Text, | ||
11 | + View, | ||
12 | + Image, | ||
13 | + ListView, | ||
14 | + Dimensions, | ||
15 | + TouchableOpacity, | ||
16 | +} = ReactNative; | ||
17 | + | ||
18 | + | ||
19 | +export default class SingleImage extends React.Component { | ||
20 | + constructor(props) { | ||
21 | + super(props); | ||
22 | + this.state = { | ||
23 | + width: Dimensions.get('window').width, | ||
24 | + height: 0, | ||
25 | + }; | ||
26 | + } | ||
27 | + | ||
28 | + shouldComponentUpdate(nextProps){ | ||
29 | + if (Immutable.is(nextProps.resource, this.props.resource && this.state.height != 0)) { | ||
30 | + return false; | ||
31 | + } else { | ||
32 | + return true; | ||
33 | + } | ||
34 | + } | ||
35 | + | ||
36 | + componentDidMount() { | ||
37 | + let {resource} = this.props; | ||
38 | + let template_name = resource.get('data'); | ||
39 | + let src = template_name.get('src'); | ||
40 | + Image.getSize(src, (width, height) => { | ||
41 | + this.setState({width, height}); | ||
42 | + }); | ||
43 | + } | ||
44 | + | ||
45 | + render() { | ||
46 | + let {resource} = this.props; | ||
47 | + let template_name = resource.get('data'); | ||
48 | + let src = template_name.get('src'); | ||
49 | + return ( | ||
50 | + <View style={{width: Dimensions.get('window').width,height: (this.state.height/this.state.width)*Dimensions.get('window').width}}> | ||
51 | + <Image | ||
52 | + source={{uri: src}} | ||
53 | + style={{width: Dimensions.get('window').width,height: (this.state.height/this.state.width)*Dimensions.get('window').width}} | ||
54 | + > | ||
55 | + </Image> | ||
56 | + </View> | ||
57 | + ); | ||
58 | + return null; | ||
59 | + } | ||
60 | +}; | ||
61 | + | ||
62 | + | ||
63 | +let styles = StyleSheet.create({ | ||
64 | + | ||
65 | +}); |
@@ -33,4 +33,8 @@ export default keyMirror({ | @@ -33,4 +33,8 @@ export default keyMirror({ | ||
33 | GET_WEIXIN_PUBLIC_SUCCESS: null, | 33 | GET_WEIXIN_PUBLIC_SUCCESS: null, |
34 | GET_WEIXIN_PUBLIC_FAILURE: null, | 34 | GET_WEIXIN_PUBLIC_FAILURE: null, |
35 | 35 | ||
36 | + PRODUCT_BY_SKNS_REQUEST: null, | ||
37 | + PRODUCT_BY_SKNS_SUCCESS: null, | ||
38 | + PRODUCT_BY_SKNS_FAILURE: null, | ||
39 | + | ||
36 | }); | 40 | }); |
@@ -33,6 +33,10 @@ const { | @@ -33,6 +33,10 @@ const { | ||
33 | GET_WEIXIN_PUBLIC_SUCCESS, | 33 | GET_WEIXIN_PUBLIC_SUCCESS, |
34 | GET_WEIXIN_PUBLIC_FAILURE, | 34 | GET_WEIXIN_PUBLIC_FAILURE, |
35 | 35 | ||
36 | + PRODUCT_BY_SKNS_REQUEST, | ||
37 | + PRODUCT_BY_SKNS_SUCCESS, | ||
38 | + PRODUCT_BY_SKNS_FAILURE, | ||
39 | + | ||
36 | } = require('../../constants/actionTypes').default; | 40 | } = require('../../constants/actionTypes').default; |
37 | 41 | ||
38 | export function setArticleId(id) { | 42 | export function setArticleId(id) { |
@@ -181,6 +185,14 @@ export function getArticleContent(reload = false) { | @@ -181,6 +185,14 @@ export function getArticleContent(reload = false) { | ||
181 | .then(json => { | 185 | .then(json => { |
182 | let payload = parseArticleContent(json); | 186 | let payload = parseArticleContent(json); |
183 | 187 | ||
188 | + payload.map((item, i) => { | ||
189 | + if (item.template_name == 'goods') { | ||
190 | + dispatch(goodsProductBySkns(item, i)); | ||
191 | + } else if (item.template_name == 'goods_group') { | ||
192 | + dispatch(goodsGroupProductBySkns(item, i)); | ||
193 | + } | ||
194 | + }); | ||
195 | + | ||
184 | dispatch(getArticleContentSuccess(payload)); | 196 | dispatch(getArticleContentSuccess(payload)); |
185 | // dispatch(dataExposure(payload.logFloors)); | 197 | // dispatch(dataExposure(payload.logFloors)); |
186 | }) | 198 | }) |
@@ -192,6 +204,8 @@ export function getArticleContent(reload = false) { | @@ -192,6 +204,8 @@ export function getArticleContent(reload = false) { | ||
192 | 204 | ||
193 | function parseArticleContent(json) { | 205 | function parseArticleContent(json) { |
194 | let contents = []; | 206 | let contents = []; |
207 | + let goodsSkns = []; | ||
208 | + let groupGoodsSkns = []; | ||
195 | 209 | ||
196 | json && json.map((item, i) => { | 210 | json && json.map((item, i) => { |
197 | for (let i in item) { | 211 | for (let i in item) { |
@@ -230,6 +244,152 @@ function parseArticleContent(json) { | @@ -230,6 +244,152 @@ function parseArticleContent(json) { | ||
230 | return contents; | 244 | return contents; |
231 | } | 245 | } |
232 | 246 | ||
247 | +/** | ||
248 | + * [获取商品的ICON] | ||
249 | + * @param {[int]} type [类型] | ||
250 | + * @return {[type]} | ||
251 | + */ | ||
252 | +function getProductIcon(type) { | ||
253 | + const icons = { | ||
254 | + 1: 'cloth', | ||
255 | + 3: 'pants', | ||
256 | + 4: 'dress', | ||
257 | + 6: 'shoe', | ||
258 | + 7: 'bag', | ||
259 | + 10: 'lamp', | ||
260 | + 241: 'headset', | ||
261 | + 8: 'watch', | ||
262 | + 360: 'swim-suit', | ||
263 | + 308: 'under' | ||
264 | + }; | ||
265 | + | ||
266 | + return icons[type] || ''; | ||
267 | +} | ||
268 | + | ||
269 | +function productBySknsRequest() { | ||
270 | + return { | ||
271 | + type: PRODUCT_BY_SKNS_REQUEST, | ||
272 | + }; | ||
273 | +} | ||
274 | + | ||
275 | +function productBySknsSuccess(json) { | ||
276 | + return { | ||
277 | + type: PRODUCT_BY_SKNS_SUCCESS, | ||
278 | + payload: json | ||
279 | + }; | ||
280 | +} | ||
281 | + | ||
282 | +function productBySknsFailure(error) { | ||
283 | + return { | ||
284 | + type: PRODUCT_BY_SKNS_FAILURE, | ||
285 | + payload: error | ||
286 | + }; | ||
287 | +} | ||
288 | + | ||
289 | +export function goodsProductBySkns(item, contentIndex) { | ||
290 | + return (dispatch, getState) => { | ||
291 | + let skns = []; | ||
292 | + let productImages = {}; | ||
293 | + // 遍历取得SKN | ||
294 | + item.data.map((item2) => { | ||
295 | + skns.push(item2.id); | ||
296 | + productImages[item2.id] = item2.src; | ||
297 | + }); | ||
298 | + | ||
299 | + if (!skns) { | ||
300 | + return; | ||
301 | + } | ||
302 | + | ||
303 | + let {app, detail} = getState(); | ||
304 | + | ||
305 | + dispatch(productBySknsRequest()); | ||
306 | + return new DetailService(app.host).productInfoBySkns(skns) | ||
307 | + .then(json => { | ||
308 | + let productList = []; | ||
309 | + let result = json.product_list.slice(0, 3); | ||
310 | + result.map((item3, i3) => { | ||
311 | + let src = productImages[item3.product_skn]; | ||
312 | + if (src) { | ||
313 | + item3.tags = []; | ||
314 | + item3.default_images = helper.image(src, 235, 314); | ||
315 | + productList.push(item3); | ||
316 | + } | ||
317 | + | ||
318 | + }); | ||
319 | + dispatch(productBySknsSuccess({ | ||
320 | + productList, | ||
321 | + contentIndex, | ||
322 | + })); | ||
323 | + }) | ||
324 | + .catch(error => { | ||
325 | + dispatch(productBySknsFailure(error)); | ||
326 | + }); | ||
327 | + }; | ||
328 | +} | ||
329 | + | ||
330 | +export function goodsGroupProductBySkns(item, contentIndex) { | ||
331 | + return (dispatch, getState) => { | ||
332 | + let skns = []; | ||
333 | + let productImages = {}; | ||
334 | + | ||
335 | + // 遍历取得SKN | ||
336 | + item.data.map((item2) => { | ||
337 | + item2.list.map((item3) => { | ||
338 | + skns.push(item3.id); | ||
339 | + productImages[item3.id] = item3.src; | ||
340 | + }); | ||
341 | + }); | ||
342 | + | ||
343 | + if (!skns) { | ||
344 | + return; | ||
345 | + } | ||
346 | + | ||
347 | + let {app, detail} = getState(); | ||
348 | + | ||
349 | + dispatch(productBySknsRequest()); | ||
350 | + return new DetailService(app.host).productInfoBySkns(skns) | ||
351 | + .then(json => { | ||
352 | + let products = {}; | ||
353 | + let result = json.product_list; | ||
354 | + result.map((item4) => { | ||
355 | + let src = productImages[item4.product_skn]; | ||
356 | + if (src) { | ||
357 | + item4.tags = []; | ||
358 | + item4.default_images = helper.image(src, 235, 314); | ||
359 | + products[item4.product_skn] = item4; | ||
360 | + } | ||
361 | + | ||
362 | + }); | ||
363 | + | ||
364 | + let productList = [] | ||
365 | + item.data.map((item5) => { | ||
366 | + let good = { | ||
367 | + thumb: item5.cover ? helper.image(item5.cover.cover, 235, 314) : '', | ||
368 | + type: item5.cover ? getProductIcon(item5.cover.maxSortId) : '', | ||
369 | + list: [], | ||
370 | + }; | ||
371 | + | ||
372 | + item5.list.map((item6) => { | ||
373 | + let product = products[item6.id]; | ||
374 | + if (product) { | ||
375 | + good.list.push(product); | ||
376 | + } | ||
377 | + }); | ||
378 | + | ||
379 | + productList.push(good); | ||
380 | + }); | ||
381 | + | ||
382 | + dispatch(productBySknsSuccess({ | ||
383 | + productList, | ||
384 | + contentIndex, | ||
385 | + })); | ||
386 | + }) | ||
387 | + .catch(error => { | ||
388 | + dispatch(productBySknsFailure(error)); | ||
389 | + }); | ||
390 | + }; | ||
391 | +} | ||
392 | + | ||
233 | function getBrandRequest() { | 393 | function getBrandRequest() { |
234 | return { | 394 | return { |
235 | type: GET_BRAND_REQUEST, | 395 | type: GET_BRAND_REQUEST, |
@@ -30,6 +30,8 @@ const { | @@ -30,6 +30,8 @@ const { | ||
30 | GET_WEIXIN_PUBLIC_SUCCESS, | 30 | GET_WEIXIN_PUBLIC_SUCCESS, |
31 | GET_WEIXIN_PUBLIC_FAILURE, | 31 | GET_WEIXIN_PUBLIC_FAILURE, |
32 | 32 | ||
33 | + PRODUCT_BY_SKNS_SUCCESS, | ||
34 | + | ||
33 | } = require('../../constants/actionTypes').default; | 35 | } = require('../../constants/actionTypes').default; |
34 | 36 | ||
35 | const initialState = new InitialState; | 37 | const initialState = new InitialState; |
@@ -135,6 +137,14 @@ export default function detailReducer(state=initialState, action) { | @@ -135,6 +137,14 @@ export default function detailReducer(state=initialState, action) { | ||
135 | return state.setIn(['weixin', 'isFetching'], false) | 137 | return state.setIn(['weixin', 'isFetching'], false) |
136 | .setIn(['weixin', 'error'], action.payload); | 138 | .setIn(['weixin', 'error'], action.payload); |
137 | } | 139 | } |
140 | + | ||
141 | + case PRODUCT_BY_SKNS_SUCCESS: { | ||
142 | + let { | ||
143 | + productList, | ||
144 | + contentIndex | ||
145 | + } = action.payload; | ||
146 | + return state.setIn(['content', 'data', contentIndex, 'productList'], Immutable.fromJS(productList)); | ||
147 | + } | ||
138 | } | 148 | } |
139 | 149 | ||
140 | return state; | 150 | return state; |
@@ -112,4 +112,22 @@ export default class DetailService { | @@ -112,4 +112,22 @@ export default class DetailService { | ||
112 | }); | 112 | }); |
113 | } | 113 | } |
114 | 114 | ||
115 | + async productInfoBySkns(skns) { | ||
116 | + return await this.api.get({ | ||
117 | + url: '', | ||
118 | + body: { | ||
119 | + method: 'app.search.li', | ||
120 | + query: skns.join(' '), | ||
121 | + limit: skns.length, | ||
122 | + order: 's_t_desc', | ||
123 | + } | ||
124 | + }) | ||
125 | + .then((json) => { | ||
126 | + return json; | ||
127 | + }) | ||
128 | + .catch((error) => { | ||
129 | + throw(error); | ||
130 | + }); | ||
131 | + } | ||
132 | + | ||
115 | } | 133 | } |
-
Please register or login to post a comment