Authored by 于良

Merge branch 'classify' into guang

... ... @@ -123,7 +123,6 @@ export default function brandStoreReducer(state=initialState, action) {
.set('is_show_shop_name', is_show_shop_name)
.set('shop_domain', shop_domain)
.set('shops_id', shops_id)
.set('is_addFav',false);
let nextState = state.set('info', info);
return nextState;
}
... ...
... ... @@ -41,21 +41,17 @@ export default class BannerReourceList extends React.Component {
<TouchableOpacity activeOpacity={0.5} onPress={() => {
this.props.onPressSlideItem && this.props.onPressSlideItem(rowData, rowID);
}}>
<View style={styles.row}>
<View style={styles.thumbnailV}>
<Image
source={{uri: newSrc}}
style={styles.thumbnail}
resizeMode={'contain'}
>
<View style={styles.textV}>
<Text style={styles.text} numberOfLines={1}>
{rowData.name}
</Text>
</View>
</Image>
</View>
<View style={styles.thumbnailV}>
<Image
source={{uri: newSrc}}
style={styles.thumbnail}
resizeMode={'contain'}
></Image>
<View style={styles.textV}>
<Text style={styles.text} numberOfLines={1}>
{rowData.name}
</Text>
</View>
</View>
</TouchableOpacity>
);
... ... @@ -113,14 +109,9 @@ let styles = StyleSheet.create({
width:Dimensions.get('window').width,
backgroundColor: 'white',
},
row: {
marginLeft: 10,
width: itemWidth,
height: itemWidth,
backgroundColor: 'white',
},
textV: {
marginTop: itemHeight - 20,
position: 'absolute',
top: itemHeight - 20,
width: itemWidth,
alignItems: 'center',
height: 20,
... ... @@ -140,6 +131,7 @@ let styles = StyleSheet.create({
fontWeight: 'bold',
},
thumbnailV: {
marginLeft: 10,
width: itemWidth,
height: itemHeight,
backgroundColor: 'white',
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
const {
View,
Image,
Text,
TouchableOpacity,
Dimensions,
StyleSheet,
} = ReactNative;
export default class GPTags extends React.Component {
constructor(props) {
super (props);
}
render() {
let {title, isLimit} = this.props;
let leftWidth = tagMaxWidth;
if (isLimit) {
leftWidth = tagMaxWidth - limitWidth - 2;
}
let textMaxWidth = leftWidth - iconWidth - 5 * 2;
return (
<View style={styles.container}>
<View style={[styles.leftContainer, {width: leftWidth}]}>
<Image
style={styles.icon}
source={require('../../images/tag/globalpurchase_fly_smallicon.png')}
/>
<Text numberOfLines={1} style={[styles.text, {maxWidth: textMaxWidth}]}>{title}</Text>
</View>
{isLimit ? <Image
style={styles.limit}
source={require('../../images/tag/gp_tip_xl_product.png')}
/> : null}
</View>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let tagMaxWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO);
let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let iconWidth = Math.ceil(10 * DEVICE_WIDTH_RATIO);
let limitWidth = Math.ceil(30 * DEVICE_WIDTH_RATIO);
let limitHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
width: width,
height: tagHeight,
},
leftContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#462e3d',
height: tagHeight,
},
icon: {
marginLeft: 5,
width: iconWidth,
height: iconWidth,
resizeMode: 'contain',
},
text: {
marginLeft: 5,
marginRight: 5,
color: 'white',
fontSize: 10,
fontFamily: 'STHeitiSC-Light',
},
limit: {
marginLeft: 2,
width: limitWidth,
height: limitHeight,
resizeMode: 'contain',
},
});
... ... @@ -13,7 +13,7 @@ import ReactNative, {
import SlicedImage from '../../../common/components/SlicedImage';
import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator';
import ProductListCell from './ProductListCell';
import ProductListCell from '../../../common/components/ListCell/ProductListCell';
import ProductFilter from './ProductFilter';
import ProductShopCell from './ProductShopCell';
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
} from 'react-native';
import SlicedImage from '../../../common/components/SlicedImage';
import Tags from './Tags';
import GPTags from './GPTags';
export default class Search extends Component {
constructor(props) {
super(props);
this._renderTags = this._renderTags.bind(this);
this._renderImages = this._renderImages.bind(this);
this._renderPrice = this._renderPrice.bind(this);
}
_renderTags() {
let {data, sourceType} = this.props;
let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品
let tags = data.get('tags'); // 商品标签
// 数据源是全球购
if (sourceType == 1) {
if (isGlobalProduct) {
} else {
tags = ['is_in_stock', ...tags];
}
}
let countryName = isGlobalProduct && data.get('country_name'); // 全球购国家名称
if (isGlobalProduct) {
return <GPTags title={countryName} limit={showGPLimitTag}/>;
} else {
return <Tags items={tags}/>;
}
}
_renderImages() {
let {data, sourceType} = this.props;
let url = data.get('default_images').replace('{width}', rowWidth).replace('{height}', imageHeight); // 商品缩略图
url = SlicedImage.getSlicedUrl(data.get('default_images'), 290, 386, 2);
let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品
let showGPLimitTag = isGlobalProduct && data.get('is_limited') && data.get('is_limited') == 'Y'; // 全球购限量商品
let showGPSoldOut = isGlobalProduct && data.get('is_stock') && data.get('is_stock') == 'Y'; // 全球购售罄
let showAlmostSoldOut = !isGlobalProduct && data.get('tags', []).indexOf('is_soon_sold_out') !== -1; // 非全球购的即将售罄
let showSoldOut = sourceType == 2 && data.get('storage_num') && data.get('storage_num') == 0; // 数据源是奥莱才显示
return (
<View style={styles.imageContainer}>
<Image style={styles.image} source={{uri: url}}>
{showAlmostSoldOut ? <Image style={styles.almostSoldOutImage} source={require('../../images/tag/tip_jjsq.png')}/> : null}
{showSoldOut ? <Image style={styles.soldOutImage} source={require('../../images/tag/outlet_sellout_bg.png')}/> : null}
{showGPSoldOut ? <Image style={styles.gpSoldOutImage} source={require('../../images/tag/gp_tip_SQ.png')}/> : null}
</Image>
</View>
);
}
_renderPrice() {
let {data, sourceType} = this.props;
let isGlobalProduct = data.get('is_global') && data.get('is_global') == 'Y'; // 是否全球购商品
let salePrice = 0; // 售卖价
let originPrice = 0; // 原价
let salePriceStr = ''; // 拼接的售卖价
let originPriceStr = ''; // 拼接的原价
let showOriginPrice = true; // 是否显示原价
let salePriceColor = '#d0021b'; // 不显示原价时,售卖价颜色
if (isGlobalProduct) {
salePrice = parseFloat(data.get('final_price'));
originPrice = parseFloat(data.get('orign_price'));
salePriceStr = data.get('formart_final_price');
originPriceStr = data.get('formart_orign_price');
} else {
salePrice = parseFloat(data.get('sales_price'));
originPrice = parseFloat(data.get('market_price'));
salePriceStr = '¥' + salePrice.toFixed(2);
originPriceStr = '¥' + originPrice.toFixed(2);
}
if (!originPrice || (salePrice == originPrice)) {
showOriginPrice = false;
salePriceColor = '#444444';
}
if (showOriginPrice) {
return (
<View style={styles.priceContainer}>
<Text style={[styles.nowPrice, {color: salePriceColor}]} numberOfLines={1}>{salePriceStr}</Text>
<View style={styles.oldPriceContainer}>
<Text style={styles.oldPrice} numberOfLines={1}>{originPriceStr}</Text>
<View style={styles.deleteLine}/>
</View>
</View>
);
} else {
return (
<View style={styles.priceContainer}>
<Text style={[styles.nowPrice, {color: salePriceColor}]} numberOfLines={1}>{salePriceStr}</Text>
</View>
);
}
}
render() {
let {data, sourceType, rowID, style} = this.props;
let name = data.get('product_name') ? data.get('product_name') : '';
return (
<TouchableOpacity
style={[styles.container, style]}
activeOpacity={1}
onPress={() => {
this.props.onPressProduct && this.props.onPressProduct(data, rowID);
}}
>
<View>
{this._renderTags()}
{this._renderImages()}
<View style={styles.nameContainer}>
<Text style={styles.name} numberOfLines={2}>{name}</Text>
</View>
{this._renderPrice()}
</View>
</TouchableOpacity>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let rowWidth = Math.ceil(137.5 * DEVICE_WIDTH_RATIO);
let rowHeight = Math.ceil(254 * DEVICE_WIDTH_RATIO);
let rowMarginTop = Math.ceil(10 * DEVICE_WIDTH_RATIO);
const IMAGE_WIDTH = 145;
const IMAGE_HEIGHT = 193;
const IMAGE_RATIO = IMAGE_HEIGHT / IMAGE_WIDTH;
let imageTop = 14 * DEVICE_WIDTH_RATIO;
let imageHeight = rowWidth * IMAGE_RATIO;
let almostSoldOutImageHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let almostSoldOutImageTop = imageHeight - almostSoldOutImageHeight;
let nameMarginTop = Math.ceil(7 * DEVICE_WIDTH_RATIO);
let nameHeight = Math.ceil(36 * DEVICE_WIDTH_RATIO);
let gpSoldOutImageHeight = Math.ceil(25 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
width: rowWidth,
height: rowHeight,
marginTop: rowMarginTop,
},
rowContainer: {
width: rowWidth,
height: rowHeight,
},
imageContainer: {
width: rowWidth,
height: imageHeight,
backgroundColor: '#f0f0f0',
},
image: {
width: rowWidth,
height: imageHeight,
backgroundColor: '#f0f0f0',
},
soldOutImage: {
position: 'absolute',
top: 0,
left: 0,
width: rowWidth,
height: imageHeight,
},
almostSoldOutImage: {
top: almostSoldOutImageTop,
width: rowWidth,
height: almostSoldOutImageHeight,
backgroundColor: '#ff9e0d',
},
nameContainer: {
// justifyContent: 'center',
marginTop: nameMarginTop,
width: rowWidth,
height: nameHeight,
},
name: {
fontFamily: 'STHeitiSC-Light',
fontSize: 12,
color: '#444444',
},
priceContainer: {
flexDirection: 'row',
},
nowPrice: {
fontSize: 12,
color: '#d0021b',
},
oldPriceContainer: {
flexDirection: 'row',
marginLeft: 5,
},
oldPrice: {
fontSize: 12,
color: '#b0b0b0',
height: 16,
},
deleteLine: {
position: 'absolute',
top: (16 / 2) - 0.8,
left: 0,
right: 0,
height: 1,
backgroundColor: '#b0b0b0',
},
gpSoldOutImage: {
position: 'absolute',
top: 5,
right: 5,
width: gpSoldOutImageHeight,
height: gpSoldOutImageHeight,
},
});
'use strict';
import React from 'react';
import ReactNative from 'react-native';
const {
View,
Image,
Text,
ListView,
Dimensions,
StyleSheet,
} = ReactNative;
export default class Tags extends React.Component {
constructor(props) {
super (props);
this.config = {
is_discount: {
image: require('../../images/tag/tip_sale.png'),
width: 30,
}, // YH_ProductTagTypeSale
resale: {
image: require('../../images/tag/tip_zdz.png'),
width: 45,
}, // YH_ProductTagTypeReSale
'mid-year': {
image: require('../../images/tag/tip_nzrc.png'),
width: 45,
}, // YH_ProductTagTypeSaleMiddle
'year-end': {
image: require('../../images/tag/tip_nzdc.png'),
width: 45,
}, // YH_ProductTagTypeSaleHot
is_new: {
image: require('../../images/tag/tip_new.png'),
width: 30,
}, // YH_ProductTagTypeNew
is_yohood: {
image: require('../../images/tag/tip_xpj.png'),
width: 45,
}, // YH_ProductTagTypeYohood
is_limited: {
image: require('../../images/tag/tip_xl_product.png'),
width: 30,
}, // YH_ProductTagTypeLimited
is_in_stock: {
image: require('../../images/tag/tip_gnzf.png'),
width: 45,
}, // YH_ProductTagTypeInland
is_deposit_advance: {
image: require('../../images/tag/tip_advance.png'),
width: 30,
}, // YH_ProductTagTypeDeposit
default: {
image: '',
width: 45,
},
};
this._renderRow = this._renderRow.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 != r2,
});
}
_renderRow(rowData, sectionID, rowID) {
let item = this.config[rowData];
if (!item) {
return null;
}
let width = Math.ceil(item.width * DEVICE_WIDTH_RATIO);
let marginLeft = rowID == 0 ? 0 : 2;
let iconStyle = {width, height: tagHeight, marginLeft};
return (
<Image style={[styles.icon, iconStyle]} source={item.image}/>
);
}
render() {
let {style, items} = this.props;
// let tags = ['is_discount', 'resale', ];
return (
<View style={[styles.container]}>
<ListView
style={[styles.container]}
contentContainerStyle={[styles.contentContainer]}
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(items.toArray())}
renderRow={this._renderRow}
scrollEnabled={false}
scrollsToTop={false}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let tagHeight = Math.ceil(14 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
},
contentContainer: {
height: tagHeight,
},
icon: {
resizeMode: 'contain',
},
});