Authored by 张丽霞

merge

@@ -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}/>
  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 +});
  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 }